From: Daniel Kirschten Date: Tue, 28 May 2019 09:22:37 +0000 (+0200) Subject: Started restructuring LogicUI X-Git-Url: https://mograsim.net/gitweb/?p=Mograsim.git;a=commitdiff_plain;h=4d29cabdc45d68b5e5f210266dc4fbc5560dbcdd Started restructuring LogicUI --- diff --git a/LogicUI/oldsrc/GUIManualSwitch.java b/LogicUI/oldsrc/GUIManualSwitch.java new file mode 100644 index 00000000..318c3f09 --- /dev/null +++ b/LogicUI/oldsrc/GUIManualSwitch.java @@ -0,0 +1,95 @@ +package era.mi.gui.components; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import era.mi.logic.components.ManualSwitch; +import era.mi.logic.types.Bit; +import era.mi.logic.wires.Wire.ReadEnd; +import era.mi.logic.wires.Wire.ReadWriteEnd; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Font; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class GUIManualSwitch extends ManualSwitch implements GUIComponent +{ + private static final Map bitNames; + static + { + Map bitNamesModifiable = new HashMap<>(); + bitNamesModifiable.put(Bit.ONE, "1"); + bitNamesModifiable.put(Bit.ZERO, "0"); + bitNamesModifiable.put(Bit.Z, "Z"); + bitNamesModifiable.put(Bit.U, "U"); + bitNamesModifiable.put(Bit.X, "X"); + bitNames = Collections.unmodifiableMap(bitNamesModifiable); + } + + private final ReadEnd we; + private final List connectedWireEnds; + private final List wireEndConnectionPoints; + + public GUIManualSwitch(ReadWriteEnd output) + { + super(output); + + this.we = output; + + List connectedWireEndsModifiable = new ArrayList<>(); + List wireEndConnectionPointsModifiable = new ArrayList<>(); + + connectedWireEndsModifiable.add(output); + wireEndConnectionPointsModifiable.add(new Point(20, 7.5)); + + this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); + this.wireEndConnectionPoints = Collections.unmodifiableList(wireEndConnectionPointsModifiable); + } + + @Override + public Rectangle getBounds() + { + return new Rectangle(0, 0, 20, 15); + } + + @Override + public void render(GeneralGC gc) + { + gc.drawRectangle(0, 0, 20, 15); + String label = bitNames.get(we.getValue()); + Font oldFont = gc.getFont(); + Font labelFont = new Font(oldFont.getName(), 6, oldFont.getStyle()); + gc.setFont(labelFont); + Point textExtent = gc.textExtent(label); + gc.drawText(label, 10 - textExtent.x / 2, 7.5 - textExtent.y / 2, true); + gc.setFont(oldFont); + } + + @Override + public boolean clicked(double x, double y) + { + toggle(); + return true; + } + + @Override + public int getConnectedWireEndsCount() + { + return connectedWireEnds.size(); + } + + @Override + public ReadEnd getConnectedWireEnd(int connectionIndex) + { + return connectedWireEnds.get(connectionIndex); + } + + @Override + public Point getWireEndConnectionPoint(int connectionI) + { + return wireEndConnectionPoints.get(connectionI); + } +} \ No newline at end of file diff --git a/LogicUI/oldsrc/GUIMerger.java b/LogicUI/oldsrc/GUIMerger.java new file mode 100644 index 00000000..64fd0aa9 --- /dev/null +++ b/LogicUI/oldsrc/GUIMerger.java @@ -0,0 +1,79 @@ +package era.mi.gui.components; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import era.mi.logic.components.Merger; +import era.mi.logic.wires.Wire.ReadEnd; +import era.mi.logic.wires.Wire.ReadWriteEnd; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class GUIMerger extends Merger implements GUIComponent +{ + private final int inputCount; + private final double height; + private final List connectedWireEnds; + private final List WireEndConnectionPoints; + + public GUIMerger(ReadWriteEnd union, ReadEnd... inputs) + { + super(union, inputs); + + List connectedWireEndsModifiable = new ArrayList<>(); + List WireEndConnectionPointsModifiable = new ArrayList<>(); + + this.inputCount = inputs.length; + this.height = (inputCount - 1) * 10; + + { + connectedWireEndsModifiable.addAll(Arrays.asList(inputs)); + double inputHeight = 0; + for (int i = 0; i < inputCount; i++, inputHeight += 10) + WireEndConnectionPointsModifiable.add(new Point(0, inputHeight)); + } + + connectedWireEndsModifiable.add(union); + WireEndConnectionPointsModifiable.add(new Point(20, height / 2)); + + this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); + this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); + } + + @Override + public Rectangle getBounds() + { + return new Rectangle(0, 0, 20, height); + } + + @Override + public void render(GeneralGC gc) + { + double inputHeight = 0; + for (int i = 0; i < inputCount; i++, inputHeight += 10) + gc.drawLine(0, inputHeight, 10, inputHeight); + gc.drawLine(10, 0, 10, height); + gc.drawLine(10, height / 2, 20, height / 2); + } + + @Override + public int getConnectedWireEndsCount() + { + return connectedWireEnds.size(); + } + + @Override + public ReadEnd getConnectedWireEnd(int connectionIndex) + { + return connectedWireEnds.get(connectionIndex); + } + + @Override + public Point getWireEndConnectionPoint(int connectionI) + { + return WireEndConnectionPoints.get(connectionI); + } +} \ No newline at end of file diff --git a/LogicUI/oldsrc/GUIMux.java b/LogicUI/oldsrc/GUIMux.java new file mode 100644 index 00000000..d004d90f --- /dev/null +++ b/LogicUI/oldsrc/GUIMux.java @@ -0,0 +1,80 @@ +package era.mi.gui.components; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import era.mi.logic.components.Mux; +import era.mi.logic.wires.Wire.ReadEnd; +import era.mi.logic.wires.Wire.ReadWriteEnd; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class GUIMux extends Mux implements GUIComponent +{ + private final double height; + private final List connectedWireEnds; + private final List WireEndConnectionPoints; + + public GUIMux(int processTime, ReadWriteEnd out, ReadEnd select, ReadEnd... inputs) + { + super(processTime, out, select, inputs); + + double height = inputs.length * 5; + if (height < 10) + height = 10; + this.height = height; + + List connectedWireEndsModifiable = new ArrayList<>(); + List WireEndConnectionPointsModifiable = new ArrayList<>(); + + connectedWireEndsModifiable.add(out); + WireEndConnectionPointsModifiable.add(new Point(20, 10 + height / 2)); + + connectedWireEndsModifiable.add(select); + WireEndConnectionPointsModifiable.add(new Point(10, 5)); + + { + connectedWireEndsModifiable.addAll(Arrays.asList(inputs)); + double inputHeightIncrement = (height + 20) / inputs.length; + double inputHeight = inputHeightIncrement / 2; + for (int i = 0; i < inputs.length; i++, inputHeight += inputHeightIncrement) + WireEndConnectionPointsModifiable.add(new Point(0, inputHeight)); + } + + this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); + this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); + } + + @Override + public Rectangle getBounds() + { + return new Rectangle(0, 0, 20, height + 20); + } + + @Override + public void render(GeneralGC gc) + { + gc.drawPolygon(new double[] { 0, 0, 20, 10, 20, height + 10, 0, height + 20 }); + } + + @Override + public int getConnectedWireEndsCount() + { + return connectedWireEnds.size(); + } + + @Override + public ReadEnd getConnectedWireEnd(int connectionIndex) + { + return connectedWireEnds.get(connectionIndex); + } + + @Override + public Point getWireEndConnectionPoint(int connectionI) + { + return WireEndConnectionPoints.get(connectionI); + } +} \ No newline at end of file diff --git a/LogicUI/oldsrc/GUISplitter.java b/LogicUI/oldsrc/GUISplitter.java new file mode 100644 index 00000000..1bff4247 --- /dev/null +++ b/LogicUI/oldsrc/GUISplitter.java @@ -0,0 +1,72 @@ +package era.mi.gui.components; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import era.mi.gui.ViewModel; +import era.mi.logic.components.Splitter; +import era.mi.logic.wires.Wire.ReadEnd; +import era.mi.logic.wires.Wire.ReadWriteEnd; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class GUISplitter extends GUIComponent +{ + public GUISplitter(ViewModel model) + { + super(model); + + this.outputCount = outputs.length; + this.height = (outputCount - 1) * 10; + + connectedWireEndsModifiable.add(input); + WireEndConnectionPointsModifiable.add(new Point(0, height / 2)); + + { + connectedWireEndsModifiable.addAll(Arrays.asList(outputs)); + double outputHeight = 0; + for (int i = 0; i < outputCount; i++, outputHeight += 10) + WireEndConnectionPointsModifiable.add(new Point(20, outputHeight)); + } + + this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); + this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); + } + + @Override + public Rectangle getBounds() + { + return new Rectangle(0, 0, 20, height); + } + + @Override + public void render(GeneralGC gc) + { + gc.drawLine(0, height / 2, 10, height / 2); + gc.drawLine(10, 0, 10, height); + double outputHeight = 0; + for (int i = 0; i < outputCount; i++, outputHeight += 10) + gc.drawLine(10, outputHeight, 20, outputHeight); + } + + @Override + public int getConnectedWireEndsCount() + { + return connectedWireEnds.size(); + } + + @Override + public ReadEnd getConnectedWireEnd(int connectionIndex) + { + return connectedWireEnds.get(connectionIndex); + } + + @Override + public Point getWireEndConnectionPoint(int connectionI) + { + return WireEndConnectionPoints.get(connectionI); + } +} \ No newline at end of file diff --git a/LogicUI/oldsrc/RSLatchGUIExample.java b/LogicUI/oldsrc/RSLatchGUIExample.java new file mode 100644 index 00000000..0fb1886a --- /dev/null +++ b/LogicUI/oldsrc/RSLatchGUIExample.java @@ -0,0 +1,61 @@ +package era.mi.gui.examples; + +import era.mi.gui.LogicUICanvas; +import era.mi.gui.LogicUIStandalone; +import era.mi.gui.components.GUIManualSwitch; +import era.mi.gui.components.GUINotGate; +import era.mi.gui.components.GUIOrGateOld; +import era.mi.gui.wires.WireConnectionPoint; +import era.mi.logic.timeline.Timeline; +import era.mi.logic.wires.Wire; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; + +public class RSLatchGUIExample +{ + private static final int WIRE_DELAY = 10; + private static final int OR_DELAY = 50; + private static final int NOT_DELAY = 50; + + public static void main(String[] args) + { + Timeline t = new Timeline(11); + LogicUIStandalone ui = new LogicUIStandalone(t); + addComponentsAndWires(ui.getLogicUICanvas(), t); + ui.run(); + } + + public static void addComponentsAndWires(LogicUICanvas ui, Timeline t) + { + Wire r = new Wire(t, 1, WIRE_DELAY); + Wire s = new Wire(t, 1, WIRE_DELAY); + Wire t2 = new Wire(t, 1, WIRE_DELAY); + Wire t1 = new Wire(t, 1, WIRE_DELAY); + Wire q = new Wire(t, 1, WIRE_DELAY); + Wire nq = new Wire(t, 1, WIRE_DELAY); + + GUIManualSwitch rIn = ui.addComponent(new GUIManualSwitch(t, r.createReadWriteEnd()), 100, 100); + GUIManualSwitch sIn = ui.addComponent(new GUIManualSwitch(t, s.createReadWriteEnd()), 100, 200); + GUIOrGateOld or1 = ui.addComponent(new GUIOrGateOld(t, OR_DELAY, t1.createReadWriteEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd()), + 160, 102.5); + GUIOrGateOld or2 = ui.addComponent(new GUIOrGateOld(t, OR_DELAY, t2.createReadWriteEnd(), q.createReadOnlyEnd(), s.createReadOnlyEnd()), + 160, 192.5); + GUINotGate not1 = ui.addComponent(new GUINotGate(t, NOT_DELAY, t1.createReadOnlyEnd(), q.createReadWriteEnd()), 200, 107.5); + GUINotGate not2 = ui.addComponent(new GUINotGate(t, NOT_DELAY, t2.createReadOnlyEnd(), nq.createReadWriteEnd()), 200, 197.5); + + WireConnectionPoint p1 = ui.addComponent(new WireConnectionPoint(q, 3), 250, 112.5); + WireConnectionPoint p2 = ui.addComponent(new WireConnectionPoint(nq, 3), 250, 202.5); + WireConnectionPoint o1 = ui.addComponent(new WireConnectionPoint(q, 1), 270, 112.5); + WireConnectionPoint o2 = ui.addComponent(new WireConnectionPoint(nq, 1), 270, 202.5); + + ui.addWire(rIn, 0, or1, 0); + ui.addWire(sIn, 0, or2, 1); + ui.addWire(or1, 2, not1, 0); + ui.addWire(or2, 2, not2, 0); + ui.addWire(not1, 1, p1, 0); + ui.addWire(not2, 1, p2, 0); + ui.addWire(p1, 1, or2, 0, new Point(250, 130), new Point(140, 185), new Point(140, 197.5)); + ui.addWire(p2, 1, or1, 1, new Point(250, 185), new Point(140, 130), new Point(140, 117.5)); + ui.addWire(p1, 2, o1, 0); + ui.addWire(p2, 2, o2, 0); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/LogicUICanvas.java b/LogicUI/src/era/mi/gui/LogicUICanvas.java index fd6d4daa..4e619884 100644 --- a/LogicUI/src/era/mi/gui/LogicUICanvas.java +++ b/LogicUI/src/era/mi/gui/LogicUICanvas.java @@ -1,19 +1,18 @@ package era.mi.gui; -import java.util.HashMap; import java.util.HashSet; -import java.util.Map; import java.util.Set; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; -import era.mi.gui.components.BasicGUIComponent; -import era.mi.gui.wires.GUIWire; +import era.mi.gui.model.components.GUIComponent; +import era.mi.gui.model.wires.GUIWire; +import era.mi.gui.model.wires.Pin; import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.gcs.TranslatedGC; import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas; /** @@ -23,8 +22,7 @@ import net.haspamelodica.swt.helper.zoomablecanvas.ZoomableCanvas; */ public class LogicUICanvas extends ZoomableCanvas { - private final Set components; - private final Map componentPositions; + private final Set components; private final Set wires; public LogicUICanvas(Composite parent, int style) @@ -32,10 +30,13 @@ public class LogicUICanvas extends ZoomableCanvas super(parent, style); components = new HashSet<>(); - componentPositions = new HashMap<>(); wires = new HashSet<>(); - addZoomedRenderer(gc -> components.forEach(c -> drawComponent(gc, c))); + addZoomedRenderer(gc -> + { + Rectangle visibleRegion = new Rectangle(offX, offY, gW / zoom, gH / zoom); + components.forEach(c -> drawComponent(gc, c, visibleRegion)); + }); addZoomedRenderer(gc -> wires.forEach(w -> w.render(gc))); addListener(SWT.MouseDown, this::mouseDown); } @@ -45,10 +46,10 @@ public class LogicUICanvas extends ZoomableCanvas * * @author Daniel Kirschten */ - public C addComponent(C component, double x, double y) + // TODO replace with model change listener + public C addComponent(C component) { components.add(component); - componentPositions.put(component, new Point(x, y)); return component; } @@ -58,18 +59,21 @@ public class LogicUICanvas extends ZoomableCanvas * * @author Daniel Kirschten */ - public void addWire(BasicGUIComponent component1, int component1ConnectionIndex, BasicGUIComponent component2, - int component2ConnectionIndex, Point... path) + // TODO replace with model change listener + public void addWire(Pin pin1, Pin pin2, Point... path) { - wires.add(new GUIWire(this::redrawThreadsafe, component1, component1ConnectionIndex, componentPositions.get(component1), component2, - component2ConnectionIndex, componentPositions.get(component2), path)); + wires.add(new GUIWire(this::redrawThreadsafe, pin1, pin2, path)); } - private void drawComponent(GeneralGC gc, BasicGUIComponent component) + private void drawComponent(GeneralGC gc, GUIComponent component, Rectangle visibleRegion) { - TranslatedGC tgc = new TranslatedGC(gc, componentPositions.get(component)); - component.render(tgc); - tgc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLUE)); + component.render(gc, visibleRegion); + gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_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) @@ -77,8 +81,8 @@ public class LogicUICanvas extends ZoomableCanvas if (e.button == 1) { Point click = displayToWorldCoords(e.x, e.y); - for (BasicGUIComponent component : components) - if (component.getBounds().translate(componentPositions.get(component)).contains(click)) + for (GUIComponent component : components) + if (component.getBounds().contains(click)) { if (component.clicked(click.x, click.y)) redraw(); diff --git a/LogicUI/src/era/mi/gui/LogicUIStandalone.java b/LogicUI/src/era/mi/gui/LogicUIStandalone.java index 3b3c740f..0bc5d8a7 100644 --- a/LogicUI/src/era/mi/gui/LogicUIStandalone.java +++ b/LogicUI/src/era/mi/gui/LogicUIStandalone.java @@ -7,7 +7,7 @@ import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; -import era.mi.logic.timeline.Timeline; +import era.mi.gui.model.ViewModel; import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasOverlay; import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInput; @@ -18,14 +18,15 @@ import net.haspamelodica.swt.helper.zoomablecanvas.helper.ZoomableCanvasUserInpu */ public class LogicUIStandalone { + private ViewModel model; + private final Display display; private final Shell shell; private final LogicUICanvas ui; - private Timeline timeline; - public LogicUIStandalone(Timeline timeline) + public LogicUIStandalone(ViewModel model) { - this.timeline = timeline; + this.model = model; display = new Display(); shell = new Shell(display); shell.setLayout(new FillLayout()); @@ -49,39 +50,39 @@ public class LogicUIStandalone public void run() { AtomicBoolean running = new AtomicBoolean(true); - Thread simulationThread = new Thread(() -> - { - while (running.get()) - { - // always execute to keep timeline from "hanging behind" for too long - timeline.executeUpTo(System.currentTimeMillis(), System.currentTimeMillis() + 10); - long sleepTime; - if (timeline.hasNext()) - sleepTime = timeline.nextEventTime() - System.currentTimeMillis(); - else - sleepTime = 10; - try - { - if (sleepTime > 0) - Thread.sleep(sleepTime); - } - catch (InterruptedException e) - { - } // it is normal execution flow to be interrupted - } - }); - simulationThread.start(); - timeline.addEventAddedListener(event -> - { - if (event.getTiming() <= System.currentTimeMillis()) - simulationThread.interrupt(); - }); +// Thread simulationThread = new Thread(() -> +// { +// while (running.get()) +// { +// // always execute to keep timeline from "hanging behind" for too long +// model.timeline.executeUpTo(System.currentTimeMillis(), System.currentTimeMillis() + 10); +// long sleepTime; +// if (model.timeline.hasNext()) +// sleepTime = model.timeline.nextEventTime() - System.currentTimeMillis(); +// else +// sleepTime = 10; +// try +// { +// if (sleepTime > 0) +// Thread.sleep(sleepTime); +// } +// catch (InterruptedException e) +// { +// } // it is normal execution flow to be interrupted +// } +// }); +// simulationThread.start(); +// model.timeline.addEventAddedListener(event -> +// { +// if (event.getTiming() <= System.currentTimeMillis()) +// simulationThread.interrupt(); +// }); shell.open(); while (!shell.isDisposed()) if (!display.readAndDispatch()) display.sleep(); running.set(false); - simulationThread.interrupt(); +// simulationThread.interrupt(); } } \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/BasicGUIComponent.java b/LogicUI/src/era/mi/gui/components/BasicGUIComponent.java deleted file mode 100644 index 2d27685b..00000000 --- a/LogicUI/src/era/mi/gui/components/BasicGUIComponent.java +++ /dev/null @@ -1,44 +0,0 @@ -package era.mi.gui.components; - -import era.mi.logic.wires.Wire.ReadEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public interface BasicGUIComponent -{ - /** - * Render this component to the given gc, at coordinates (0, 0). - */ - public void render(GeneralGC gc); - - /** - * Returns the bounds of this component. Used for calculating which component is clicked. - */ - public Rectangle getBounds(); - - /** - * Called when this component is clicked. Relative coordinates of the click are given. Returns true if this component has to be redrawn. - */ - public default boolean clicked(double x, double y) - { - return false; - } - - // TODO this code will be replaced by code in BasicComponent. - /** - * Returns how many wire arrays are connected to this component. (Connections are static - they can't be removed and no new ones can be - * added) - */ - public int getConnectedWireEndsCount(); - - /** - * Returns the n-th wire array connected to this component. - */ - public ReadEnd getConnectedWireEnd(int connectionIndex); - - /** - * Returns relative coordinates where the n-th wire array is connected to this component. - */ - public Point getWireEndConnectionPoint(int connectionIndex); -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUIAndGate.java b/LogicUI/src/era/mi/gui/components/GUIAndGate.java deleted file mode 100644 index c76d65a0..00000000 --- a/LogicUI/src/era/mi/gui/components/GUIAndGate.java +++ /dev/null @@ -1,85 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import era.mi.logic.components.gates.AndGate; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Font; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUIAndGate extends AndGate implements BasicGUIComponent -{ - private static final String LABEL = "&"; - - private final int inputCount; - private final double height; - private final List connectedWireEnds; - private final List wireEndConnectionPoints; - - public GUIAndGate(Timeline timeline, int processTime, ReadWriteEnd out, ReadEnd... in) - { - super(timeline, processTime, out, in); - - List connectedWireEndsModifiable = new ArrayList<>(); - List wireEndConnectionPointsModifiable = new ArrayList<>(); - - this.inputCount = in.length; - this.height = inputCount * 10; - - { - connectedWireEndsModifiable.addAll(Arrays.asList(in)); - double inputHeight = 5; - for (int i = 0; i < inputCount; i++, inputHeight += 10) - wireEndConnectionPointsModifiable.add(new Point(0, inputHeight)); - } - - connectedWireEndsModifiable.add(out); - wireEndConnectionPointsModifiable.add(new Point(20, height / 2)); - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.wireEndConnectionPoints = Collections.unmodifiableList(wireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, height); - } - - @Override - public void render(GeneralGC gc) - { - gc.drawRectangle(0, 0, 20, height); - Font oldFont = gc.getFont(); - Font labelFont = new Font(oldFont.getName(), 5, oldFont.getStyle()); - gc.setFont(labelFont); - Point textExtent = gc.textExtent(LABEL); - gc.drawText(LABEL, 10 - textExtent.x / 2, (height - textExtent.y) / 2, true); - gc.setFont(oldFont); - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return wireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUIManualSwitch.java b/LogicUI/src/era/mi/gui/components/GUIManualSwitch.java deleted file mode 100644 index 7dcb025f..00000000 --- a/LogicUI/src/era/mi/gui/components/GUIManualSwitch.java +++ /dev/null @@ -1,96 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import era.mi.logic.components.ManualSwitch; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.types.Bit; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Font; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUIManualSwitch extends ManualSwitch implements BasicGUIComponent -{ - private static final Map bitNames; - static - { - Map bitNamesModifiable = new HashMap<>(); - bitNamesModifiable.put(Bit.ONE, "1"); - bitNamesModifiable.put(Bit.ZERO, "0"); - bitNamesModifiable.put(Bit.Z, "Z"); - bitNamesModifiable.put(Bit.U, "U"); - bitNamesModifiable.put(Bit.X, "X"); - bitNames = Collections.unmodifiableMap(bitNamesModifiable); - } - - private final ReadEnd we; - private final List connectedWireEnds; - private final List wireEndConnectionPoints; - - public GUIManualSwitch(Timeline timeline, ReadWriteEnd output) - { - super(timeline, output); - - this.we = output; - - List connectedWireEndsModifiable = new ArrayList<>(); - List wireEndConnectionPointsModifiable = new ArrayList<>(); - - connectedWireEndsModifiable.add(output); - wireEndConnectionPointsModifiable.add(new Point(20, 7.5)); - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.wireEndConnectionPoints = Collections.unmodifiableList(wireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, 15); - } - - @Override - public void render(GeneralGC gc) - { - gc.drawRectangle(0, 0, 20, 15); - String label = bitNames.get(we.getValue()); - Font oldFont = gc.getFont(); - Font labelFont = new Font(oldFont.getName(), 6, oldFont.getStyle()); - gc.setFont(labelFont); - Point textExtent = gc.textExtent(label); - gc.drawText(label, 10 - textExtent.x / 2, 7.5 - textExtent.y / 2, true); - gc.setFont(oldFont); - } - - @Override - public boolean clicked(double x, double y) - { - toggle(); - return true; - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return wireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUIMerger.java b/LogicUI/src/era/mi/gui/components/GUIMerger.java deleted file mode 100644 index 240855c3..00000000 --- a/LogicUI/src/era/mi/gui/components/GUIMerger.java +++ /dev/null @@ -1,80 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import era.mi.logic.components.Merger; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUIMerger extends Merger implements BasicGUIComponent -{ - private final int inputCount; - private final double height; - private final List connectedWireEnds; - private final List WireEndConnectionPoints; - - public GUIMerger(Timeline timeline, ReadWriteEnd union, ReadEnd... inputs) - { - super(timeline, union, inputs); - - List connectedWireEndsModifiable = new ArrayList<>(); - List WireEndConnectionPointsModifiable = new ArrayList<>(); - - this.inputCount = inputs.length; - this.height = (inputCount - 1) * 10; - - { - connectedWireEndsModifiable.addAll(Arrays.asList(inputs)); - double inputHeight = 0; - for (int i = 0; i < inputCount; i++, inputHeight += 10) - WireEndConnectionPointsModifiable.add(new Point(0, inputHeight)); - } - - connectedWireEndsModifiable.add(union); - WireEndConnectionPointsModifiable.add(new Point(20, height / 2)); - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, height); - } - - @Override - public void render(GeneralGC gc) - { - double inputHeight = 0; - for (int i = 0; i < inputCount; i++, inputHeight += 10) - gc.drawLine(0, inputHeight, 10, inputHeight); - gc.drawLine(10, 0, 10, height); - gc.drawLine(10, height / 2, 20, height / 2); - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return WireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUIMux.java b/LogicUI/src/era/mi/gui/components/GUIMux.java deleted file mode 100644 index 0eba8f55..00000000 --- a/LogicUI/src/era/mi/gui/components/GUIMux.java +++ /dev/null @@ -1,81 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import era.mi.logic.components.Mux; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUIMux extends Mux implements BasicGUIComponent -{ - private final double height; - private final List connectedWireEnds; - private final List WireEndConnectionPoints; - - public GUIMux(Timeline timeline, int processTime, ReadWriteEnd out, ReadEnd select, ReadEnd... inputs) - { - super(timeline, processTime, out, select, inputs); - - double height = inputs.length * 5; - if (height < 10) - height = 10; - this.height = height; - - List connectedWireEndsModifiable = new ArrayList<>(); - List WireEndConnectionPointsModifiable = new ArrayList<>(); - - connectedWireEndsModifiable.add(out); - WireEndConnectionPointsModifiable.add(new Point(20, 10 + height / 2)); - - connectedWireEndsModifiable.add(select); - WireEndConnectionPointsModifiable.add(new Point(10, 5)); - - { - connectedWireEndsModifiable.addAll(Arrays.asList(inputs)); - double inputHeightIncrement = (height + 20) / inputs.length; - double inputHeight = inputHeightIncrement / 2; - for (int i = 0; i < inputs.length; i++, inputHeight += inputHeightIncrement) - WireEndConnectionPointsModifiable.add(new Point(0, inputHeight)); - } - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, height + 20); - } - - @Override - public void render(GeneralGC gc) - { - gc.drawPolygon(new double[] { 0, 0, 20, 10, 20, height + 10, 0, height + 20 }); - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return WireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUINotGate.java b/LogicUI/src/era/mi/gui/components/GUINotGate.java deleted file mode 100644 index fa4730a1..00000000 --- a/LogicUI/src/era/mi/gui/components/GUINotGate.java +++ /dev/null @@ -1,76 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import era.mi.logic.components.gates.NotGate; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Font; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUINotGate extends NotGate implements BasicGUIComponent -{ - private static final String LABEL = "\u22651";// >=1 - - private final List connectedWireEnds; - private final List WireEndConnectionPoints; - - public GUINotGate(Timeline timeline, int processTime, ReadEnd in, ReadWriteEnd out) - { - super(timeline, processTime, in, out); - - List connectedWireEndsModifiable = new ArrayList<>(); - List WireEndConnectionPointsModifiable = new ArrayList<>(); - - connectedWireEndsModifiable.add(in); - WireEndConnectionPointsModifiable.add(new Point(0, 5)); - - connectedWireEndsModifiable.add(out); - WireEndConnectionPointsModifiable.add(new Point(20, 5)); - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, 10); - } - - @Override - public void render(GeneralGC gc) - { - gc.drawRectangle(0, 0, 17, 10); - Font oldFont = gc.getFont(); - Font labelFont = new Font(oldFont.getName(), 5, oldFont.getStyle()); - gc.setFont(labelFont); - Point textExtent = gc.textExtent(LABEL); - gc.drawText(LABEL, 8.5 - textExtent.x / 2, 5 - textExtent.y / 2, true); - gc.setFont(oldFont); - gc.drawOval(17, 3.5, 3, 3); - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return WireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUIOrGate.java b/LogicUI/src/era/mi/gui/components/GUIOrGate.java deleted file mode 100644 index 549cb402..00000000 --- a/LogicUI/src/era/mi/gui/components/GUIOrGate.java +++ /dev/null @@ -1,85 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import era.mi.logic.components.gates.OrGate; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Font; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUIOrGate extends OrGate implements BasicGUIComponent -{ - private static final String LABEL = "\u22651";// >=1 - - private final int inputCount; - private final double height; - private final List connectedWireEnds; - private final List WireEndConnectionPoints; - - public GUIOrGate(Timeline timeline, int processTime, ReadWriteEnd out, ReadEnd... in) - { - super(timeline, processTime, out, in); - - List connectedWireEndsModifiable = new ArrayList<>(); - List WireEndConnectionPointsModifiable = new ArrayList<>(); - - this.inputCount = in.length; - this.height = inputCount * 10; - - { - connectedWireEndsModifiable.addAll(Arrays.asList(in)); - double inputHeight = 5; - for (int i = 0; i < inputCount; i++, inputHeight += 10) - WireEndConnectionPointsModifiable.add(new Point(0, inputHeight)); - } - - connectedWireEndsModifiable.add(out); - WireEndConnectionPointsModifiable.add(new Point(20, height / 2)); - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, height); - } - - @Override - public void render(GeneralGC gc) - { - gc.drawRectangle(0, 0, 20, height); - Font oldFont = gc.getFont(); - Font labelFont = new Font(oldFont.getName(), 5, oldFont.getStyle()); - gc.setFont(labelFont); - Point textExtent = gc.textExtent(LABEL); - gc.drawText(LABEL, 10 - textExtent.x / 2, (height - textExtent.y) / 2, true); - gc.setFont(oldFont); - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return WireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/components/GUISplitter.java b/LogicUI/src/era/mi/gui/components/GUISplitter.java deleted file mode 100644 index 6873e637..00000000 --- a/LogicUI/src/era/mi/gui/components/GUISplitter.java +++ /dev/null @@ -1,80 +0,0 @@ -package era.mi.gui.components; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import era.mi.logic.components.Splitter; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire.ReadEnd; -import era.mi.logic.wires.Wire.ReadWriteEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class GUISplitter extends Splitter implements BasicGUIComponent -{ - private final int outputCount; - private final double height; - private final List connectedWireEnds; - private final List WireEndConnectionPoints; - - public GUISplitter(Timeline timeline, ReadEnd input, ReadWriteEnd... outputs) - { - super(timeline, input, outputs); - - List connectedWireEndsModifiable = new ArrayList<>(); - List WireEndConnectionPointsModifiable = new ArrayList<>(); - - this.outputCount = outputs.length; - this.height = (outputCount - 1) * 10; - - connectedWireEndsModifiable.add(input); - WireEndConnectionPointsModifiable.add(new Point(0, height / 2)); - - { - connectedWireEndsModifiable.addAll(Arrays.asList(outputs)); - double outputHeight = 0; - for (int i = 0; i < outputCount; i++, outputHeight += 10) - WireEndConnectionPointsModifiable.add(new Point(20, outputHeight)); - } - - this.connectedWireEnds = Collections.unmodifiableList(connectedWireEndsModifiable); - this.WireEndConnectionPoints = Collections.unmodifiableList(WireEndConnectionPointsModifiable); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 20, height); - } - - @Override - public void render(GeneralGC gc) - { - gc.drawLine(0, height / 2, 10, height / 2); - gc.drawLine(10, 0, 10, height); - double outputHeight = 0; - for (int i = 0; i < outputCount; i++, outputHeight += 10) - gc.drawLine(10, outputHeight, 20, outputHeight); - } - - @Override - public int getConnectedWireEndsCount() - { - return connectedWireEnds.size(); - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return connectedWireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionI) - { - return WireEndConnectionPoints.get(connectionI); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/examples/Playground.java b/LogicUI/src/era/mi/gui/examples/Playground.java new file mode 100644 index 00000000..eafa1a58 --- /dev/null +++ b/LogicUI/src/era/mi/gui/examples/Playground.java @@ -0,0 +1,32 @@ +package era.mi.gui.examples; + +import era.mi.gui.LogicUICanvas; +import era.mi.gui.LogicUIStandalone; +import era.mi.gui.model.ViewModel; +import era.mi.gui.model.components.GUIAndGate; +import era.mi.gui.model.components.GUINotGate; + +public class Playground +{ + private static final int WIRE_DELAY = 10; + private static final int OR_DELAY = 50; + private static final int NOT_DELAY = 50; + + public static void main(String[] args) + { + ViewModel model = new ViewModel(); + LogicUIStandalone ui = new LogicUIStandalone(model); + addComponentsAndWires(ui.getLogicUICanvas(), model); + ui.run(); + } + + public static void addComponentsAndWires(LogicUICanvas ui, ViewModel model) + { + GUIAndGate andGate = ui.addComponent(new GUIAndGate(model)); + andGate.moveTo(10, 10); + GUINotGate notGate = ui.addComponent(new GUINotGate(model)); + notGate.moveTo(10, 40); + + ui.addWire(andGate.getPins().get(0), notGate.getPins().get(1)); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/examples/RSLatchGUIExample.java b/LogicUI/src/era/mi/gui/examples/RSLatchGUIExample.java deleted file mode 100644 index dc6091f6..00000000 --- a/LogicUI/src/era/mi/gui/examples/RSLatchGUIExample.java +++ /dev/null @@ -1,61 +0,0 @@ -package era.mi.gui.examples; - -import era.mi.gui.LogicUICanvas; -import era.mi.gui.LogicUIStandalone; -import era.mi.gui.components.GUIManualSwitch; -import era.mi.gui.components.GUINotGate; -import era.mi.gui.components.GUIOrGate; -import era.mi.gui.wires.WireConnectionPoint; -import era.mi.logic.timeline.Timeline; -import era.mi.logic.wires.Wire; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; - -public class RSLatchGUIExample -{ - private static final int WIRE_DELAY = 10; - private static final int OR_DELAY = 50; - private static final int NOT_DELAY = 50; - - public static void main(String[] args) - { - Timeline t = new Timeline(11); - LogicUIStandalone ui = new LogicUIStandalone(t); - addComponentsAndWires(ui.getLogicUICanvas(), t); - ui.run(); - } - - public static void addComponentsAndWires(LogicUICanvas ui, Timeline t) - { - Wire r = new Wire(t, 1, WIRE_DELAY); - Wire s = new Wire(t, 1, WIRE_DELAY); - Wire t2 = new Wire(t, 1, WIRE_DELAY); - Wire t1 = new Wire(t, 1, WIRE_DELAY); - Wire q = new Wire(t, 1, WIRE_DELAY); - Wire nq = new Wire(t, 1, WIRE_DELAY); - - GUIManualSwitch rIn = ui.addComponent(new GUIManualSwitch(t, r.createReadWriteEnd()), 100, 100); - GUIManualSwitch sIn = ui.addComponent(new GUIManualSwitch(t, s.createReadWriteEnd()), 100, 200); - GUIOrGate or1 = ui.addComponent(new GUIOrGate(t, OR_DELAY, t1.createReadWriteEnd(), r.createReadOnlyEnd(), nq.createReadOnlyEnd()), - 160, 102.5); - GUIOrGate or2 = ui.addComponent(new GUIOrGate(t, OR_DELAY, t2.createReadWriteEnd(), q.createReadOnlyEnd(), s.createReadOnlyEnd()), - 160, 192.5); - GUINotGate not1 = ui.addComponent(new GUINotGate(t, NOT_DELAY, t1.createReadOnlyEnd(), q.createReadWriteEnd()), 200, 107.5); - GUINotGate not2 = ui.addComponent(new GUINotGate(t, NOT_DELAY, t2.createReadOnlyEnd(), nq.createReadWriteEnd()), 200, 197.5); - - WireConnectionPoint p1 = ui.addComponent(new WireConnectionPoint(q, 3), 250, 112.5); - WireConnectionPoint p2 = ui.addComponent(new WireConnectionPoint(nq, 3), 250, 202.5); - WireConnectionPoint o1 = ui.addComponent(new WireConnectionPoint(q, 1), 270, 112.5); - WireConnectionPoint o2 = ui.addComponent(new WireConnectionPoint(nq, 1), 270, 202.5); - - ui.addWire(rIn, 0, or1, 0); - ui.addWire(sIn, 0, or2, 1); - ui.addWire(or1, 2, not1, 0); - ui.addWire(or2, 2, not2, 0); - ui.addWire(not1, 1, p1, 0); - ui.addWire(not2, 1, p2, 0); - ui.addWire(p1, 1, or2, 0, new Point(250, 130), new Point(140, 185), new Point(140, 197.5)); - ui.addWire(p2, 1, or1, 1, new Point(250, 185), new Point(140, 130), new Point(140, 117.5)); - ui.addWire(p1, 2, o1, 0); - ui.addWire(p2, 2, o2, 0); - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/ViewModel.java b/LogicUI/src/era/mi/gui/model/ViewModel.java new file mode 100644 index 00000000..de22f447 --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/ViewModel.java @@ -0,0 +1,66 @@ +package era.mi.gui.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import era.mi.gui.model.components.GUIComponent; +import era.mi.gui.model.wires.GUIWire; + +public class ViewModel +{ + private final List components; + private final List wires; + + private final List> componentAddedListeners; + private final List> componentRemovedListeners; + private final List> wireAddedListeners; + private final List> wireRemovedListeners; + + public ViewModel() + { + components = new ArrayList<>(); + wires = new ArrayList<>(); + + componentAddedListeners = new ArrayList<>(); + componentRemovedListeners = new ArrayList<>(); + wireAddedListeners = new ArrayList<>(); + wireRemovedListeners = new ArrayList<>(); + } + + /** + * Adds the given component to the list of components and calls all componentAddedListeners. Don't call this method from application + * code as it is automatically called in GUIComponent::new. + */ + public void addComponent(GUIComponent component) + { + if (components.contains(component)) + throw new IllegalStateException("Don't add the same component twice!"); + components.add(component); + componentAddedListeners.forEach(l -> l.accept(component)); + } + + /** + * Removes the given component from the list of components and calls all componentRemovedListeners. Don't call this method from + * application code as it is automatically called in GUIComponent::destroy. + */ + public void removeComponent(GUIComponent component) + { + if (!components.contains(component)) + throw new IllegalStateException("Don't remove the same component twice!"); + components.remove(component); + componentRemovedListeners.forEach(l -> l.accept(component)); + } + + // @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 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);} + // @formatter:on +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java b/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java new file mode 100644 index 00000000..4f69d36d --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java @@ -0,0 +1,12 @@ +package era.mi.gui.model.components; + +import era.mi.gui.model.ViewModel; + +public class GUIAndGate extends RectangularShapedGUIGate +{ + public GUIAndGate(ViewModel model) + { + super(model, "&", false); + setInputCount(2); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/components/GUIComponent.java b/LogicUI/src/era/mi/gui/model/components/GUIComponent.java new file mode 100644 index 00000000..75a7a53f --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/components/GUIComponent.java @@ -0,0 +1,78 @@ +package era.mi.gui.model.components; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import era.mi.gui.model.ViewModel; +import era.mi.gui.model.wires.Pin; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public abstract class GUIComponent +{ + protected final ViewModel model; + private final Rectangle bounds; + private final List pins; + protected final List pinsUnmodifiable; + + public GUIComponent(ViewModel model) + { + this.model = model; + this.bounds = new Rectangle(0, 0, 0, 0); + this.pins = new ArrayList<>(); + this.pinsUnmodifiable = Collections.unmodifiableList(pins); + } + + public void moveTo(double x, double y) + { + bounds.x = x; + bounds.y = y; + } + + /** + * Returns the bounds of this component. Used for calculating which component is clicked. + */ + public Rectangle getBounds() + { + return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); + } + + // TODO + /** + * Called when this component is clicked. Relative coordinates of the click are given. Returns true if this component has to be redrawn. + */ + public boolean clicked(double x, double y) + { + return false; + } + + /** + * Returns a list of pins of this component. + */ + public List getPins() + { + return pinsUnmodifiable; + } + + /** + * Render this component to the given gc. + */ + public abstract void render(GeneralGC gc, Rectangle visibleRegion); + + protected void setSize(double width, double height) + { + bounds.width = width; + bounds.height = height; + } + + protected void addPin(Pin pin) + {// TODO notify pins they are "created" + pins.add(pin); + } + + protected void removePin(Pin pin) + {// TODO notify pins they are "destroyed" + pins.remove(pin); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/components/GUINotGate.java b/LogicUI/src/era/mi/gui/model/components/GUINotGate.java new file mode 100644 index 00000000..5f41592b --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/components/GUINotGate.java @@ -0,0 +1,12 @@ +package era.mi.gui.model.components; + +import era.mi.gui.model.ViewModel; + +public class GUINotGate extends RectangularShapedGUIGate +{ + public GUINotGate(ViewModel model) + { + super(model, "1", true); + setInputCount(1); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/components/GUIOrGate.java b/LogicUI/src/era/mi/gui/model/components/GUIOrGate.java new file mode 100644 index 00000000..df64bba1 --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/components/GUIOrGate.java @@ -0,0 +1,12 @@ +package era.mi.gui.model.components; + +import era.mi.gui.model.ViewModel; + +public class GUIOrGate extends RectangularShapedGUIGate +{ + public GUIOrGate(ViewModel model) + { + super(model, "\u22651", false);// ">=1" + setInputCount(2); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/components/RectangularShapedGUIGate.java b/LogicUI/src/era/mi/gui/model/components/RectangularShapedGUIGate.java new file mode 100644 index 00000000..c7d0b346 --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/components/RectangularShapedGUIGate.java @@ -0,0 +1,74 @@ +package era.mi.gui.model.components; + +import java.util.ArrayList; +import java.util.List; + +import era.mi.gui.model.ViewModel; +import era.mi.gui.model.wires.MovablePin; +import era.mi.gui.model.wires.Pin; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Font; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class RectangularShapedGUIGate extends GUIComponent +{ + private static final double width = 20; + private static final double pinDistance = 10; + private static final double fontHeight = 5; + private static final double invertedCircleDiam = 3.5; + + private final String label; + private final boolean isInverted; + private final double rectWidth; + + private MovablePin outputPin; + private final List inputPins; + + protected RectangularShapedGUIGate(ViewModel model, String label, boolean isInverted) + { + super(model); + this.label = label; + this.isInverted = isInverted; + this.rectWidth = width - (isInverted ? invertedCircleDiam : 0); + this.outputPin = new MovablePin(this, width, 0); + addPin(outputPin); + this.inputPins = new ArrayList<>(); + setInputCount(1); + } + + protected void setInputCount(int inputCount) + { + int oldInputCount = inputPins.size(); + setSize(width, inputCount * pinDistance); + if (oldInputCount > inputCount) + while (inputPins.size() > inputCount) + removePin(inputPins.get(inputCount)); + else if (oldInputCount < inputCount) + for (int i = oldInputCount; i < inputCount; i++) + { + Pin pin = new Pin(this, 0, pinDistance / 2 + i * pinDistance); + inputPins.add(pin); + addPin(pin); + } + outputPin.setRelPos(width, inputCount * pinDistance / 2); + } + + @Override + public void render(GeneralGC gc, Rectangle visibleRegion) + { + double posX = getBounds().x; + double posY = getBounds().y; + + double height = inputPins.size() * pinDistance; + gc.drawRectangle(posX, posY, rectWidth, height); + Font oldFont = gc.getFont(); + Font labelFont = new Font(oldFont.getName(), fontHeight, oldFont.getStyle()); + gc.setFont(labelFont); + Point textExtent = gc.textExtent(label); + gc.drawText(label, posX + (rectWidth - textExtent.x) / 2, posY + (height - textExtent.y) / 2, true); + gc.setFont(oldFont); + if (isInverted) + gc.drawOval(posX + rectWidth, posY + (height - invertedCircleDiam) / 2, invertedCircleDiam, invertedCircleDiam); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/wires/GUIWire.java b/LogicUI/src/era/mi/gui/model/wires/GUIWire.java new file mode 100644 index 00000000..d0bd9908 --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/wires/GUIWire.java @@ -0,0 +1,75 @@ +package era.mi.gui.model.wires; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; + +import era.mi.logic.types.Bit; +import era.mi.logic.wires.Wire; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; + +public class GUIWire +{ + private Pin pin1; + private Pin pin2; + private double[] path; + + private Wire wire; + + public GUIWire(Runnable redraw, Pin pin1, Pin pin2, Point... path) + { + this.path = new double[path.length * 2 + 4]; + for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2) + { + this.path[dstI + 0] = path[srcI].x; + this.path[dstI + 1] = path[srcI].y; + } + // TODO support moving pins + Point pos; + pos = pin1.getPos(); + this.path[0] = pos.x; + this.path[1] = pos.y; + pos = pin2.getPos(); + this.path[this.path.length - 2] = pos.x; + this.path[this.path.length - 1] = pos.y; + } + + public void render(GeneralGC gc) + { + Color oldFG = gc.getForeground(); + gc.setForeground(gc.getDevice().getSystemColor(getSWTColorConstantForWire(wire))); + gc.drawPolyline(path); + gc.setForeground(oldFG); + } + + public void setLogicModelWire(Wire wire) + { + this.wire = wire; + } + + public static int getSWTColorConstantForWire(Wire wire) + { + if (wire != null && wire.length == 1) + return getSWTColorConstantForBit(wire.getValue()); + else + return SWT.COLOR_BLACK; + } + + public static int getSWTColorConstantForBit(Bit bit) + { + switch (bit) + { + case ONE: + return SWT.COLOR_GREEN; + case ZERO: + return SWT.COLOR_BLUE; + case Z: + return SWT.COLOR_BLACK; + case U: + case X: + return SWT.COLOR_RED; + default: + throw new IllegalArgumentException("Unknown enum constant: " + bit); + } + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/wires/MovablePin.java b/LogicUI/src/era/mi/gui/model/wires/MovablePin.java new file mode 100644 index 00000000..673b2578 --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/wires/MovablePin.java @@ -0,0 +1,17 @@ +package era.mi.gui.model.wires; + +import era.mi.gui.model.components.GUIComponent; + +public class MovablePin extends Pin +{ + public MovablePin(GUIComponent component, double relX, double relY) + { + super(component, relX, relY); + } + + @Override + public void setRelPos(double relX, double relY) + { + super.setRelPos(relX, relY); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/wires/Pin.java b/LogicUI/src/era/mi/gui/model/wires/Pin.java new file mode 100644 index 00000000..1ab74047 --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/wires/Pin.java @@ -0,0 +1,46 @@ +package era.mi.gui.model.wires; + +import era.mi.gui.model.components.GUIComponent; +import net.haspamelodica.swt.helper.swtobjectwrappers.Point; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class Pin +{ + public final GUIComponent component; + protected double relX; + protected double relY; + + public Pin(GUIComponent component, double relX, double relY) + { + this.component = component; + this.relX = relX; + this.relY = relY; + } + + public double getRelX() + { + return relX; + } + + public double getRelY() + { + return relY; + } + + public Point getRelPos() + { + return new Point(relX, relY); + } + + public Point getPos() + { + Rectangle componentBounds = component.getBounds(); + return new Point(relX + componentBounds.x, relY + componentBounds.y); + } + + protected void setRelPos(double relX, double relY) + { + this.relX = relX; + this.relY = relY; + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/wires/WireCrossPoint.java b/LogicUI/src/era/mi/gui/model/wires/WireCrossPoint.java new file mode 100644 index 00000000..84179fad --- /dev/null +++ b/LogicUI/src/era/mi/gui/model/wires/WireCrossPoint.java @@ -0,0 +1,35 @@ +package era.mi.gui.model.wires; + +import org.eclipse.swt.graphics.Color; + +import era.mi.gui.model.ViewModel; +import era.mi.gui.model.components.GUIComponent; +import era.mi.logic.wires.Wire; +import net.haspamelodica.swt.helper.gcs.GeneralGC; +import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; + +public class WireCrossPoint extends GUIComponent +{ + private Wire wire; + + public WireCrossPoint(ViewModel model) + { + super(model); + setSize(0, 0); + addPin(new Pin(this, 0, 0)); + } + + @Override + public void render(GeneralGC gc, Rectangle visibleRegion) + { + Color oldBG = gc.getBackground(); + gc.setBackground(gc.getDevice().getSystemColor(GUIWire.getSWTColorConstantForWire(wire))); + gc.fillOval(-1, -1, 2, 2); + gc.setBackground(oldBG); + } + + public void setLogicModelWire(Wire wire) + { + this.wire = wire; + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/modeladapter/ViewLogicModelAdapter.java b/LogicUI/src/era/mi/gui/modeladapter/ViewLogicModelAdapter.java new file mode 100644 index 00000000..f005a80b --- /dev/null +++ b/LogicUI/src/era/mi/gui/modeladapter/ViewLogicModelAdapter.java @@ -0,0 +1,6 @@ +package era.mi.gui.modeladapter; + +public class ViewLogicModelAdapter +{ + +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/wires/GUIWire.java b/LogicUI/src/era/mi/gui/wires/GUIWire.java deleted file mode 100644 index 53e122a3..00000000 --- a/LogicUI/src/era/mi/gui/wires/GUIWire.java +++ /dev/null @@ -1,67 +0,0 @@ -package era.mi.gui.wires; - -import java.util.Objects; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.graphics.Color; - -import era.mi.gui.components.BasicGUIComponent; -import era.mi.logic.types.Bit; -import era.mi.logic.wires.Wire; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; - -public class GUIWire -{ - private final Wire wire; - private final double[] path; - - public GUIWire(Runnable redraw, BasicGUIComponent component1, int component1ConnectionIndex, Point component1Pos, - BasicGUIComponent component2, int component2ConnectionIndex, Point component2Pos, Point... path) - { - this.wire = component1.getConnectedWireEnd(component1ConnectionIndex).getWire(); - if (!Objects.equals(wire, component2.getConnectedWireEnd(component2ConnectionIndex).getWire())) - throw new IllegalArgumentException("Given connection points are not connected!"); - this.path = new double[path.length * 2 + 4]; - Point component1ConnectionPoint = component1.getWireEndConnectionPoint(component1ConnectionIndex); - this.path[0] = component1Pos.x + component1ConnectionPoint.x; - this.path[1] = component1Pos.y + component1ConnectionPoint.y; - for (int srcI = 0, dstI = 2; srcI < path.length; srcI++, dstI += 2) - { - this.path[dstI + 0] = path[srcI].x; - this.path[dstI + 1] = path[srcI].y; - } - Point component2ConnectionPoint = component2.getWireEndConnectionPoint(component2ConnectionIndex); - this.path[this.path.length - 2] = component2Pos.x + component2ConnectionPoint.x; - this.path[this.path.length - 1] = component2Pos.y + component2ConnectionPoint.y; - - wire.createReadOnlyEnd().addObserver((initiator, oldValues) -> redraw.run()); - } - - public void render(GeneralGC gc) - { - Color oldFG = gc.getForeground(); - if (wire.length == 1) - gc.setForeground(gc.getDevice().getSystemColor(getSWTColorConstantForBit(wire.getValue()))); - gc.drawPolyline(path); - gc.setForeground(oldFG); - } - - public static int getSWTColorConstantForBit(Bit bit) - { - switch (bit) - { - case ONE: - return SWT.COLOR_GREEN; - case ZERO: - return SWT.COLOR_BLUE; - case Z: - return SWT.COLOR_BLACK; - case U: - case X: - return SWT.COLOR_RED; - default: - throw new IllegalArgumentException("Unknown enum constant: " + bit); - } - } -} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/wires/WireConnectionPoint.java b/LogicUI/src/era/mi/gui/wires/WireConnectionPoint.java deleted file mode 100644 index df82a733..00000000 --- a/LogicUI/src/era/mi/gui/wires/WireConnectionPoint.java +++ /dev/null @@ -1,65 +0,0 @@ -package era.mi.gui.wires; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.eclipse.swt.graphics.Color; - -import era.mi.gui.components.BasicGUIComponent; -import era.mi.logic.wires.Wire; -import era.mi.logic.wires.Wire.ReadEnd; -import net.haspamelodica.swt.helper.gcs.GeneralGC; -import net.haspamelodica.swt.helper.swtobjectwrappers.Point; -import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; - -public class WireConnectionPoint implements BasicGUIComponent -{ - private final Wire wire; - private final List wireEnds; - private final int wiresCrossing; - - public WireConnectionPoint(Wire wire, int wiresCrossing) - { - this.wire = wire; - List wireEndsModifiable = new ArrayList<>(); - for (int i = 0; i < wiresCrossing; i++) - wireEndsModifiable.add(wire.createReadOnlyEnd()); - wireEnds = Collections.unmodifiableList(wireEndsModifiable); - this.wiresCrossing = wiresCrossing; - } - - @Override - public void render(GeneralGC gc) - { - Color oldBG = gc.getBackground(); - if (wire.length == 1) - gc.setBackground(gc.getDevice().getSystemColor(GUIWire.getSWTColorConstantForBit(wire.getValue()))); - gc.fillOval(-1, -1, 2, 2); - gc.setBackground(oldBG); - } - - @Override - public Rectangle getBounds() - { - return new Rectangle(0, 0, 0, 0); - } - - @Override - public int getConnectedWireEndsCount() - { - return wiresCrossing; - } - - @Override - public ReadEnd getConnectedWireEnd(int connectionIndex) - { - return wireEnds.get(connectionIndex); - } - - @Override - public Point getWireEndConnectionPoint(int connectionIndex) - { - return new Point(0, 0); - } -} \ No newline at end of file diff --git a/SWTHelper b/SWTHelper index 6f9a55d4..1b4a52c0 160000 --- a/SWTHelper +++ b/SWTHelper @@ -1 +1 @@ -Subproject commit 6f9a55d483020bad4a5f66de375c3d0d6da585df +Subproject commit 1b4a52c0491e8d22fe6b2352a11d7d82f14c7074