1 package net.mograsim.logic.ui.model.components;
3 import java.io.IOException;
4 import java.lang.reflect.Constructor;
5 import java.lang.reflect.InvocationTargetException;
8 import net.mograsim.logic.ui.model.ViewModelModifiable;
9 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams.InnerComponentParams;
10 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams;
11 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.InnerWireParams;
12 import net.mograsim.logic.ui.model.components.SubmodelComponentParams.InterfacePinParams;
13 import net.mograsim.logic.ui.model.wires.GUIWire;
16 * Creates {@link SubmodelComponent}s from {@link SubmodelComponentParams}
18 public final class GUICustomComponentCreator
20 private static final String rectC = SimpleRectangularSubmodelComponent.class.getSimpleName();
23 * Creates a {@link SubmodelComponent} from the {@link SubmodelComponentParams}, specified at the given path. The returned
24 * SubmodelComponent can also be e.g. a {@link SimpleRectangularSubmodelComponent}, depending on what the
25 * {@link SubmodelComponentParams} describe.
27 * @param path The path of the file describing the {@link SubmodelComponentParams}, which define the new {@link SubmodelComponent}
28 * @return A new SubmodelComponent, as described in the file located at the given path
30 public static SubmodelComponent create(ViewModelModifiable model, String path)
34 SubmodelComponentParams params = SubmodelComponentParams.readJson(path);
35 SubmodelComponent ret = create(model, params, path);
40 System.err.println("Failed to construct GUICustomComponent. Parameters were not found.");
43 return new SimpleRectangularSubmodelComponent(model, 0, "ERROR");
47 * Creates a {@link SubmodelComponent} from the specified {@link SubmodelComponentParams}. The returned SubmodelComponent can also be
48 * e.g. a {@link SimpleRectangularSubmodelComponent}, depending on what the {@link SubmodelComponentParams} describe.
50 * @param params The parameters describing the {@link SubmodelComponent}
51 * @param path This value is used when the new {@link SubmodelComponent} is an inner component to a different SubmodelComponent, which
52 * is being saved to a file; Then, the new {@link SubmodelComponent} is referenced by its given path within the file.
53 * @return A new SubmodelComponent, as described by the {@link SubmodelComponentParams}
55 public static SubmodelComponent create(ViewModelModifiable model, SubmodelComponentParams params, String path)
57 SubmodelComponent comp = null;
58 if (rectC.equals(params.type))
60 comp = createRectComponent(model, params);
65 comp = createSubmodelComponent(model, params);
67 comp.identifierDelegate = () -> "file:".concat(path);
68 initInnerComponents(comp, params.composition);
73 private static SimpleRectangularSubmodelComponent createRectComponent(ViewModelModifiable model, SubmodelComponentParams params)
77 Map<String, Object> m = params.specialized;
78 SimpleRectangularSubmodelComponent rect = new SimpleRectangularSubmodelComponent(model,
79 ((Number) m.get(SimpleRectangularSubmodelComponent.kLogicWidth)).intValue(),
80 (String) m.get(SimpleRectangularSubmodelComponent.kLabel));
81 rect.setSubmodelScale(params.composition.innerScale);
82 // rect.setSize(params.width, params.height);
84 // TODO save & restore names
85 int inputCount = ((Number) m.get(SimpleRectangularSubmodelComponent.kInCount)).intValue();
86 String[] inputNames = new String[inputCount];
87 for (int i = 0; i < inputCount; i++)
88 inputNames[i] = "Input pin #" + i;
89 rect.setInputPins(inputNames);
91 int outputCount = ((Number) m.get(SimpleRectangularSubmodelComponent.kOutCount)).intValue();
92 String[] outputPins = new String[outputCount];
93 for (int i = 0; i < outputCount; i++)
94 outputPins[i] = "Output pin #" + i;
95 rect.setOutputPins(outputPins);
99 catch (ClassCastException | NullPointerException e)
101 System.err.println("Failed to specialize component!");
107 private static SubmodelComponent createSubmodelComponent(ViewModelModifiable model, SubmodelComponentParams params)
109 // As SubmodelComponent is abstract, for now SubmodelComponents are instantiated as SimpleRectangularSubmodelComponents
110 SubmodelComponent comp = new SimpleRectangularSubmodelComponent(model, 0, "");
111 comp.setSubmodelScale(params.composition.innerScale);
112 comp.setSize(params.width, params.height);
113 for (InterfacePinParams iPinParams : params.interfacePins)
115 comp.addSubmodelInterface(iPinParams.name, iPinParams.logicWidth, iPinParams.location.x, iPinParams.location.y);
120 @SuppressWarnings("unused")
121 private static void initInnerComponents(SubmodelComponent comp, ComponentCompositionParams params)
125 GUIComponent[] components = new GUIComponent[params.subComps.length];
126 for (int i = 0; i < components.length; i++)
128 InnerComponentParams cParams = params.subComps[i];
129 String path = cParams.type;
130 if (path.startsWith("class:"))
132 path = path.substring(6);
133 components[i] = createInnerComponentFromClass(comp, path, cParams.logicWidth);
134 components[i].moveTo(cParams.pos.x, cParams.pos.y);
135 } else if (path.startsWith("file:"))
137 path = path.substring(5);
138 components[i] = create(comp.submodelModifiable, path);
139 components[i].moveTo(cParams.pos.x, cParams.pos.y);
141 throw new IllegalArgumentException("Invalid submodel type! Type was neither prefixed by 'class:' nor by 'file:'");
144 for (int i = 0; i < params.innerWires.length; i++)
146 InnerWireParams innerWire = params.innerWires[i];
147 new GUIWire(comp.submodelModifiable,
148 comp.submodelModifiable.getComponents().get(innerWire.pin1.compId).getPins().get(innerWire.pin1.pinIndex),
149 comp.submodelModifiable.getComponents().get(innerWire.pin2.compId).getPins().get(innerWire.pin2.pinIndex),
153 catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException
154 | ClassNotFoundException | IllegalArgumentException e)
156 System.err.println("Failed to initialize custom component!");
161 private static GUIComponent createInnerComponentFromClass(SubmodelComponent parent, String classname, int logicWidth)
162 throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
163 NoSuchMethodException, SecurityException, ClassNotFoundException
165 Class<?> c = Class.forName(classname);
169 Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class);
170 comp = constructor.newInstance(parent.submodelModifiable);
172 catch (@SuppressWarnings("unused") NoSuchMethodException e)
174 Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class, int.class);
175 comp = constructor.newInstance(parent.submodelModifiable, logicWidth);
178 if (comp instanceof GUIComponent)
179 return (GUIComponent) comp;
180 throw new IllegalArgumentException("Class given as subcomponent was not a GUIComponent!");