X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=LogicUI%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fui%2Fmodeladapter%2FViewLogicModelAdapter.java;fp=LogicUI%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fui%2Fmodeladapter%2FViewLogicModelAdapter.java;h=6f4e7b739d55e077cc91161d4f76333fa680ecdc;hb=0009789a8df6b8d4562b6e1cbfa75102a7516ea8;hp=0000000000000000000000000000000000000000;hpb=a28f7aa0dab4248e99159c5a647676170cb17a4e;p=Mograsim.git diff --git a/LogicUI/src/net/mograsim/logic/ui/modeladapter/ViewLogicModelAdapter.java b/LogicUI/src/net/mograsim/logic/ui/modeladapter/ViewLogicModelAdapter.java new file mode 100644 index 00000000..6f4e7b73 --- /dev/null +++ b/LogicUI/src/net/mograsim/logic/ui/modeladapter/ViewLogicModelAdapter.java @@ -0,0 +1,146 @@ +package net.mograsim.logic.ui.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 net.mograsim.logic.ui.model.ViewModel; +import net.mograsim.logic.ui.model.components.GUIAndGate; +import net.mograsim.logic.ui.model.components.GUIComponent; +import net.mograsim.logic.ui.model.components.GUINotGate; +import net.mograsim.logic.ui.model.components.GUIOrGate; +import net.mograsim.logic.ui.model.wires.GUIWire; +import net.mograsim.logic.ui.model.wires.Pin; +import net.mograsim.logic.ui.model.wires.WireCrossPoint; +import net.mograsim.logic.ui.modeladapter.componentadapters.ComponentAdapter; +import net.mograsim.logic.ui.modeladapter.componentadapters.ManualSwitchAdapter; +import net.mograsim.logic.ui.modeladapter.componentadapters.SimpleGateAdapter; +import net.mograsim.logic.core.components.Component; +import net.mograsim.logic.core.components.gates.AndGate; +import net.mograsim.logic.core.components.gates.NotGate; +import net.mograsim.logic.core.components.gates.OrGate; +import net.mograsim.logic.core.timeline.Timeline; +import net.mograsim.logic.core.wires.Wire; +import net.mograsim.logic.core.wires.Wire.ReadEnd; + +public class ViewLogicModelAdapter +{ + private final static Map, ComponentAdapter> componentAdapters; + static + { + Set> componentAdaptersModifiable = new HashSet<>(); + componentAdaptersModifiable.add(new SimpleGateAdapter<>(GUIOrGate.class, OrGate::new)); + componentAdaptersModifiable.add(new SimpleGateAdapter<>(GUIAndGate.class, AndGate::new)); + componentAdaptersModifiable.add(new SimpleGateAdapter<>(GUINotGate.class, (t, p, o, i) -> new NotGate(t, p, i[0], o))); + componentAdaptersModifiable.add(new ManualSwitchAdapter()); + // TODO list all "primitive" adapters here + componentAdapters = Collections.unmodifiableMap( + componentAdaptersModifiable.stream().collect(Collectors.toMap(ComponentAdapter::getSupportedClass, Function.identity()))); + } + + 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.getComponents().stream().flatMap(component -> component.getPins().stream()).collect(Collectors.toSet()), + viewModel.getWires(), params, timeline); + Map logicWiresPerPinUnmodifiable = Collections.unmodifiableMap(logicWiresPerPin); + + Map oneToOneComponents = new HashMap<>(); + for (GUIComponent guiComp : viewModel.getComponents()) + { + if (!(guiComp instanceof WireCrossPoint)) + oneToOneComponents.put(guiComp, createAndLinkComponent(timeline, params, guiComp, logicWiresPerPinUnmodifiable, + componentAdapters.get(guiComp.getClass()))); + else + { + WireCrossPoint guiCompCasted = (WireCrossPoint) guiComp; + guiCompCasted.setLogicModelBinding(logicWiresPerPin.get(guiCompCasted.getPin()).createReadOnlyEnd()); + } + } + + // TODO handle complex components + + List logicComponents = new ArrayList<>(); + logicComponents.addAll(oneToOneComponents.values()); + + return timeline; + } + + private static Map convertWires(Set allPins, List wires, LogicModelParameters params, Timeline timeline) + { + Map> connectedPinGroups = getConnectedPinGroups(allPins, 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().distinct() + .collect(Collectors.toMap(Function.identity(), Wire::createReadOnlyEnd)); + for (GUIWire guiWire : wires) + guiWire.setLogicModelBinding(guiWireSharedReadEnd.get(logicWiresPerPin.get(guiWire.getPin1()))); + } + + private static Map> getConnectedPinGroups(Set allPins, List wires) + { + Map> connectedPinsPerPin = new HashMap<>(); + + for (Pin p : allPins) + { + HashSet connectedPins = new HashSet<>(); + connectedPins.add(p); + connectedPinsPerPin.put(p, connectedPins); + } + + wires.forEach(wire -> + { + Pin pin1 = wire.getPin1(); + Pin pin2 = wire.getPin2(); + + Set pin1ConnectedPins = connectedPinsPerPin.get(pin1); + Set pin2ConnectedPins = connectedPinsPerPin.get(pin2); + + 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) + { + if (adapter == null) + throw new IllegalArgumentException("Unknown component class: " + guiComponent.getClass()); + return adapter.createAndLinkComponent(timeline, params, (G) guiComponent, logicWiresPerPin); + } + + private ViewLogicModelAdapter() + { + throw new UnsupportedOperationException("No ViewLogicModelConverter instances"); + } +} \ No newline at end of file