Restructured serializing / deserializing
[Mograsim.git] / net.mograsim.logic.ui / src / net / mograsim / logic / ui / model / components / submodels / SimpleRectangularSubmodelComponent.java
1 package net.mograsim.logic.ui.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 org.eclipse.swt.graphics.Color;
10
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.MovablePin;
17 import net.mograsim.logic.ui.model.wires.Pin;
18 import net.mograsim.preferences.Preferences;
19
20 public class SimpleRectangularSubmodelComponent extends SubmodelComponent
21 {
22         public static String kLabel = "label", kInCount = "input_count", kOutCount = "output_count", kLogicWidth = "logic_width";
23
24         private static final double width = 35;
25         private static final double pinDistance = 10;
26         private static final double pinNameMargin = .5;
27         private static final double labelFontHeight = 5;
28         private static final double pinNameFontHeight = 3.5;
29
30         private final String label;
31         protected final int logicWidth;
32
33         private final List<String> inputPinNames;
34         private final List<String> inputPinNamesUnmodifiable;
35         private final List<String> outputPinNames;
36         private final List<String> outputPinNamesUnmodifiable;
37
38         public SimpleRectangularSubmodelComponent(ViewModelModifiable model, int logicWidth, String label)
39         {
40                 super(model);
41                 this.label = label;
42                 this.logicWidth = logicWidth;
43                 this.inputPinNames = new ArrayList<>();
44                 this.inputPinNamesUnmodifiable = Collections.unmodifiableList(inputPinNames);
45                 this.outputPinNames = new ArrayList<>();
46                 this.outputPinNamesUnmodifiable = Collections.unmodifiableList(outputPinNames);
47         }
48
49         protected void setInputPins(String... pinNames)
50         {
51                 setIOPins(0, inputPinNames, outputPinNames, pinNames);
52         }
53
54         protected void setOutputPins(String... pinNames)
55         {
56                 setIOPins(width, outputPinNames, inputPinNames, pinNames);
57         }
58
59         private void setIOPins(double relX, List<String> pinNamesListThisSide, List<String> pinNamesListOtherSide, String... newPinNames)
60         {
61                 int inputCount = newPinNames.length;
62                 List<String> newPinNamesList = Arrays.asList(newPinNames);
63                 if (new HashSet<>(newPinNamesList).size() != inputCount)
64                         throw new IllegalArgumentException("Pin names contain duplicates");
65                 for (String pinName : newPinNamesList)
66                         if (pinNamesListOtherSide.contains(pinName))
67                                 throw new IllegalArgumentException("Can't add pin. There is a pin on the other side with the same name: " + pinName);
68                 super.setSize(width, Math.max(inputCount, pinNamesListOtherSide.size()) * pinDistance);
69                 for (int i = 0; i < inputCount; i++)
70                 {
71                         String pinName = newPinNames[i];
72                         int oldPinIndex = pinNamesListThisSide.indexOf(pinName);
73                         if (oldPinIndex == -1)
74                                 super.addSubmodelInterface(new MovablePin(this, pinName, logicWidth, relX, pinDistance / 2 + i * pinDistance));
75                         else
76                                 getSupermodelMovablePin(pinName).setRelPos(relX, pinDistance / 2 + i * pinDistance);
77                 }
78                 for (String pinName : pinNamesListThisSide)
79                         if (!newPinNamesList.contains(pinName))
80                                 super.removeSubmodelInterface(pinName);
81                 pinNamesListThisSide.clear();
82                 pinNamesListThisSide.addAll(newPinNamesList);
83         }
84
85         public List<String> getInputPinNames()
86         {
87                 return inputPinNamesUnmodifiable;
88         }
89
90         public List<String> getOutputPinNames()
91         {
92                 return outputPinNamesUnmodifiable;
93         }
94
95         @Override
96         protected void renderSymbol(GeneralGC gc, Rectangle visibleRegion)
97         {
98                 Font oldFont = gc.getFont();
99                 gc.setFont(new Font(oldFont.getName(), labelFontHeight, oldFont.getStyle()));
100                 Point textExtent = gc.textExtent(label);
101                 Color textColor = Preferences.current().getColor("net.mograsim.logic.ui.color.text");
102                 if (textColor != null)
103                         gc.setForeground(textColor);
104                 gc.drawText(label, getPosX() + (getWidth() - textExtent.x) / 2, getPosY() + (getHeight() - textExtent.y) / 2, true);
105                 gc.setFont(new Font(oldFont.getName(), pinNameFontHeight, oldFont.getStyle()));
106                 for (int i = 0; i < inputPinNames.size(); i++)
107                 {
108                         String pinName = inputPinNames.get(i);
109                         textExtent = gc.textExtent(pinName);
110                         gc.drawText(pinName, getPosX() + pinNameMargin, getPosY() + i * pinDistance + (pinDistance - textExtent.y) / 2, true);
111                 }
112                 for (int i = 0; i < outputPinNames.size(); i++)
113                 {
114                         String pinName = outputPinNames.get(i);
115                         textExtent = gc.textExtent(pinName);
116                         gc.drawText(pinName, getPosX() + width - textExtent.x - pinNameMargin,
117                                         getPosY() + i * pinDistance + (pinDistance - textExtent.y) / 2, true);
118                 }
119                 gc.setFont(oldFont);
120         }
121
122         @Override
123         protected void renderOutline(GeneralGC gc, Rectangle visibleRegion)
124         {
125                 Color foreground = Preferences.current().getColor("net.mograsim.logic.ui.color.foreground");
126                 if (foreground != null)
127                         gc.setForeground(foreground);
128                 gc.drawRectangle(getBounds());
129         }
130
131         @Override
132         protected Pin addSubmodelInterface(MovablePin supermodelPin)
133         {
134                 throw new UnsupportedOperationException(
135                                 "Can't add submodel interfaces to a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
136         }
137
138         @Override
139         protected void removeSubmodelInterface(String name)
140         {
141                 throw new UnsupportedOperationException(
142                                 "Can't remove submodel interfaces of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
143         }
144
145         @Override
146         protected void setSize(double width, double height)
147         {
148                 throw new UnsupportedOperationException(
149                                 "Can't set the size of a SimpleRectangularSubmodelComponent directly, call setInputPins / setOutputPins instead");
150         }
151 }