From e9b72fcd41c45807f9e126cae897c9b17e79961d Mon Sep 17 00:00:00 2001 From: Daniel Kirschten Date: Wed, 29 May 2019 16:40:21 +0200 Subject: [PATCH] Created first version of ViewLogicModelAdapter --- .../mi/gui/model/components/GUIAndGate.java | 2 +- .../components/SimpleRectangularGUIGate.java | 13 ++ .../modeladapter/LogicModelParameters.java | 7 ++ .../modeladapter/ViewLogicModelAdapter.java | 114 ++++++++++++++++++ .../componentadapters/AndGateAdapter.java | 29 +++++ .../componentadapters/ComponentAdapter.java | 16 +++ 6 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 LogicUI/src/era/mi/gui/modeladapter/LogicModelParameters.java create mode 100644 LogicUI/src/era/mi/gui/modeladapter/componentadapters/AndGateAdapter.java create mode 100644 LogicUI/src/era/mi/gui/modeladapter/componentadapters/ComponentAdapter.java diff --git a/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java b/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java index 5e5c787a..65f1db4e 100644 --- a/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java +++ b/LogicUI/src/era/mi/gui/model/components/GUIAndGate.java @@ -7,6 +7,6 @@ public class GUIAndGate extends SimpleRectangularGUIGate public GUIAndGate(ViewModel model, int logicWidth) { super(model, logicWidth, "&", false); - setInputCount(2); + setInputCount(2);// TODO make variable } } \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/model/components/SimpleRectangularGUIGate.java b/LogicUI/src/era/mi/gui/model/components/SimpleRectangularGUIGate.java index 6edf1647..eb396cca 100644 --- a/LogicUI/src/era/mi/gui/model/components/SimpleRectangularGUIGate.java +++ b/LogicUI/src/era/mi/gui/model/components/SimpleRectangularGUIGate.java @@ -1,6 +1,7 @@ package era.mi.gui.model.components; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import era.mi.gui.model.ViewModel; @@ -25,6 +26,7 @@ public class SimpleRectangularGUIGate extends GUIComponent private MovablePin outputPin; private final List inputPins; + private final List inputPinsUnmodifiable; protected SimpleRectangularGUIGate(ViewModel model, int logicWidth, String label, boolean isInverted) { @@ -36,6 +38,7 @@ public class SimpleRectangularGUIGate extends GUIComponent this.outputPin = new MovablePin(this, logicWidth, width, 0); addPin(outputPin); this.inputPins = new ArrayList<>(); + this.inputPinsUnmodifiable = Collections.unmodifiableList(inputPins); setInputCount(1); } @@ -56,6 +59,16 @@ public class SimpleRectangularGUIGate extends GUIComponent outputPin.setRelPos(width, inputCount * pinDistance / 2); } + public Pin getOutputPin() + { + return outputPin; + } + + public List getInputPins() + { + return inputPinsUnmodifiable; + } + @Override public void render(GeneralGC gc, Rectangle visibleRegion) { diff --git a/LogicUI/src/era/mi/gui/modeladapter/LogicModelParameters.java b/LogicUI/src/era/mi/gui/modeladapter/LogicModelParameters.java new file mode 100644 index 00000000..435f7086 --- /dev/null +++ b/LogicUI/src/era/mi/gui/modeladapter/LogicModelParameters.java @@ -0,0 +1,7 @@ +package era.mi.gui.modeladapter; + +public class LogicModelParameters +{ + public int wireTravelTime; + public int gateProcessTime; +} \ 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 index f005a80b..d159b605 100644 --- a/LogicUI/src/era/mi/gui/modeladapter/ViewLogicModelAdapter.java +++ b/LogicUI/src/era/mi/gui/modeladapter/ViewLogicModelAdapter.java @@ -1,6 +1,120 @@ package era.mi.gui.modeladapter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +import era.mi.gui.model.ViewModel; +import era.mi.gui.model.components.GUIAndGate; +import era.mi.gui.model.components.GUIComponent; +import era.mi.gui.model.wires.GUIWire; +import era.mi.gui.model.wires.Pin; +import era.mi.gui.model.wires.WireCrossPoint; +import era.mi.gui.modeladapter.componentadapters.AndGateAdapter; +import era.mi.gui.modeladapter.componentadapters.ComponentAdapter; +import era.mi.logic.components.Component; +import era.mi.logic.timeline.Timeline; +import era.mi.logic.wires.Wire; +import era.mi.logic.wires.Wire.ReadEnd; + public class ViewLogicModelAdapter { + private final static Map, ComponentAdapter> componentAdapters; + static + { + Map, ComponentAdapter> componentAdaptersModifiable = new HashMap<>(); + componentAdaptersModifiable.put(GUIAndGate.class, new AndGateAdapter()); + // TODO list all "primitive" adapters here + componentAdapters = Collections.unmodifiableMap(componentAdaptersModifiable); + } + + public static Timeline convert(ViewModel viewModel, LogicModelParameters params) + { + // TODO replace Timeline with LogicModel as soon as it exists + Timeline timeline = new Timeline(10); + + Map logicWiresPerPin = convertWires(viewModel.getWires(), params, timeline); + Map logicWiresPerPinUnmodifiable = Collections.unmodifiableMap(logicWiresPerPin); + + Map oneToOneComponents = new HashMap<>(); + for (GUIComponent guiComp : viewModel.getComponents()) + { + // WireCrossPoints just vanish + if (!(guiComp instanceof WireCrossPoint)) + oneToOneComponents.put(guiComp, createAndLinkComponent(timeline, params, guiComp, logicWiresPerPinUnmodifiable, + componentAdapters.get(guiComp.getClass()))); + } + + // TODO handle complex components + + List logicComponents = new ArrayList<>(); + logicComponents.addAll(oneToOneComponents.values()); + + return timeline; + } + + private static Map convertWires(List wires, LogicModelParameters params, Timeline timeline) + { + Map> connectedPinGroups = getConnectedPinGroups(wires); + Map logicWiresPerPin = createLogicWires(params, timeline, connectedPinGroups); + setGUIWiresLogicModelBinding(wires, logicWiresPerPin); + return logicWiresPerPin; + } + + private static Map createLogicWires(LogicModelParameters params, Timeline timeline, Map> connectedPinGroups) + { + Map logicWiresPerPin = new HashMap<>(); + Map, Wire> logicWiresPerPinGroup = new HashMap<>(); + for (Entry> e : connectedPinGroups.entrySet()) + logicWiresPerPin.put(e.getKey(), logicWiresPerPinGroup.computeIfAbsent(e.getValue(), + set -> new Wire(timeline, e.getKey().logicWidth, params.wireTravelTime))); + return logicWiresPerPin; + } + + private static void setGUIWiresLogicModelBinding(List wires, Map logicWiresPerPin) + { + Map guiWireSharedReadEnd = logicWiresPerPin.values().stream() + .collect(Collectors.toMap(Function.identity(), Wire::createReadOnlyEnd)); + for (GUIWire guiWire : wires) + guiWire.setLogicModelBinding(guiWireSharedReadEnd.get(logicWiresPerPin.get(guiWire.getPin1()))); + } + + private static Map> getConnectedPinGroups(List wires) + { + Map> connectedPinsPerPin = new HashMap<>(); + wires.forEach(wire -> + { + Pin pin1 = wire.getPin1(); + Pin pin2 = wire.getPin2(); + + Set pin1ConnectedPins = connectedPinsPerPin.putIfAbsent(pin1, new HashSet<>()); + Set pin2ConnectedPins = connectedPinsPerPin.putIfAbsent(pin2, new HashSet<>()); + + pin1ConnectedPins.addAll(pin2ConnectedPins); + pin1ConnectedPins.add(pin1); + pin1ConnectedPins.add(pin2); + + pin2ConnectedPins.forEach(pin -> connectedPinsPerPin.put(pin, pin1ConnectedPins)); + }); + return connectedPinsPerPin; + } + + @SuppressWarnings("unchecked") + private static Component createAndLinkComponent(Timeline timeline, LogicModelParameters params, + GUIComponent guiComponent, Map logicWiresPerPin, ComponentAdapter adapter) + { + return adapter.createAndLinkComponent(timeline, params, (G) guiComponent, logicWiresPerPin); + } + private ViewLogicModelAdapter() + { + throw new UnsupportedOperationException("No ViewLogicModelConverter instances"); + } } \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/modeladapter/componentadapters/AndGateAdapter.java b/LogicUI/src/era/mi/gui/modeladapter/componentadapters/AndGateAdapter.java new file mode 100644 index 00000000..3b34d900 --- /dev/null +++ b/LogicUI/src/era/mi/gui/modeladapter/componentadapters/AndGateAdapter.java @@ -0,0 +1,29 @@ +package era.mi.gui.modeladapter.componentadapters; + +import java.util.List; +import java.util.Map; + +import era.mi.gui.model.components.GUIAndGate; +import era.mi.gui.model.wires.Pin; +import era.mi.gui.modeladapter.LogicModelParameters; +import era.mi.logic.components.Component; +import era.mi.logic.components.gates.AndGate; +import era.mi.logic.timeline.Timeline; +import era.mi.logic.wires.Wire; +import era.mi.logic.wires.Wire.ReadEnd; +import era.mi.logic.wires.Wire.ReadWriteEnd; + +public class AndGateAdapter implements ComponentAdapter +{ + @Override + public Component createAndLinkComponent(Timeline timeline, LogicModelParameters params, GUIAndGate guiComponent, + Map logicWiresPerPin) + { + ReadWriteEnd out = logicWiresPerPin.get(guiComponent.getOutputPin()).createReadWriteEnd(); + List inputPins = guiComponent.getInputPins(); + ReadEnd[] ins = new ReadEnd[inputPins.size()]; + for (int i = 0; i < inputPins.size(); i++) + ins[i] = logicWiresPerPin.get(inputPins.get(i)).createReadOnlyEnd(); + return new AndGate(timeline, params.gateProcessTime, out, ins); + } +} \ No newline at end of file diff --git a/LogicUI/src/era/mi/gui/modeladapter/componentadapters/ComponentAdapter.java b/LogicUI/src/era/mi/gui/modeladapter/componentadapters/ComponentAdapter.java new file mode 100644 index 00000000..8598fa83 --- /dev/null +++ b/LogicUI/src/era/mi/gui/modeladapter/componentadapters/ComponentAdapter.java @@ -0,0 +1,16 @@ +package era.mi.gui.modeladapter.componentadapters; + +import java.util.Map; + +import era.mi.gui.model.components.GUIComponent; +import era.mi.gui.model.wires.Pin; +import era.mi.gui.modeladapter.LogicModelParameters; +import era.mi.logic.components.Component; +import era.mi.logic.timeline.Timeline; +import era.mi.logic.wires.Wire; + +public interface ComponentAdapter +{ + public Component createAndLinkComponent(Timeline timeline, LogicModelParameters params, G guiComponent, + Map logicWiresPerPin); +} \ No newline at end of file -- 2.17.1