Created first version of ViewLogicModelAdapter
authorDaniel Kirschten <daniel.kirschten@gmx.de>
Wed, 29 May 2019 14:40:21 +0000 (16:40 +0200)
committerDaniel Kirschten <daniel.kirschten@gmx.de>
Wed, 29 May 2019 14:40:21 +0000 (16:40 +0200)
LogicUI/src/era/mi/gui/model/components/GUIAndGate.java
LogicUI/src/era/mi/gui/model/components/SimpleRectangularGUIGate.java
LogicUI/src/era/mi/gui/modeladapter/LogicModelParameters.java [new file with mode: 0644]
LogicUI/src/era/mi/gui/modeladapter/ViewLogicModelAdapter.java
LogicUI/src/era/mi/gui/modeladapter/componentadapters/AndGateAdapter.java [new file with mode: 0644]
LogicUI/src/era/mi/gui/modeladapter/componentadapters/ComponentAdapter.java [new file with mode: 0644]

index 5e5c787..65f1db4 100644 (file)
@@ -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
index 6edf164..eb396cc 100644 (file)
@@ -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<Pin> inputPins;
+       private final List<Pin> 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<Pin> 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 (file)
index 0000000..435f708
--- /dev/null
@@ -0,0 +1,7 @@
+package era.mi.gui.modeladapter;
+
+public class LogicModelParameters
+{
+       public int wireTravelTime;
+       public int gateProcessTime;
+}
\ No newline at end of file
index f005a80..d159b60 100644 (file)
@@ -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<Class<? extends GUIComponent>, ComponentAdapter<? extends GUIComponent>> componentAdapters;
+       static
+       {
+               Map<Class<? extends GUIComponent>, ComponentAdapter<? extends GUIComponent>> 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<Pin, Wire> logicWiresPerPin = convertWires(viewModel.getWires(), params, timeline);
+               Map<Pin, Wire> logicWiresPerPinUnmodifiable = Collections.unmodifiableMap(logicWiresPerPin);
+
+               Map<GUIComponent, Component> 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<Component> logicComponents = new ArrayList<>();
+               logicComponents.addAll(oneToOneComponents.values());
+
+               return timeline;
+       }
+
+       private static Map<Pin, Wire> convertWires(List<GUIWire> wires, LogicModelParameters params, Timeline timeline)
+       {
+               Map<Pin, Set<Pin>> connectedPinGroups = getConnectedPinGroups(wires);
+               Map<Pin, Wire> logicWiresPerPin = createLogicWires(params, timeline, connectedPinGroups);
+               setGUIWiresLogicModelBinding(wires, logicWiresPerPin);
+               return logicWiresPerPin;
+       }
+
+       private static Map<Pin, Wire> createLogicWires(LogicModelParameters params, Timeline timeline, Map<Pin, Set<Pin>> connectedPinGroups)
+       {
+               Map<Pin, Wire> logicWiresPerPin = new HashMap<>();
+               Map<Set<Pin>, Wire> logicWiresPerPinGroup = new HashMap<>();
+               for (Entry<Pin, Set<Pin>> 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<GUIWire> wires, Map<Pin, Wire> logicWiresPerPin)
+       {
+               Map<Wire, ReadEnd> 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<Pin, Set<Pin>> getConnectedPinGroups(List<GUIWire> wires)
+       {
+               Map<Pin, Set<Pin>> connectedPinsPerPin = new HashMap<>();
+               wires.forEach(wire ->
+               {
+                       Pin pin1 = wire.getPin1();
+                       Pin pin2 = wire.getPin2();
+
+                       Set<Pin> pin1ConnectedPins = connectedPinsPerPin.putIfAbsent(pin1, new HashSet<>());
+                       Set<Pin> 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 <G extends GUIComponent> Component createAndLinkComponent(Timeline timeline, LogicModelParameters params,
+                       GUIComponent guiComponent, Map<Pin, Wire> logicWiresPerPin, ComponentAdapter<G> 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 (file)
index 0000000..3b34d90
--- /dev/null
@@ -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<GUIAndGate>
+{
+       @Override
+       public Component createAndLinkComponent(Timeline timeline, LogicModelParameters params, GUIAndGate guiComponent,
+                       Map<Pin, Wire> logicWiresPerPin)
+       {
+               ReadWriteEnd out = logicWiresPerPin.get(guiComponent.getOutputPin()).createReadWriteEnd();
+               List<Pin> 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 (file)
index 0000000..8598fa8
--- /dev/null
@@ -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<G extends GUIComponent>
+{
+       public Component createAndLinkComponent(Timeline timeline, LogicModelParameters params, G guiComponent,
+                       Map<Pin, Wire> logicWiresPerPin);
+}
\ No newline at end of file