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.
*/
public class LogicUICanvas extends ZoomableCanvas
{
- private static final boolean DRAW_PINS = false;
-
private final ViewModel model;
public LogicUICanvas(Composite parent, int style, ViewModel model)
this.model = model;
- Consumer<Object> redrawConsumer = o -> redrawThreadsafe();
- Consumer<Pin> pinAddedListener = p ->
- {
- p.addPinMovedListener(redrawConsumer);
- redrawThreadsafe();
- };
- Consumer<Pin> pinRemovedListener = p ->
- {
- p.removePinMovedListener(redrawConsumer);
- redrawThreadsafe();
- };
- Consumer<? super GUIComponent> 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<? super GUIWire> 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)
--- /dev/null
+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
private final List<Consumer<? super GUIComponent>> componentRemovedListeners;
private final List<Consumer<? super GUIWire>> wireAddedListeners;
private final List<Consumer<? super GUIWire>> wireRemovedListeners;
+ private final List<Runnable> redrawListeners;
+
+ private final Runnable redrawListenerForSubcomponents;
public ViewModel()
{
componentRemovedListeners = new ArrayList<>();
wireAddedListeners = new ArrayList<>();
wireRemovedListeners = new ArrayList<>();
+ redrawListeners = new ArrayList<>();
+
+ redrawListenerForSubcomponents = this::callRedrawListeners;
}
/**
throw new IllegalStateException("Don't add the same component twice!");
components.add(component);
callComponentAddedListeners(component);
+ component.addRedrawListener(redrawListenerForSubcomponents);
+ callRedrawListeners();
}
/**
throw new IllegalStateException("Don't remove the same component twice!");
components.remove(component);
callComponentRemovedListeners(component);
+ component.removeRedrawListener(redrawListenerForSubcomponents);
+ callRedrawListeners();
}
/**
throw new IllegalStateException("Don't add the same wire twice!");
wires.add(wire);
callWireAddedListeners(wire);
+ wire.addRedrawListener(redrawListenerForSubcomponents);
+ callRedrawListeners();
}
/**
throw new IllegalStateException("Don't remove the same wire twice!");
wires.remove(wire);
callWireRemovedListeners(wire);
+ wire.removeRedrawListener(redrawListenerForSubcomponents);
+ callRedrawListeners();
}
public List<GUIComponent> getComponents()
return wiresUnmodifiable;
}
+// public void requestRedraw()
+// {
+// callRedrawListeners();
+// }
+
// @formatter:off
- public void addComponentAddedListener (Consumer<? super GUIComponent> listener){componentAddedListeners .add (listener);}
- public void addComponentRemovedListener (Consumer<? super GUIComponent> listener){componentRemovedListeners.add (listener);}
- public void addWireAddedListener (Consumer<? super GUIWire > listener){wireAddedListeners .add (listener);}
- public void addWireRemovedListener (Consumer<? super GUIWire > listener){wireRemovedListeners .add (listener);}
+ public void addComponentAddedListener (Consumer<? super GUIComponent> listener) {componentAddedListeners .add (listener);}
+ public void addComponentRemovedListener (Consumer<? super GUIComponent> listener) {componentRemovedListeners.add (listener);}
+ public void addWireAddedListener (Consumer<? super GUIWire > listener) {wireAddedListeners .add (listener);}
+ public void addWireRemovedListener (Consumer<? super GUIWire > listener) {wireRemovedListeners .add (listener);}
+ public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);}
- public void removeComponentAddedListener (Consumer<? super GUIComponent> listener){componentAddedListeners .remove(listener);}
- public void removeComponentRemovedListener(Consumer<? super GUIComponent> listener){componentRemovedListeners.remove(listener);}
- public void removeWireAddedListener (Consumer<? super GUIWire > listener){wireAddedListeners .remove(listener);}
- public void removeWireRemovedListener (Consumer<? super GUIWire > listener){wireRemovedListeners .remove(listener);}
+ public void removeComponentAddedListener (Consumer<? super GUIComponent> listener) {componentAddedListeners .remove(listener);}
+ public void removeComponentRemovedListener(Consumer<? super GUIComponent> listener) {componentRemovedListeners.remove(listener);}
+ public void removeWireAddedListener (Consumer<? super GUIWire > listener) {wireAddedListeners .remove(listener);}
+ public void removeWireRemovedListener (Consumer<? super GUIWire > 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
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));
private final List<Pin> pins;
protected final List<Pin> pinsUnmodifiable;
- private final List<Consumer<? super GUIComponent>> componentLookChangedListeners;
private final List<Consumer<? super GUIComponent>> componentMovedListeners;
private final List<Consumer<? super Pin>> pinAddedListeners;
private final List<Consumer<? super Pin>> pinRemovedListeners;
+ private final List<Runnable> redrawListeners;
+
+ private final Runnable redrawListenerForSubcomponents;
public GUIComponent(ViewModel model)
{
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);
}
}
// @formatter:off
- public void addComponentLookChangedListener (Consumer<? super GUIComponent> listener) {componentLookChangedListeners.add (listener);}
- public void addComponentMovedListener (Consumer<? super GUIComponent> listener) {componentMovedListeners .add (listener);}
- public void addPinAddedListener (Consumer<? super Pin > listener) {pinAddedListeners .add (listener);}
- public void addPinRemovedListener (Consumer<? super Pin > listener) {pinRemovedListeners .add (listener);}
-
- public void removeComponentLookChangedListener(Consumer<? super GUIComponent> listener) {componentLookChangedListeners.remove(listener);}
- public void removeComponentMovedListener (Consumer<? super GUIComponent> listener) {componentMovedListeners .remove(listener);}
- public void removePinAddedListener (Consumer<? super Pin > listener) {pinAddedListeners .remove(listener);}
- public void removePinRemovedListener (Consumer<? super Pin > 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<? super GUIComponent> listener) {componentMovedListeners.add (listener);}
+ public void addPinAddedListener (Consumer<? super Pin > listener) {pinAddedListeners .add (listener);}
+ public void addPinRemovedListener (Consumer<? super Pin > listener) {pinRemovedListeners .add (listener);}
+ public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);}
+
+ public void removeComponentMovedListener(Consumer<? super GUIComponent> listener) {componentMovedListeners .remove(listener);}
+ public void removePinAddedListener (Consumer<? super Pin > listener) {pinAddedListeners .remove(listener);}
+ public void removePinRemovedListener (Consumer<? super Pin > 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
public GUIManualSwitch(ViewModel model)\r
{\r
super(model);\r
- logicObs = (i) -> callComponentLookChangedListeners();\r
+ logicObs = (i) -> requestRedraw();\r
\r
setSize(width, height);\r
addPin(this.outputPin = new Pin(this, 1, width, height / 2));\r
\r
import java.util.ArrayList;\r
import java.util.List;\r
-import java.util.function.Consumer;\r
\r
-import net.mograsim.logic.ui.ColorHelper;\r
-import net.mograsim.logic.ui.model.ViewModel;\r
import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
import net.haspamelodica.swt.helper.swtobjectwrappers.Point;\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
import net.mograsim.logic.core.types.BitVectorFormatter;\r
import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.ui.ColorHelper;\r
+import net.mograsim.logic.ui.model.ViewModel;\r
\r
public class GUIWire\r
{\r
private Pin pin2;\r
private double[] path;\r
\r
- private final List<Consumer<? super GUIWire>> wireLookChangedListeners;\r
+ private final List<Runnable> redrawListeners;\r
\r
+ private final LogicObserver logicObs;\r
private ReadEnd end;\r
\r
public GUIWire(ViewModel model, Pin pin1, Pin pin2, Point... path)\r
{\r
+ logicObs = (i) -> callRedrawListeners();\r
this.model = model;\r
this.logicWidth = pin1.logicWidth;\r
if (pin2.logicWidth != pin1.logicWidth)\r
this.pin1 = pin1;\r
this.pin2 = pin2;\r
\r
- wireLookChangedListeners = new ArrayList<>();\r
+ redrawListeners = new ArrayList<>();\r
\r
pin1.addPinMovedListener(p -> pin1Moved());\r
pin2.addPinMovedListener(p -> pin2Moved());\r
Point pos = pin1.getPos();\r
this.path[0] = pos.x;\r
this.path[1] = pos.y;\r
+ callRedrawListeners();\r
}\r
\r
private void pin2Moved()\r
Point pos = pin2.getPos();\r
this.path[this.path.length - 2] = pos.x;\r
this.path[this.path.length - 1] = pos.y;\r
+ callRedrawListeners();\r
}\r
\r
public void destroy()\r
\r
public void setLogicModelBinding(ReadEnd end)\r
{\r
+ deregisterLogicObs(this.end);\r
this.end = end;\r
- end.registerObserver((i) -> callWireLookChangedListeners());\r
+ registerLogicObs(end);\r
+ }\r
+\r
+ private void registerLogicObs(LogicObservable observable)\r
+ {\r
+ if (observable != null)\r
+ observable.registerObserver(logicObs);\r
+ }\r
+\r
+ private void deregisterLogicObs(LogicObservable observable)\r
+ {\r
+ if (observable != null)\r
+ observable.deregisterObserver(logicObs);\r
}\r
\r
public Pin getPin1()\r
}\r
\r
// @formatter:off\r
- public void addWireLookChangedListener (Consumer<? super GUIWire> listener) {wireLookChangedListeners.add (listener);}\r
+ public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);}\r
\r
- public void removeWireLookChangedListener(Consumer<? super GUIWire> listener) {wireLookChangedListeners.remove(listener);}\r
+ public void removeRedrawListener(Runnable listener) {redrawListeners .remove(listener);}\r
\r
- private void callWireLookChangedListeners() {wireLookChangedListeners.forEach(l -> l.accept(this));}\r
+ private void callRedrawListeners() {redrawListeners.forEach(l -> l.run());}\r
// @formatter:on\r
\r
}
\ No newline at end of file
protected double relY;
private final List<Consumer<? super Pin>> pinMovedListeners;
+ private final List<Runnable> redrawListeners;
public Pin(GUIComponent component, int logicWidth, double relX, double relY)
{
this.relY = relY;
this.pinMovedListeners = new ArrayList<>();
+ this.redrawListeners = new ArrayList<>();
component.addComponentMovedListener(c -> callPinMovedListeners());
}
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<? super Pin> listener){pinMovedListeners.add (listener);}
+ public void addRedrawListener (Runnable listener){redrawListeners .add (listener);}
public void removePinMovedListener(Consumer<? super Pin> 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
package net.mograsim.logic.ui.model.wires;\r
\r
-import net.mograsim.logic.ui.ColorHelper;\r
-import net.mograsim.logic.ui.model.ViewModel;\r
-import net.mograsim.logic.ui.model.components.GUIComponent;\r
import net.haspamelodica.swt.helper.gcs.GeneralGC;\r
import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;\r
+import net.mograsim.logic.core.LogicObservable;\r
+import net.mograsim.logic.core.LogicObserver;\r
import net.mograsim.logic.core.types.BitVectorFormatter;\r
import net.mograsim.logic.core.wires.Wire.ReadEnd;\r
+import net.mograsim.logic.ui.ColorHelper;\r
+import net.mograsim.logic.ui.model.ViewModel;\r
+import net.mograsim.logic.ui.model.components.GUIComponent;\r
\r
public class WireCrossPoint extends GUIComponent\r
{\r
private final Pin pin;\r
+ private final int logicWidth;\r
\r
+ private final LogicObserver logicObs;\r
private ReadEnd end;\r
- private final int logicWidth;\r
\r
public WireCrossPoint(ViewModel model, int logicWidth)\r
{\r
super(model);\r
+ logicObs = (i) -> requestRedraw();\r
+\r
this.logicWidth = logicWidth;\r
setSize(0, 0);\r
addPin(this.pin = new Pin(this, logicWidth, 0, 0));\r
\r
public void setLogicModelBinding(ReadEnd end)\r
{\r
+ deregisterLogicObs(this.end);\r
this.end = end;\r
- end.registerObserver((i) -> callComponentLookChangedListeners());\r
+ registerLogicObs(end);\r
+ }\r
+\r
+ private void registerLogicObs(LogicObservable observable)\r
+ {\r
+ if (observable != null)\r
+ observable.registerObserver(logicObs);\r
+ }\r
+\r
+ private void deregisterLogicObs(LogicObservable observable)\r
+ {\r
+ if (observable != null)\r
+ observable.deregisterObserver(logicObs);\r
}\r
\r
public int getLogicWidth()\r