1 package net.mograsim.logic.ui.model.components;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.HashSet;
9 import java.util.TreeMap;
11 import net.haspamelodica.swt.helper.gcs.GeneralGC;
12 import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
13 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
14 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
15 import net.mograsim.logic.ui.model.ViewModelModifiable;
16 import net.mograsim.logic.ui.model.wires.Pin;
18 public class SimpleRectangularSubmodelComponent extends SubmodelComponent
20 public static String kLabel = "label", kInCount = "input_count", kOutCount = "output_count", kLogicWidth = "logic_width";
22 private static final double width = 35;
23 private static final double pinDistance = 10;
24 private static final double pinNameMargin = .5;
25 private static final double labelFontHeight = 5;
26 private static final double pinNameFontHeight = 3.5;
28 private final String label;
29 protected final int logicWidth;
31 private final List<String> inputPinNames;
32 private final List<String> inputPinNamesUnmodifiable;
33 private final List<String> outputPinNames;
34 private final List<String> outputPinNamesUnmodifiable;
36 protected SimpleRectangularSubmodelComponent(ViewModelModifiable model, int logicWidth, String label)
40 this.logicWidth = logicWidth;
41 this.inputPinNames = new ArrayList<>();
42 this.inputPinNamesUnmodifiable = Collections.unmodifiableList(inputPinNames);
43 this.outputPinNames = new ArrayList<>();
44 this.outputPinNamesUnmodifiable = Collections.unmodifiableList(outputPinNames);
47 protected void setInputPins(String... pinNames)
49 setIOPins(0, inputPinNames, outputPinNames, pinNames);
52 protected void setOutputPins(String... pinNames)
54 setIOPins(width, outputPinNames, inputPinNames, pinNames);
57 private void setIOPins(double relX, List<String> pinNamesListThisSide, List<String> pinNamesListOtherSide, String... newPinNames)
59 int inputCount = newPinNames.length;
60 List<String> newPinNamesList = Arrays.asList(newPinNames);
61 if (new HashSet<>(newPinNamesList).size() != inputCount)
62 throw new IllegalArgumentException("Pin names contain duplicates");
63 for (String pinName : newPinNamesList)
64 if (pinNamesListOtherSide.contains(pinName))
65 throw new IllegalArgumentException("Can't add pin. There is a pin on the other side with the same name: " + pinName);
66 super.setSize(width, Math.max(inputCount, pinNamesListOtherSide.size()) * pinDistance);
67 for (int i = 0; i < inputCount; i++)
69 String pinName = newPinNames[i];
70 int oldPinIndex = pinNamesListThisSide.indexOf(pinName);
71 if (oldPinIndex == -1)
72 super.addSubmodelInterface(pinName, logicWidth, relX, pinDistance / 2 + i * pinDistance);
74 getSupermodelMovablePin(pinName).setRelPos(relX, pinDistance / 2 + i * pinDistance);
76 for (String pinName : pinNamesListThisSide)
77 if (!newPinNamesList.contains(pinName))
78 super.removeSubmodelInterface(pinName);
79 pinNamesListThisSide.clear();
80 pinNamesListThisSide.addAll(newPinNamesList);
83 public List<String> getInputPinNames()
85 return inputPinNamesUnmodifiable;
88 public List<String> getOutputPinNames()
90 return outputPinNamesUnmodifiable;
94 protected void renderSymbol(GeneralGC gc, Rectangle visibleRegion)
96 double posX = getBounds().x;
97 double posY = getBounds().y;
99 Font oldFont = gc.getFont();
100 gc.setFont(new Font(oldFont.getName(), labelFontHeight, oldFont.getStyle()));
101 Point textExtent = gc.textExtent(label);
102 gc.drawText(label, posX + (getBounds().width - textExtent.x) / 2, posY + (getBounds().height - textExtent.y) / 2, true);
103 gc.setFont(new Font(oldFont.getName(), pinNameFontHeight, oldFont.getStyle()));
104 for (int i = 0; i < inputPinNames.size(); i++)
106 String pinName = inputPinNames.get(i);
107 textExtent = gc.textExtent(pinName);
108 gc.drawText(pinName, posX + pinNameMargin, posY + i * pinDistance + (pinDistance - textExtent.y) / 2, true);
110 for (int i = 0; i < outputPinNames.size(); i++)
112 String pinName = outputPinNames.get(i);
113 textExtent = gc.textExtent(pinName);
114 gc.drawText(pinName, posX + width - textExtent.x - pinNameMargin, posY + i * pinDistance + (pinDistance - textExtent.y) / 2,
121 protected void renderOutline(GeneralGC gc, Rectangle visibleRegion)
123 gc.drawRectangle(getBounds());
127 public SubmodelComponentParams calculateParams()
129 SubmodelComponentParams ret = super.calculateParams();
130 ret.type = SimpleRectangularSubmodelComponent.class.getSimpleName();
131 Map<String, Object> m = new TreeMap<>();
132 m.put(kLabel, label);
133 m.put(kInCount, inputPinNames.size());
134 m.put(kOutCount, outputPinNames.size());
135 m.put(kLogicWidth, logicWidth);
141 protected Pin addSubmodelInterface(String name, int logicWidth, double relX, double relY)
143 throw new UnsupportedOperationException(
144 "Can't add submodel interfaces to a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
148 protected void removeSubmodelInterface(String name)
150 throw new UnsupportedOperationException(
151 "Can't remove submodel interfaces of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
155 protected void setSize(double width, double height)
157 throw new UnsupportedOperationException(
158 "Can't set the size of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");