From e7193d1fb16edc79e9cc3d8adcfb71caecd8463b Mon Sep 17 00:00:00 2001 From: Daniel Kirschten Date: Mon, 3 Jun 2019 15:28:27 +0200 Subject: [PATCH] Improved rendering: -Splitted LogicUICanvas and LogicUIRenderer -The ViewModel hierarchy supports redraw listeners --- .../net/mograsim/logic/ui/LogicUICanvas.java | 72 +------------------ .../mograsim/logic/ui/LogicUIRenderer.java | 44 ++++++++++++ .../mograsim/logic/ui/model/ViewModel.java | 38 +++++++--- .../ui/model/components/GUIBitDisplay.java | 2 +- .../ui/model/components/GUIComponent.java | 49 ++++++++----- .../ui/model/components/GUIManualSwitch.java | 2 +- .../logic/ui/model/wires/GUIWire.java | 36 +++++++--- .../mograsim/logic/ui/model/wires/Pin.java | 19 +++-- .../logic/ui/model/wires/WireCrossPoint.java | 28 ++++++-- 9 files changed, 173 insertions(+), 117 deletions(-) create mode 100644 net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUIRenderer.java diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUICanvas.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUICanvas.java index 3a080973..08dc4eb0 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUICanvas.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUICanvas.java @@ -1,19 +1,14 @@ package net.mograsim.logic.ui; -import java.util.function.Consumer; - import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; -import net.haspamelodica.swt.helper.gcs.GeneralGC; import net.haspamelodica.swt.helper.swtobjectwrappers.Point; import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas; import net.mograsim.logic.ui.model.ViewModel; import net.mograsim.logic.ui.model.components.GUIComponent; -import net.mograsim.logic.ui.model.wires.GUIWire; -import net.mograsim.logic.ui.model.wires.Pin; /** * Simulation visualizer canvas. @@ -22,8 +17,6 @@ import net.mograsim.logic.ui.model.wires.Pin; */ public class LogicUICanvas extends ZoomableCanvas { - private static final boolean DRAW_PINS = false; - private final ViewModel model; public LogicUICanvas(Composite parent, int style, ViewModel model) @@ -32,72 +25,13 @@ public class LogicUICanvas extends ZoomableCanvas this.model = model; - Consumer redrawConsumer = o -> redrawThreadsafe(); - Consumer pinAddedListener = p -> - { - p.addPinMovedListener(redrawConsumer); - redrawThreadsafe(); - }; - Consumer pinRemovedListener = p -> - { - p.removePinMovedListener(redrawConsumer); - redrawThreadsafe(); - }; - Consumer componentAddedListener = c -> - { - c.addComponentLookChangedListener(redrawConsumer); - c.addComponentMovedListener(redrawConsumer); - c.addPinAddedListener(pinAddedListener); - c.addPinRemovedListener(pinRemovedListener); - redrawThreadsafe(); - }; - model.addComponentAddedListener(componentAddedListener); - model.getComponents().forEach(componentAddedListener); - model.addComponentRemovedListener(c -> - { - c.removeComponentLookChangedListener(redrawConsumer); - c.removeComponentMovedListener(redrawConsumer); - c.removePinAddedListener(pinAddedListener); - c.removePinRemovedListener(pinRemovedListener); - redrawThreadsafe(); - }); - Consumer wireAddedListener = w -> - { - w.addWireLookChangedListener(redrawConsumer); - redrawThreadsafe(); - }; - model.addWireAddedListener(wireAddedListener); - model.getWires().forEach(wireAddedListener); - model.addWireRemovedListener(w -> - { - w.removeWireLookChangedListener(redrawConsumer); - redrawThreadsafe(); - }); + LogicUIRenderer renderer = new LogicUIRenderer(model); + addZoomedRenderer(gc -> renderer.render(gc, new Rectangle(offX, offY, gW / zoom, gH / zoom))); + model.addRedrawListener(this::redrawThreadsafe); - addZoomedRenderer(gc -> - { - gc.setLineWidth(.5); - model.getWires().forEach(w -> w.render(gc)); - Rectangle visibleRegion = new Rectangle(offX, offY, gW / zoom, gH / zoom); - model.getComponents().forEach(c -> drawComponent(gc, c, visibleRegion)); - }); addListener(SWT.MouseDown, this::mouseDown); } - private void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion) - { - component.render(gc, visibleRegion); - if (DRAW_PINS) - { - gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_DARK_CYAN)); - for (Pin p : component.getPins()) - { - Point pos = p.getPos(); - gc.fillOval(pos.x - 1, pos.y - 1, 2, 2); - } - } - } - private void mouseDown(Event e) { if (e.button == 1) diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUIRenderer.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUIRenderer.java new file mode 100644 index 00000000..ce204599 --- /dev/null +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/LogicUIRenderer.java @@ -0,0 +1,44 @@ +package net.mograsim.logic.ui; + +import org.eclipse.swt.SWT; + +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; +import net.mograsim.logic.ui.model.ViewModel; +import net.mograsim.logic.ui.model.components.GUIComponent; +import net.mograsim.logic.ui.model.wires.Pin; + +public class LogicUIRenderer +{ + private static final boolean DRAW_PINS = false; + + private final ViewModel model; + + public LogicUIRenderer(ViewModel model) + { + this.model = model; + } + + public void render(GeneralGC gc, Rectangle visibleRegion) + { + gc.setLineWidth(.5); + model.getWires().forEach(w -> w.render(gc)); + model.getComponents().forEach(c -> drawComponent(gc, c, visibleRegion)); + } + + private static void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion) + { + component.render(gc, visibleRegion); + if (DRAW_PINS) + { + gc.setBackground(gc.getDevice().getSystemColor(SWT.COLOR_DARK_CYAN)); + for (Pin p : component.getPins()) + { + Point pos = p.getPos(); + gc.fillOval(pos.x - 1, pos.y - 1, 2, 2); + } + } + } + +} \ No newline at end of file diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/ViewModel.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/ViewModel.java index 717ee13a..7f9b113f 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/ViewModel.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/ViewModel.java @@ -19,6 +19,9 @@ public class ViewModel private final List> componentRemovedListeners; private final List> wireAddedListeners; private final List> wireRemovedListeners; + private final List redrawListeners; + + private final Runnable redrawListenerForSubcomponents; public ViewModel() { @@ -31,6 +34,9 @@ public class ViewModel componentRemovedListeners = new ArrayList<>(); wireAddedListeners = new ArrayList<>(); wireRemovedListeners = new ArrayList<>(); + redrawListeners = new ArrayList<>(); + + redrawListenerForSubcomponents = this::callRedrawListeners; } /** @@ -43,6 +49,8 @@ public class ViewModel throw new IllegalStateException("Don't add the same component twice!"); components.add(component); callComponentAddedListeners(component); + component.addRedrawListener(redrawListenerForSubcomponents); + callRedrawListeners(); } /** @@ -55,6 +63,8 @@ public class ViewModel throw new IllegalStateException("Don't remove the same component twice!"); components.remove(component); callComponentRemovedListeners(component); + component.removeRedrawListener(redrawListenerForSubcomponents); + callRedrawListeners(); } /** @@ -67,6 +77,8 @@ public class ViewModel throw new IllegalStateException("Don't add the same wire twice!"); wires.add(wire); callWireAddedListeners(wire); + wire.addRedrawListener(redrawListenerForSubcomponents); + callRedrawListeners(); } /** @@ -79,6 +91,8 @@ public class ViewModel throw new IllegalStateException("Don't remove the same wire twice!"); wires.remove(wire); callWireRemovedListeners(wire); + wire.removeRedrawListener(redrawListenerForSubcomponents); + callRedrawListeners(); } public List getComponents() @@ -91,20 +105,28 @@ public class ViewModel return wiresUnmodifiable; } +// public void requestRedraw() +// { +// callRedrawListeners(); +// } + // @formatter:off - public void addComponentAddedListener (Consumer listener){componentAddedListeners .add (listener);} - public void addComponentRemovedListener (Consumer listener){componentRemovedListeners.add (listener);} - public void addWireAddedListener (Consumer listener){wireAddedListeners .add (listener);} - public void addWireRemovedListener (Consumer listener){wireRemovedListeners .add (listener);} + public void addComponentAddedListener (Consumer listener) {componentAddedListeners .add (listener);} + public void addComponentRemovedListener (Consumer listener) {componentRemovedListeners.add (listener);} + public void addWireAddedListener (Consumer listener) {wireAddedListeners .add (listener);} + public void addWireRemovedListener (Consumer listener) {wireRemovedListeners .add (listener);} + public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);} - public void removeComponentAddedListener (Consumer listener){componentAddedListeners .remove(listener);} - public void removeComponentRemovedListener(Consumer listener){componentRemovedListeners.remove(listener);} - public void removeWireAddedListener (Consumer listener){wireAddedListeners .remove(listener);} - public void removeWireRemovedListener (Consumer listener){wireRemovedListeners .remove(listener);} + public void removeComponentAddedListener (Consumer listener) {componentAddedListeners .remove(listener);} + public void removeComponentRemovedListener(Consumer listener) {componentRemovedListeners.remove(listener);} + public void removeWireAddedListener (Consumer listener) {wireAddedListeners .remove(listener);} + public void removeWireRemovedListener (Consumer listener) {wireRemovedListeners .remove(listener);} + public void removeRedrawListener (Runnable listener) {redrawListeners .remove(listener);} private void callComponentAddedListeners (GUIComponent c) {componentAddedListeners .forEach(l -> l.accept(c));} private void callComponentRemovedListeners(GUIComponent c) {componentRemovedListeners.forEach(l -> l.accept(c));} private void callWireAddedListeners (GUIWire w ) {wireAddedListeners .forEach(l -> l.accept(w));} private void callWireRemovedListeners (GUIWire w ) {wireRemovedListeners .forEach(l -> l.accept(w));} + private void callRedrawListeners ( ) {redrawListeners .forEach(l -> l.run( ));} // @formatter:on } \ No newline at end of file diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIBitDisplay.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIBitDisplay.java index 4a75f541..abaec56b 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIBitDisplay.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIBitDisplay.java @@ -25,7 +25,7 @@ public class GUIBitDisplay extends GUIComponent public GUIBitDisplay(ViewModel model) { super(model); - logicObs = (i) -> callComponentLookChangedListeners(); + logicObs = (i) -> requestRedraw(); setSize(width, height); addPin(this.inputPin = new Pin(this, 1, 0, height / 2)); diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIComponent.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIComponent.java index 9cea86a6..ca21622a 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIComponent.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIComponent.java @@ -17,10 +17,12 @@ public abstract class GUIComponent private final List pins; protected final List pinsUnmodifiable; - private final List> componentLookChangedListeners; private final List> componentMovedListeners; private final List> pinAddedListeners; private final List> pinRemovedListeners; + private final List redrawListeners; + + private final Runnable redrawListenerForSubcomponents; public GUIComponent(ViewModel model) { @@ -29,10 +31,12 @@ public abstract class GUIComponent this.pins = new ArrayList<>(); this.pinsUnmodifiable = Collections.unmodifiableList(pins); - this.componentLookChangedListeners = new ArrayList<>(); this.componentMovedListeners = new ArrayList<>(); this.pinAddedListeners = new ArrayList<>(); this.pinRemovedListeners = new ArrayList<>(); + this.redrawListeners = new ArrayList<>(); + + redrawListenerForSubcomponents = this::callRedrawListeners; model.componentCreated(this); } @@ -77,43 +81,52 @@ public abstract class GUIComponent } // @formatter:off - public void addComponentLookChangedListener (Consumer listener) {componentLookChangedListeners.add (listener);} - public void addComponentMovedListener (Consumer listener) {componentMovedListeners .add (listener);} - public void addPinAddedListener (Consumer listener) {pinAddedListeners .add (listener);} - public void addPinRemovedListener (Consumer listener) {pinRemovedListeners .add (listener);} - - public void removeComponentLookChangedListener(Consumer listener) {componentLookChangedListeners.remove(listener);} - public void removeComponentMovedListener (Consumer listener) {componentMovedListeners .remove(listener);} - public void removePinAddedListener (Consumer listener) {pinAddedListeners .remove(listener);} - public void removePinRemovedListener (Consumer listener) {pinRemovedListeners .remove(listener);} - - protected void callComponentLookChangedListeners( ) {componentLookChangedListeners.forEach(l -> l.accept(this));} - private void callComponentMovedListeners ( ) {componentMovedListeners .forEach(l -> l.accept(this));} - private void callPinAddedListeners (Pin p) {pinAddedListeners .forEach(l -> l.accept(p ));} - private void callPinRemovedListeners (Pin p) {pinRemovedListeners .forEach(l -> l.accept(p ));} - // @form atter:on + public void addComponentMovedListener (Consumer listener) {componentMovedListeners.add (listener);} + public void addPinAddedListener (Consumer listener) {pinAddedListeners .add (listener);} + public void addPinRemovedListener (Consumer listener) {pinRemovedListeners .add (listener);} + public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);} + + public void removeComponentMovedListener(Consumer listener) {componentMovedListeners .remove(listener);} + public void removePinAddedListener (Consumer listener) {pinAddedListeners .remove(listener);} + public void removePinRemovedListener (Consumer listener) {pinRemovedListeners .remove(listener);} + public void removeRedrawListener (Runnable listener) {redrawListeners .remove(listener);} + + private void callComponentMovedListeners( ) {componentMovedListeners.forEach(l -> l.accept(this));} + private void callPinAddedListeners (Pin p) {pinAddedListeners .forEach(l -> l.accept(p ));} + private void callPinRemovedListeners (Pin p) {pinRemovedListeners .forEach(l -> l.accept(p ));} + private void callRedrawListeners ( ) {redrawListeners .forEach(l -> l.run( ));} + // @formatter:on /** * Render this component to the given gc. */ public abstract void render(GeneralGC gc, Rectangle visibleRegion); + protected void requestRedraw() + { + callRedrawListeners(); + } + protected void setSize(double width, double height) { bounds.width = width; bounds.height = height; - callComponentLookChangedListeners(); + callRedrawListeners(); } protected void addPin(Pin pin) { pins.add(pin); callPinAddedListeners(pin); + pin.addRedrawListener(redrawListenerForSubcomponents); + callRedrawListeners(); } protected void removePin(Pin pin) { pins.remove(pin); callPinRemovedListeners(pin); + pin.removeRedrawListener(redrawListenerForSubcomponents); + callRedrawListeners(); } } \ No newline at end of file diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIManualSwitch.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIManualSwitch.java index 265efa3c..dbeabd2c 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIManualSwitch.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIManualSwitch.java @@ -27,7 +27,7 @@ public class GUIManualSwitch extends GUIComponent public GUIManualSwitch(ViewModel model) { super(model); - logicObs = (i) -> callComponentLookChangedListeners(); + logicObs = (i) -> requestRedraw(); setSize(width, height); addPin(this.outputPin = new Pin(this, 1, width, height / 2)); diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/GUIWire.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/GUIWire.java index c6c9432d..50871fe5 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/GUIWire.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/GUIWire.java @@ -2,14 +2,15 @@ package net.mograsim.logic.ui.model.wires; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; -import net.mograsim.logic.ui.ColorHelper; -import net.mograsim.logic.ui.model.ViewModel; import net.haspamelodica.swt.helper.gcs.GeneralGC; import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.mograsim.logic.core.LogicObservable; +import net.mograsim.logic.core.LogicObserver; import net.mograsim.logic.core.types.BitVectorFormatter; import net.mograsim.logic.core.wires.Wire.ReadEnd; +import net.mograsim.logic.ui.ColorHelper; +import net.mograsim.logic.ui.model.ViewModel; public class GUIWire { @@ -19,12 +20,14 @@ public class GUIWire private Pin pin2; private double[] path; - private final List> wireLookChangedListeners; + private final List redrawListeners; + private final LogicObserver logicObs; private ReadEnd end; public GUIWire(ViewModel model, Pin pin1, Pin pin2, Point... path) { + logicObs = (i) -> callRedrawListeners(); this.model = model; this.logicWidth = pin1.logicWidth; if (pin2.logicWidth != pin1.logicWidth) @@ -39,7 +42,7 @@ public class GUIWire this.pin1 = pin1; this.pin2 = pin2; - wireLookChangedListeners = new ArrayList<>(); + redrawListeners = new ArrayList<>(); pin1.addPinMovedListener(p -> pin1Moved()); pin2.addPinMovedListener(p -> pin2Moved()); @@ -54,6 +57,7 @@ public class GUIWire Point pos = pin1.getPos(); this.path[0] = pos.x; this.path[1] = pos.y; + callRedrawListeners(); } private void pin2Moved() @@ -61,6 +65,7 @@ public class GUIWire Point pos = pin2.getPos(); this.path[this.path.length - 2] = pos.x; this.path[this.path.length - 1] = pos.y; + callRedrawListeners(); } public void destroy() @@ -75,8 +80,21 @@ public class GUIWire public void setLogicModelBinding(ReadEnd end) { + deregisterLogicObs(this.end); this.end = end; - end.registerObserver((i) -> callWireLookChangedListeners()); + registerLogicObs(end); + } + + private void registerLogicObs(LogicObservable observable) + { + if (observable != null) + observable.registerObserver(logicObs); + } + + private void deregisterLogicObs(LogicObservable observable) + { + if (observable != null) + observable.deregisterObserver(logicObs); } public Pin getPin1() @@ -90,11 +108,11 @@ public class GUIWire } // @formatter:off - public void addWireLookChangedListener (Consumer listener) {wireLookChangedListeners.add (listener);} + public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);} - public void removeWireLookChangedListener(Consumer listener) {wireLookChangedListeners.remove(listener);} + public void removeRedrawListener(Runnable listener) {redrawListeners .remove(listener);} - private void callWireLookChangedListeners() {wireLookChangedListeners.forEach(l -> l.accept(this));} + private void callRedrawListeners() {redrawListeners.forEach(l -> l.run());} // @formatter:on } \ No newline at end of file diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/Pin.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/Pin.java index 51635836..8c0333a4 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/Pin.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/Pin.java @@ -18,6 +18,7 @@ public class Pin protected double relY; private final List> pinMovedListeners; + private final List redrawListeners; public Pin(GUIComponent component, int logicWidth, double relX, double relY) { @@ -27,6 +28,7 @@ public class Pin this.relY = relY; this.pinMovedListeners = new ArrayList<>(); + this.redrawListeners = new ArrayList<>(); component.addComponentMovedListener(c -> callPinMovedListeners()); } @@ -52,18 +54,23 @@ public class Pin return new Point(relX + componentBounds.x, relY + componentBounds.y); } + protected void setRelPos(double relX, double relY) + { + this.relX = relX; + this.relY = relY; + callPinMovedListeners(); + callRedrawListeners(); + } + // @formatter:off public void addPinMovedListener (Consumer listener){pinMovedListeners.add (listener);} + public void addRedrawListener (Runnable listener){redrawListeners .add (listener);} public void removePinMovedListener(Consumer listener){pinMovedListeners.remove(listener);} + public void removeRedrawListener (Runnable listener){redrawListeners .remove(listener);} private void callPinMovedListeners() {pinMovedListeners.forEach(l -> l.accept(this));} + private void callRedrawListeners () {redrawListeners .forEach(l -> l.run ( ));} // @formatter:on - protected void setRelPos(double relX, double relY) - { - this.relX = relX; - this.relY = relY; - callPinMovedListeners(); - } } \ No newline at end of file diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/WireCrossPoint.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/WireCrossPoint.java index 927e4e50..46262808 100644 --- a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/WireCrossPoint.java +++ b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/WireCrossPoint.java @@ -1,23 +1,28 @@ package net.mograsim.logic.ui.model.wires; -import net.mograsim.logic.ui.ColorHelper; -import net.mograsim.logic.ui.model.ViewModel; -import net.mograsim.logic.ui.model.components.GUIComponent; import net.haspamelodica.swt.helper.gcs.GeneralGC; import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; +import net.mograsim.logic.core.LogicObservable; +import net.mograsim.logic.core.LogicObserver; import net.mograsim.logic.core.types.BitVectorFormatter; import net.mograsim.logic.core.wires.Wire.ReadEnd; +import net.mograsim.logic.ui.ColorHelper; +import net.mograsim.logic.ui.model.ViewModel; +import net.mograsim.logic.ui.model.components.GUIComponent; public class WireCrossPoint extends GUIComponent { private final Pin pin; + private final int logicWidth; + private final LogicObserver logicObs; private ReadEnd end; - private final int logicWidth; public WireCrossPoint(ViewModel model, int logicWidth) { super(model); + logicObs = (i) -> requestRedraw(); + this.logicWidth = logicWidth; setSize(0, 0); addPin(this.pin = new Pin(this, logicWidth, 0, 0)); @@ -33,8 +38,21 @@ public class WireCrossPoint extends GUIComponent public void setLogicModelBinding(ReadEnd end) { + deregisterLogicObs(this.end); this.end = end; - end.registerObserver((i) -> callComponentLookChangedListeners()); + registerLogicObs(end); + } + + private void registerLogicObs(LogicObservable observable) + { + if (observable != null) + observable.registerObserver(logicObs); + } + + private void deregisterLogicObs(LogicObservable observable) + { + if (observable != null) + observable.deregisterObserver(logicObs); } public int getLogicWidth() -- 2.17.1