c153956c3659a490fe25e32aac5209e98357281d
[Mograsim.git] / net.mograsim.logic.ui / src / net / mograsim / logic / ui / model / components / GUICustomComponentCreator.java
1 package net.mograsim.logic.ui.model.components;
2
3 import java.io.IOException;
4 import java.lang.reflect.Constructor;
5 import java.lang.reflect.InvocationTargetException;
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Map;
9
10 import net.mograsim.logic.ui.model.ViewModelModifiable;
11 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams;
12 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams.InnerComponentParams;
13 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.InnerWireParams;
14 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.InterfacePinParams;
15 import net.mograsim.logic.ui.model.wires.GUIWire;
16 import net.mograsim.logic.ui.model.wires.MovablePin;
17 import net.mograsim.logic.ui.model.wires.WireCrossPoint;
18
19 /**
20  * Creates {@link SubmodelComponent}s from {@link SubmodelComponentParams}
21  */
22 public final class GUICustomComponentCreator
23 {
24         private static final String rectC = SimpleRectangularSubmodelComponent.class.getSimpleName();
25
26         /**
27          * Creates a {@link SubmodelComponent} from the {@link SubmodelComponentParams}, specified at the given path. The returned
28          * SubmodelComponent can also be e.g. a {@link SimpleRectangularSubmodelComponent}, depending on what the
29          * {@link SubmodelComponentParams} describe.
30          * 
31          * @param path The path of the file describing the {@link SubmodelComponentParams}, which define the new {@link SubmodelComponent}
32          * @return A new SubmodelComponent, as described in the file located at the given path
33          */
34         public static SubmodelComponent create(ViewModelModifiable model, String path)
35         {
36                 try
37                 {
38                         SubmodelComponentParams params = SubmodelComponentParams.readJson(path);
39                         SubmodelComponent ret = create(model, params);
40                         return ret;
41                 }
42                 catch (IOException e)
43                 {
44                         System.err.println("Failed to construct GUICustomComponent. Parameters were not found.");
45                         e.printStackTrace();
46                 }
47                 return new SimpleRectangularSubmodelComponent(model, 0, "ERROR");
48         }
49
50         /**
51          * Creates a {@link SubmodelComponent} from the specified {@link SubmodelComponentParams}. The returned SubmodelComponent can also be
52          * e.g. a {@link SimpleRectangularSubmodelComponent}, depending on what the {@link SubmodelComponentParams} describe.
53          * 
54          * @param params The parameters describing the {@link SubmodelComponent}
55          * 
56          * @return A new SubmodelComponent, as described by the {@link SubmodelComponentParams}
57          */
58         public static SubmodelComponent create(ViewModelModifiable model, SubmodelComponentParams params)
59         {
60                 SubmodelComponent comp = null;
61                 if (rectC.equals(params.type))
62                 {
63                         comp = createRectComponent(model, params);
64                 }
65
66                 if (comp == null)
67                 {
68                         comp = createSubmodelComponent(model, params);
69                 }
70                 comp.identifierDelegate = () -> params.name;
71                 initInnerComponents(comp, params.composition);
72                 return comp;
73         }
74
75         // May return null
76         @SuppressWarnings("unchecked")
77         private static SimpleRectangularSubmodelComponent createRectComponent(ViewModelModifiable model, SubmodelComponentParams params)
78         {
79                 try
80                 {
81                         Map<String, Object> m = params.specialized;
82                         SimpleRectangularSubmodelComponent rect = new SimpleRectangularSubmodelComponent(model,
83                                         ((Number) m.get(SimpleRectangularSubmodelComponent.kLogicWidth)).intValue(),
84                                         (String) m.get(SimpleRectangularSubmodelComponent.kLabel));
85                         rect.setSubmodelScale(params.composition.innerScale);
86
87                         Object[] names = ((ArrayList<Object>) m.get(SimpleRectangularSubmodelComponent.kInCount)).toArray();
88                         rect.setInputPins(Arrays.copyOf(names, names.length, String[].class));
89
90                         names = ((ArrayList<Object>) m.get(SimpleRectangularSubmodelComponent.kOutCount)).toArray();
91                         rect.setOutputPins(Arrays.copyOf(names, names.length, String[].class));
92
93                         return rect;
94                 }
95                 catch (ClassCastException | NullPointerException e)
96                 {
97                         System.err.println("Failed to specialize component!");
98                         e.printStackTrace();
99                         return null;
100                 }
101         }
102
103         private static SubmodelComponent createSubmodelComponent(ViewModelModifiable model, SubmodelComponentParams params)
104         {
105                 // As SubmodelComponent is abstract, for now SubmodelComponents are instantiated as SimpleRectangularSubmodelComponents
106                 SubmodelComponent comp = new SimpleRectangularSubmodelComponent(model, 0, "");
107                 comp.setSubmodelScale(params.composition.innerScale);
108                 comp.setSize(params.width, params.height);
109                 for (InterfacePinParams iPinParams : params.interfacePins)
110                 {
111                         comp.addSubmodelInterface(
112                                         new MovablePin(comp, iPinParams.name, iPinParams.logicWidth, iPinParams.location.x, iPinParams.location.y));
113                 }
114                 return comp;
115         }
116
117         @SuppressWarnings("unused")
118         private static void initInnerComponents(SubmodelComponent comp, ComponentCompositionParams params)
119         {
120                 GUIComponent[] components = new GUIComponent[params.subComps.length];
121                 for (int i = 0; i < components.length; i++)
122                 {
123                         InnerComponentParams cParams = params.subComps[i];
124                         String path = cParams.name;
125                         components[i] = GUIComponentCreator.create(comp.submodelModifiable, cParams.name, cParams.params);
126                         components[i].moveTo(cParams.pos.x, cParams.pos.y);
127                 }
128
129                 for (int i = 0; i < params.innerWires.length; i++)
130                 {
131                         InnerWireParams innerWire = params.innerWires[i];
132                         new GUIWire(comp.submodelModifiable,
133                                         comp.submodelModifiable.getComponents().get(innerWire.pin1.compId).getPin(innerWire.pin1.pinName),
134                                         comp.submodelModifiable.getComponents().get(innerWire.pin2.compId).getPin(innerWire.pin2.pinName), innerWire.path);
135                 }
136         }
137 }