Simplified file representation of SubmodelComponents
[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.Map;
7
8 import net.mograsim.logic.ui.model.ViewModelModifiable;
9 import net.mograsim.logic.ui.model.components.params.GeneralComponentParams;
10 import net.mograsim.logic.ui.model.components.params.GeneralComponentParams.InnerComponentParams;
11 import net.mograsim.logic.ui.model.components.params.SubComponentParams;
12 import net.mograsim.logic.ui.model.components.params.SubComponentParams.InnerWireParams;
13 import net.mograsim.logic.ui.model.components.params.SubComponentParams.InterfacePinParams;
14 import net.mograsim.logic.ui.model.wires.GUIWire;
15
16 public class GUICustomComponentCreator
17 {
18         private static final String rectC = SimpleRectangularSubmodelComponent.class.getSimpleName();
19
20         private static class CustomRectComponent extends SimpleRectangularSubmodelComponent
21         {
22                 private String path;
23
24                 protected CustomRectComponent(ViewModelModifiable model, int logicWidth, String label, String path)
25                 {
26                         super(model, logicWidth, label);
27                         this.path = path;
28                 }
29
30                 @Override
31                 public String getIdentifier()
32                 {
33                         return "file:".concat(path);
34                 }
35         }
36
37         public static SubmodelComponent create(ViewModelModifiable model, String path)
38         {
39                 try
40                 {
41                         SubComponentParams params = SubComponentParams.readJson(path);
42                         SubmodelComponent ret = create(model, params, path);
43                         return ret;
44                 }
45                 catch (IOException e)
46                 {
47                         System.err.println("Failed to construct GUICustomComponent. Parameters were not found.");
48                         e.printStackTrace();
49                 }
50                 return new CustomRectComponent(model, 0, "ERROR", "NONE");
51         }
52
53         /**
54          * @param path This value is used when the new SubmodelComponent is an inner component to a different SubmodelComponent, which is being
55          *             saved to a file; Then, the new SubmodelComponent is referenced by its given path within the file.
56          */
57         public static SubmodelComponent create(ViewModelModifiable model, SubComponentParams params, String path)
58         {
59                 // TODO: Clean up this mess
60                 SubmodelComponent comp = null;
61                 if (rectC.equals(params.type))
62                 {
63                         try
64                         {
65                                 Map<String, Object> m = params.specialized;
66                                 SimpleRectangularSubmodelComponent rect = new CustomRectComponent(model,
67                                                 ((Number) m.get(SimpleRectangularSubmodelComponent.kLogicWidth)).intValue(),
68                                                 (String) m.get(SimpleRectangularSubmodelComponent.kLabel), path);
69                                 rect.setSubmodelScale(params.composition.innerScale);
70                                 rect.setSize(params.width, params.height);
71                                 rect.setInputCount(((Number) m.get(SimpleRectangularSubmodelComponent.kInCount)).intValue());
72                                 rect.setOutputCount(((Number) m.get(SimpleRectangularSubmodelComponent.kOutCount)).intValue());
73                                 comp = rect;
74                         }
75                         catch (ClassCastException | NullPointerException e)
76                         {
77                                 System.err.println("Failed to specialize component!");
78                                 e.printStackTrace();
79                         }
80                 }
81                 if (comp == null)
82                 {
83                         // As SubmodelComponent is abstract, for now SubmodelComponents are instantiated as SimpleRectangularSubmodelComponents
84                         comp = new CustomRectComponent(model, 0, "", path);
85
86                         comp.setSubmodelScale(params.composition.innerScale);
87                         comp.setSize(params.width, params.height);
88                         for (InterfacePinParams iPinParams : params.interfacePins)
89                         {
90                                 comp.addSubmodelInterface(iPinParams.logicWidth, iPinParams.location.x, iPinParams.location.y);
91                         }
92                 }
93                 initSubmodelComponents(comp, params.composition);
94                 return comp;
95         }
96
97         @SuppressWarnings("unused")
98         private static void initSubmodelComponents(SubmodelComponent comp, GeneralComponentParams params)
99         {
100                 try
101                 {
102                         GUIComponent[] components = new GUIComponent[params.subComps.length];
103                         for (int i = 0; i < components.length; i++)
104                         {
105                                 InnerComponentParams cParams = params.subComps[i];
106                                 String path = cParams.type;
107                                 if (path.startsWith("class:"))
108                                 {
109                                         path = path.substring(6);
110                                         components[i] = createInnerComponentFromClass(comp, path, cParams.logicWidth);
111                                         components[i].moveTo(cParams.pos.x, cParams.pos.y);
112                                 } else if (path.startsWith("file:"))
113                                 {
114                                         path = path.substring(5);
115                                         components[i] = create(comp.submodelModifiable, path);
116                                         components[i].moveTo(cParams.pos.x, cParams.pos.y);
117                                 } else
118                                         throw new IllegalArgumentException("Invalid submodel type! Type was neither prefixed by 'class:' nor by 'file:'");
119                         }
120
121                         for (int i = 0; i < params.innerWires.length; i++)
122                         {
123                                 InnerWireParams innerWire = params.innerWires[i];
124                                 new GUIWire(comp.submodelModifiable,
125                                                 comp.submodelModifiable.getComponents().get(innerWire.pin1.compId).getPins().get(innerWire.pin1.pinIndex),
126                                                 comp.submodelModifiable.getComponents().get(innerWire.pin2.compId).getPins().get(innerWire.pin2.pinIndex),
127                                                 innerWire.path);
128                         }
129                 }
130                 catch (Exception e)
131                 {
132                         System.err.println("Failed to create custom component!");
133                         e.printStackTrace();
134                 }
135         }
136
137         private static GUIComponent createInnerComponentFromClass(SubmodelComponent parent, String classname, int logicWidth)
138                         throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
139                         NoSuchMethodException, SecurityException, ClassNotFoundException
140         {
141                 Class<?> c = Class.forName(classname);
142                 Object comp;
143                 try
144                 {
145                         Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class);
146                         comp = constructor.newInstance(parent.submodelModifiable);
147                 }
148                 catch (@SuppressWarnings("unused") NoSuchMethodException e)
149                 {
150                         Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class, int.class);
151                         comp = constructor.newInstance(parent.submodelModifiable, logicWidth);
152                 }
153
154                 if (comp instanceof GUIComponent)
155                         return (GUIComponent) comp;
156                 throw new IllegalArgumentException("Class given as subcomponent was not a GUIComponent!");
157         }
158 }