Fixed a bug in Am2900; created dlatch8/80; relayouted some components
[Mograsim.git] / net.mograsim.logic.model / src / net / mograsim / logic / model / model / components / submodels / SimpleRectangularSubmodelComponent.java
1 package net.mograsim.logic.model.model.components.submodels;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.HashSet;
7 import java.util.List;
8
9 import net.mograsim.logic.model.model.LogicModelModifiable;
10 import net.mograsim.logic.model.model.wires.MovablePin;
11 import net.mograsim.logic.model.model.wires.Pin;
12 import net.mograsim.logic.model.model.wires.PinUsage;
13 import net.mograsim.logic.model.snippets.outlinerenderers.DefaultOutlineRenderer;
14 import net.mograsim.logic.model.snippets.symbolrenderers.SimpleRectangularLikeSymbolRenderer;
15 import net.mograsim.logic.model.snippets.symbolrenderers.SimpleRectangularLikeSymbolRenderer.SimpleRectangularLikeParams;
16
17 public class SimpleRectangularSubmodelComponent extends SubmodelComponent
18 {
19         public static final double width = 35;
20         public static final double pinDistance = 10;
21         public static final double pinNameMargin = .5;
22         public static final double labelFontHeight = 5;
23         public static final double pinNameFontHeight = 3.5;
24
25         public final String label;
26         protected final int logicWidth;
27
28         private final List<String> inputPinNames;
29         private final List<String> inputPinNamesUnmodifiable;
30         private final List<String> outputPinNames;
31         private final List<String> outputPinNamesUnmodifiable;
32
33         public SimpleRectangularSubmodelComponent(LogicModelModifiable model, int logicWidth, String label)
34         {
35                 this(model, logicWidth, label, null);
36         }
37
38         public SimpleRectangularSubmodelComponent(LogicModelModifiable model, int logicWidth, String label, String name)
39         {
40                 this(model, logicWidth, label, name, true);
41         }
42
43         protected SimpleRectangularSubmodelComponent(LogicModelModifiable model, int logicWidth, String label, String name, boolean callInit)
44         {
45                 super(model, name, false);
46                 this.label = label;
47                 this.logicWidth = logicWidth;
48                 this.inputPinNames = new ArrayList<>();
49                 this.inputPinNamesUnmodifiable = Collections.unmodifiableList(inputPinNames);
50                 this.outputPinNames = new ArrayList<>();
51                 this.outputPinNamesUnmodifiable = Collections.unmodifiableList(outputPinNames);
52
53                 SimpleRectangularLikeParams rendererParams = new SimpleRectangularLikeParams();
54                 rendererParams.centerText = label;
55                 rendererParams.centerTextHeight = labelFontHeight;
56                 rendererParams.horizontalComponentCenter = width / 2;
57                 rendererParams.pinLabelHeight = pinNameFontHeight;
58                 rendererParams.pinLabelMargin = pinNameMargin;
59                 setSymbolRenderer(new SimpleRectangularLikeSymbolRenderer(this, rendererParams));
60                 setOutlineRenderer(new DefaultOutlineRenderer(this));
61
62                 if (callInit)
63                         init();
64         }
65
66         protected void setInputPins(String... pinNames)
67         {
68                 setIOPins(0, inputPinNames, outputPinNames, PinUsage.INPUT, pinNames);
69         }
70
71         protected void setOutputPins(String... pinNames)
72         {
73                 setIOPins(width, outputPinNames, inputPinNames, PinUsage.OUTPUT, pinNames);
74         }
75
76         private void setIOPins(double relX, List<String> pinNamesListThisSide, List<String> pinNamesListOtherSide, PinUsage usage,
77                         String... newPinNames)
78         {
79                 int inputCount = newPinNames.length;
80                 List<String> newPinNamesList = Arrays.asList(newPinNames);
81                 if (new HashSet<>(newPinNamesList).size() != inputCount)
82                         throw new IllegalArgumentException("Pin names contain duplicates");
83                 for (String pinName : newPinNamesList)
84                         if (pinNamesListOtherSide.contains(pinName))
85                                 throw new IllegalArgumentException("Can't add pin. There is a pin on the other side with the same name: " + pinName);
86                 super.setSize(width, Math.max(inputCount, pinNamesListOtherSide.size()) * pinDistance);
87                 for (int i = 0; i < inputCount; i++)
88                 {
89                         String pinName = newPinNames[i];
90                         int oldPinIndex = pinNamesListThisSide.indexOf(pinName);
91                         if (oldPinIndex == -1)
92                                 super.addSubmodelInterface(
93                                                 new MovablePin(model, this, pinName, logicWidth, usage, relX, pinDistance / 2 + i * pinDistance));
94                         else
95                                 getSupermodelMovablePin(pinName).setRelPos(relX, pinDistance / 2 + i * pinDistance);
96                 }
97                 for (String pinName : pinNamesListThisSide)
98                         if (!newPinNamesList.contains(pinName))
99                                 super.removeSubmodelInterface(pinName);
100                 pinNamesListThisSide.clear();
101                 pinNamesListThisSide.addAll(newPinNamesList);
102         }
103
104         public List<String> getInputPinNames()
105         {
106                 return inputPinNamesUnmodifiable;
107         }
108
109         public List<String> getOutputPinNames()
110         {
111                 return outputPinNamesUnmodifiable;
112         }
113
114         @Override
115         protected Pin addSubmodelInterface(MovablePin supermodelPin)
116         {
117                 throw new UnsupportedOperationException(
118                                 "Can't add submodel interfaces to a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
119         }
120
121         @Override
122         protected void removeSubmodelInterface(String name)
123         {
124                 throw new UnsupportedOperationException(
125                                 "Can't remove submodel interfaces of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
126         }
127
128         @Override
129         protected void setSize(double width, double height)
130         {
131                 throw new UnsupportedOperationException(
132                                 "Can't set the size of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
133         }
134 }