f28723d23b50c063e68ab2fbdf278dd92fc87378
[Mograsim.git] / net.mograsim.logic.ui / src / net / mograsim / logic / ui / model / components / SimpleRectangularSubmodelComponent.java
1 package net.mograsim.logic.ui.model.components;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.TreeMap;
8
9 import net.haspamelodica.swt.helper.gcs.GeneralGC;
10 import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
11 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
12 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
13 import net.mograsim.logic.ui.model.ViewModelModifiable;
14 import net.mograsim.logic.ui.model.wires.Pin;
15
16 public class SimpleRectangularSubmodelComponent extends SubmodelComponent
17 {
18         public static String kLabel = "label", kInCount = "input_count", kOutCount = "output_count", kLogicWidth = "logic_width";
19
20         private static final double width = 35;
21         private static final double pinDistance = 10;
22         private static final double pinNameMargin = .5;
23         private static final double labelFontHeight = 5;
24         private static final double pinNameFontHeight = 3.5;
25
26         private final String label;
27         protected final int logicWidth;
28
29         private final List<Pin> inputSupermodelPins;
30         private final List<Pin> inputSupermodelPinsUnmodifiable;
31         private final List<Pin> outputSupermodelPins;
32         private final List<Pin> outputSupermodelPinsUnmodifiable;
33         private final List<Pin> inputSubmodelPins;
34         private final List<Pin> inputSubmodelPinsUnmodifiable;
35         private final List<Pin> outputSubmodelPins;
36         private final List<Pin> outputSubmodelPinsUnmodifiable;
37
38         protected SimpleRectangularSubmodelComponent(ViewModelModifiable model, int logicWidth, String label)
39         {
40                 super(model);
41                 this.label = label;
42                 this.logicWidth = logicWidth;
43                 this.inputSupermodelPins = new ArrayList<>();
44                 this.inputSupermodelPinsUnmodifiable = Collections.unmodifiableList(inputSupermodelPins);
45                 this.outputSupermodelPins = new ArrayList<>();
46                 this.outputSupermodelPinsUnmodifiable = Collections.unmodifiableList(outputSupermodelPins);
47                 this.inputSubmodelPins = new ArrayList<>();
48                 this.inputSubmodelPinsUnmodifiable = Collections.unmodifiableList(inputSubmodelPins);
49                 this.outputSubmodelPins = new ArrayList<>();
50                 this.outputSubmodelPinsUnmodifiable = Collections.unmodifiableList(outputSubmodelPins);
51         }
52
53         protected void setInputPins(String... pinNames)
54         {
55                 int inputCount = pinNames.length;
56                 int oldInputCount = inputSupermodelPins.size();
57                 double height = Math.max(inputCount, outputSupermodelPins.size()) * pinDistance;
58                 super.setSize(width, height);
59                 if (oldInputCount > inputCount)
60                         while (inputSupermodelPins.size() > inputCount)
61                         {
62                                 inputSubmodelPins.remove(inputCount);
63                                 super.removeSubmodelInterface(inputSupermodelPins.remove(inputCount));
64                         }
65                 else if (oldInputCount < inputCount)
66                         for (int i = oldInputCount; i < inputCount; i++)
67                         {
68                                 Pin submodelPin = super.addSubmodelInterface(pinNames[i], logicWidth, 0, pinDistance / 2 + i * pinDistance);
69                                 inputSubmodelPins.add(submodelPin);
70                                 inputSupermodelPins.add(getSupermodelPin(submodelPin));
71                         }
72                 for (int i = 0; i < Math.min(oldInputCount, inputCount); i++)
73                 {
74                         if (!inputSubmodelPins.get(i).name.equals(pinNames[i]))
75                         {
76                                 super.removeSubmodelInterface(inputSupermodelPins.get(i));
77                                 Pin submodelPin = super.addSubmodelInterface(pinNames[i], logicWidth, 0, pinDistance / 2 + i * pinDistance);
78                                 inputSubmodelPins.set(i, submodelPin);
79                                 inputSupermodelPins.set(i, getSupermodelPin(submodelPin));
80                         }
81                 }
82         }
83
84         protected void setOutputPins(String... pinNames)
85         {
86                 int outputCount = pinNames.length;
87                 int oldOutputCount = outputSupermodelPins.size();
88                 super.setSize(width, Math.max(inputSupermodelPins.size(), outputCount) * pinDistance);
89                 if (oldOutputCount > outputCount)
90                         while (outputSupermodelPins.size() > outputCount)
91                         {
92                                 outputSubmodelPins.remove(outputCount);
93                                 super.removeSubmodelInterface(outputSupermodelPins.get(outputCount));
94                         }
95                 else if (oldOutputCount < outputCount)
96                         for (int i = oldOutputCount; i < outputCount; i++)
97                         {
98                                 Pin submodelPin = super.addSubmodelInterface(pinNames[i], logicWidth, width, pinDistance / 2 + i * pinDistance);
99                                 outputSubmodelPins.add(submodelPin);
100                                 outputSupermodelPins.add(getSupermodelPin(submodelPin));
101                         }
102                 for (int i = 0; i < Math.min(oldOutputCount, outputCount); i++)
103                 {
104                         if (!outputSubmodelPins.get(i).name.equals(pinNames[i]))
105                         {
106                                 super.removeSubmodelInterface(outputSupermodelPins.get(i));
107                                 Pin submodelPin = super.addSubmodelInterface(pinNames[i], logicWidth, width, pinDistance / 2 + i * pinDistance);
108                                 outputSubmodelPins.set(i, submodelPin);
109                                 outputSupermodelPins.set(i, getSupermodelPin(submodelPin));
110                         }
111                 }
112         }
113
114         public List<Pin> getInputPins()
115         {
116                 return inputSupermodelPinsUnmodifiable;
117         }
118
119         public List<Pin> getOutputPins()
120         {
121                 return outputSupermodelPinsUnmodifiable;
122         }
123
124         protected List<Pin> getInputSubmodelPins()
125         {
126                 return inputSubmodelPinsUnmodifiable;
127         }
128
129         protected List<Pin> getOutputSubmodelPins()
130         {
131                 return outputSubmodelPinsUnmodifiable;
132         }
133
134         @Override
135         protected void renderSymbol(GeneralGC gc, Rectangle visibleRegion)
136         {
137                 double posX = getBounds().x;
138                 double posY = getBounds().y;
139
140                 Font oldFont = gc.getFont();
141                 gc.setFont(new Font(oldFont.getName(), labelFontHeight, oldFont.getStyle()));
142                 Point textExtent = gc.textExtent(label);
143                 gc.drawText(label, posX + (getBounds().width - textExtent.x) / 2, posY + (getBounds().height - textExtent.y) / 2, true);
144                 gc.setFont(new Font(oldFont.getName(), pinNameFontHeight, oldFont.getStyle()));
145                 for (int i = 0; i < inputSupermodelPins.size(); i++)
146                 {
147                         String pinName = inputSupermodelPins.get(i).name;
148                         textExtent = gc.textExtent(pinName);
149                         gc.drawText(pinName, posX + pinNameMargin, posY + i * pinDistance + (pinDistance - textExtent.y) / 2, true);
150                 }
151                 for (int i = 0; i < outputSupermodelPins.size(); i++)
152                 {
153                         String pinName = outputSupermodelPins.get(i).name;
154                         textExtent = gc.textExtent(pinName);
155                         gc.drawText(pinName, posX + width - textExtent.x - pinNameMargin, posY + i * pinDistance + (pinDistance - textExtent.y) / 2,
156                                         true);
157                 }
158                 gc.setFont(oldFont);
159         }
160
161         @Override
162         protected void renderOutline(GeneralGC gc, Rectangle visibleRegion)
163         {
164                 gc.drawRectangle(getBounds());
165         }
166
167         @Override
168         public SubmodelComponentParams calculateParams()
169         {
170                 SubmodelComponentParams ret = super.calculateParams();
171                 ret.type = SimpleRectangularSubmodelComponent.class.getSimpleName();
172                 Map<String, Object> m = new TreeMap<>();
173                 m.put(kLabel, label);
174                 m.put(kInCount, inputSupermodelPins.size());
175                 m.put(kOutCount, outputSupermodelPins.size());
176                 m.put(kLogicWidth, logicWidth);
177                 ret.specialized = m;
178                 return ret;
179         }
180
181         @Override
182         protected Pin addSubmodelInterface(String name, int logicWidth, double relX, double relY)
183         {
184                 throw new UnsupportedOperationException(
185                                 "Can't add submodel interfaces to a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
186         }
187
188         @Override
189         protected void removeSubmodelInterface(Pin supermodelPin)
190         {
191                 throw new UnsupportedOperationException(
192                                 "Can't remove submodel interfaces of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
193         }
194
195         @Override
196         protected void setSize(double width, double height)
197         {
198                 throw new UnsupportedOperationException(
199                                 "Can't set the size of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
200         }
201 }