1 package net.mograsim.logic.model.model.components.atomic;
3 import org.eclipse.swt.SWT;
5 import net.haspamelodica.swt.helper.gcs.GeneralGC;
6 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
7 import net.mograsim.logic.core.types.BitVectorFormatter;
8 import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
9 import net.mograsim.logic.model.model.LogicModelModifiable;
10 import net.mograsim.logic.model.model.components.ModelComponent;
11 import net.mograsim.logic.model.model.components.Orientation;
12 import net.mograsim.logic.model.model.components.OrientationCalculator;
13 import net.mograsim.logic.model.model.wires.Pin;
14 import net.mograsim.logic.model.model.wires.PinUsage;
15 import net.mograsim.logic.model.modeladapter.LogicCoreAdapter;
16 import net.mograsim.logic.model.modeladapter.componentadapters.SplitterAdapter;
17 import net.mograsim.logic.model.serializing.IdentifyParams;
18 import net.mograsim.logic.model.serializing.IndirectModelComponentCreator;
19 import net.mograsim.logic.model.util.JsonHandler;
20 import net.mograsim.preferences.ColorDefinition;
21 import net.mograsim.preferences.ColorManager;
22 import net.mograsim.preferences.Preferences;
24 public class ModelSplitter extends ModelComponent
26 private static final double width = 10;
27 private static final double heightPerPin = 10;
29 private final double heightWithoutOC;
30 public final int logicWidth;
31 private final OrientationCalculator oc;
32 private final Pin inputPin;
34 private ReadEnd inputEnd;
35 private final ReadEnd[] outputEnds;
37 public ModelSplitter(LogicModelModifiable model, SplitterParams params)
39 this(model, params, null);
42 public ModelSplitter(LogicModelModifiable model, SplitterParams params, String name)
44 super(model, name, false);
45 this.logicWidth = params.logicWidth;
46 this.oc = new OrientationCalculator(toggleLeftDownAlt(params.orientation), width,
47 this.heightWithoutOC = (logicWidth - 1) * heightPerPin);
48 setSize(oc.width(), oc.height());
49 double inLineY = (logicWidth - 1) * heightPerPin / 2;
50 addPin(this.inputPin = new Pin(model, this, "I", logicWidth, PinUsage.TRISTATE, oc.newX(0, inLineY), oc.newY(0, inLineY)));
51 double outputHeight = (logicWidth - 1) * heightPerPin;
52 for (int i = 0; i < logicWidth; i++, outputHeight -= 10)
53 addPin(new Pin(model, this, "O" + i, 1, PinUsage.TRISTATE, oc.newX(width, outputHeight), oc.newY(width, outputHeight)));
54 outputEnds = new ReadEnd[logicWidth];
60 public void render(GeneralGC gc, Rectangle visibleRegion)
62 double posX = getPosX();
63 double posY = getPosY();
65 ColorDefinition c = BitVectorFormatter.formatAsColor(inputEnd);
67 gc.setForeground(ColorManager.current().toColor(c));
69 Preferences.current().getDouble("net.mograsim.logic.model.linewidth.wire." + (logicWidth == 1 ? "singlebit" : "multibit")));
70 double inLineY = heightWithoutOC / 2;
71 gc.drawLine(posX + oc.newX(0, inLineY), posY + oc.newY(0, inLineY), posX + oc.newX(width / 2, inLineY),
72 posY + oc.newY(width / 2, inLineY));
73 gc.setLineWidth(Preferences.current().getDouble("net.mograsim.logic.model.linewidth.wire.singlebit"));
74 double outputHeight = 0;
75 for (int i = 0; i < logicWidth; i++, outputHeight += 10)
77 c = BitVectorFormatter.formatAsColor(outputEnds[i]);
79 gc.setForeground(ColorManager.current().toColor(c));
80 gc.drawLine(posX + oc.newX(width / 2, outputHeight), posY + oc.newY(width / 2, outputHeight),
81 posX + oc.newX(width, outputHeight), posY + oc.newY(width, outputHeight));
83 gc.setForeground(Preferences.current().getColor("net.mograsim.logic.model.color.foreground"));
84 int oldLineCap = gc.getLineCap();
85 int lineJoin = gc.getLineJoin();
86 // TODO find better "replacement" for JOIN_BEVEL
87 // TODO it looks weird that the vertical line is thinner than the single multibit wire.
88 gc.setLineCap(lineJoin == SWT.JOIN_MITER ? SWT.CAP_SQUARE : lineJoin == SWT.JOIN_ROUND ? SWT.CAP_ROUND : SWT.CAP_SQUARE);
89 gc.drawLine(posX + oc.newX(width / 2, 0), posY + oc.newY(width / 2, 0), posX + oc.newX(width / 2, heightWithoutOC),
90 posY + oc.newY(width / 2, heightWithoutOC));
91 gc.setLineWidth(Preferences.current().getDouble("net.mograsim.logic.model.linewidth.default"));
92 gc.setLineCap(oldLineCap);
96 public String getIDForSerializing(IdentifyParams idParams)
102 public SplitterParams getParamsForSerializing(IdentifyParams idParams)
104 SplitterParams splitterParams = new SplitterParams();
105 splitterParams.logicWidth = logicWidth;
106 splitterParams.orientation = toggleLeftDownAlt(oc.getOrientation());
107 return splitterParams;
110 public void setCoreModelBinding(ReadEnd inputEnd, ReadEnd[] outputEnds)
112 this.inputEnd = inputEnd;
113 System.arraycopy(outputEnds, 0, this.outputEnds, 0, logicWidth);
116 public Pin getInputPin()
122 * Used to leave bit order intuitive (MSB left or on top)
124 private static Orientation toggleLeftDownAlt(Orientation orientation)
126 // TODO if we upgrade to Java 12, replace with switch-expression
130 return Orientation.LEFT_ALT;
132 return Orientation.LEFT;
134 return Orientation.DOWN_ALT;
136 return Orientation.DOWN;
142 public static class SplitterParams
144 public int logicWidth;
145 public Orientation orientation;
150 LogicCoreAdapter.addComponentAdapter(new SplitterAdapter());
151 IndirectModelComponentCreator.setComponentSupplier(ModelSplitter.class.getCanonicalName(),
152 (m, p, n) -> new ModelSplitter(m, JsonHandler.fromJsonTree(p, SplitterParams.class), n));