import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.util.Map;
import net.mograsim.logic.ui.model.ViewModelModifiable;
-import net.mograsim.logic.ui.model.components.params.GeneralComponentParams;
-import net.mograsim.logic.ui.model.components.params.RectComponentParams;
-import net.mograsim.logic.ui.model.components.params.SubComponentParams;
-import net.mograsim.logic.ui.model.components.params.RectComponentParams.InnerComponentParams;
-import net.mograsim.logic.ui.model.components.params.RectComponentParams.InnerWireParams;
-import net.mograsim.logic.ui.model.components.params.SubComponentParams.InterfacePinParams;
+import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams.InnerComponentParams;
+import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams;
+import net.mograsim.logic.ui.model.components.SubmodelComponentParams.InnerWireParams;
+import net.mograsim.logic.ui.model.components.SubmodelComponentParams.InterfacePinParams;
import net.mograsim.logic.ui.model.wires.GUIWire;
+import net.mograsim.logic.ui.model.wires.WireCrossPoint;
-public class GUICustomComponentCreator
+/**
+ * Creates {@link SubmodelComponent}s from {@link SubmodelComponentParams}
+ */
+public final class GUICustomComponentCreator
{
- private static class CustomRectComponent extends SimpleRectangularSubmodelComponent
- {
- private String path;
-
- protected CustomRectComponent(ViewModelModifiable model, int logicWidth, String label, String path)
- {
- super(model, logicWidth, label);
- this.path = path;
- }
-
- @Override
- public String getIdentifier()
- {
- return "file:".concat(path);
- }
- }
+ private static final String rectC = SimpleRectangularSubmodelComponent.class.getSimpleName();
+ /**
+ * Creates a {@link SubmodelComponent} from the {@link SubmodelComponentParams}, specified at the given path. The returned
+ * SubmodelComponent can also be e.g. a {@link SimpleRectangularSubmodelComponent}, depending on what the
+ * {@link SubmodelComponentParams} describe.
+ *
+ * @param path The path of the file describing the {@link SubmodelComponentParams}, which define the new {@link SubmodelComponent}
+ * @return A new SubmodelComponent, as described in the file located at the given path
+ */
public static SubmodelComponent create(ViewModelModifiable model, String path)
{
try
{
- if (path.endsWith(RectComponentParams.fileExtension))
- {
- RectComponentParams params = RectComponentParams.readJson(path);
- SubmodelComponent ret = create(model, params, path);
- return ret;
- } else if (path.endsWith(SubComponentParams.fileExtension))
- {
- SubComponentParams params = SubComponentParams.readJson(path);
- SubmodelComponent ret = create(model, params, path);
- return ret;
- } else
- throw new IOException(String.format("\"%s\" does not have a valid file extension. Must be either %s or %s", path,
- RectComponentParams.fileExtension, SubComponentParams.fileExtension));
+ SubmodelComponentParams params = SubmodelComponentParams.readJson(path);
+ SubmodelComponent ret = create(model, params, path);
+ return ret;
}
catch (IOException e)
{
System.err.println("Failed to construct GUICustomComponent. Parameters were not found.");
e.printStackTrace();
}
- return new CustomRectComponent(model, 0, "ERROR", "NONE");
+ return new SimpleRectangularSubmodelComponent(model, 0, "ERROR");
}
/**
- * @param path This value is used when the new SubmodelComponent is an inner component to a different SubmodelComponent, which is being
- * saved to a file; Then, the new SubmodelComponent is referenced by its given path within the file.
+ * Creates a {@link SubmodelComponent} from the specified {@link SubmodelComponentParams}. The returned SubmodelComponent can also be
+ * e.g. a {@link SimpleRectangularSubmodelComponent}, depending on what the {@link SubmodelComponentParams} describe.
+ *
+ * @param params The parameters describing the {@link SubmodelComponent}
+ * @param path This value is used when the new {@link SubmodelComponent} is an inner component to a different SubmodelComponent, which
+ * is being saved to a file; Then, the new {@link SubmodelComponent} is referenced by its given path within the file.
+ * @return A new SubmodelComponent, as described by the {@link SubmodelComponentParams}
*/
- public static SimpleRectangularSubmodelComponent create(ViewModelModifiable model, RectComponentParams params, String path)
+ public static SubmodelComponent create(ViewModelModifiable model, SubmodelComponentParams params, String path)
{
- CustomRectComponent comp = new CustomRectComponent(model, params.logicWidth, params.displayName, path);
- comp.setSubmodelScale(params.composition.innerScale);
- comp.setInputCount(params.inputCount);
- comp.setOutputCount(params.outputCount);
- initSubmodelComponents(comp, params.composition);
+ SubmodelComponent comp = null;
+ if (rectC.equals(params.type))
+ {
+ comp = createRectComponent(model, params);
+ }
+
+ if (comp == null)
+ {
+ comp = createSubmodelComponent(model, params);
+ }
+ comp.identifierDelegate = () -> "file:".concat(path);
+ initInnerComponents(comp, params.composition);
return comp;
}
- /**
- * @param path This value is used when the new SubmodelComponent is an inner component to a different SubmodelComponent, which is being
- * saved to a file; Then, the new SubmodelComponent is referenced by its given path within the file.
- */
- public static SubmodelComponent create(ViewModelModifiable model, SubComponentParams params, String path)
+ // May return null
+ private static SimpleRectangularSubmodelComponent createRectComponent(ViewModelModifiable model, SubmodelComponentParams params)
+ {
+ try
+ {
+ Map<String, Object> m = params.specialized;
+ SimpleRectangularSubmodelComponent rect = new SimpleRectangularSubmodelComponent(model,
+ ((Number) m.get(SimpleRectangularSubmodelComponent.kLogicWidth)).intValue(),
+ (String) m.get(SimpleRectangularSubmodelComponent.kLabel));
+ rect.setSubmodelScale(params.composition.innerScale);
+ // rect.setSize(params.width, params.height);
+
+ // TODO save & restore names
+ int inputCount = ((Number) m.get(SimpleRectangularSubmodelComponent.kInCount)).intValue();
+ String[] inputNames = new String[inputCount];
+ for (int i = 0; i < inputCount; i++)
+ inputNames[i] = params.interfacePins[i].name;
+ rect.setInputPins(inputNames);
+
+ int outputCount = ((Number) m.get(SimpleRectangularSubmodelComponent.kOutCount)).intValue();
+ String[] outputPins = new String[outputCount];
+ for (int i = 0; i < outputCount; i++)
+ outputPins[i] = params.interfacePins[inputCount + i].name;
+ rect.setOutputPins(outputPins);
+
+ return rect;
+ }
+ catch (ClassCastException | NullPointerException e)
+ {
+ System.err.println("Failed to specialize component!");
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static SubmodelComponent createSubmodelComponent(ViewModelModifiable model, SubmodelComponentParams params)
{
// As SubmodelComponent is abstract, for now SubmodelComponents are instantiated as SimpleRectangularSubmodelComponents
- CustomRectComponent comp = new CustomRectComponent(model, 0, "", path);
+ SubmodelComponent comp = new SimpleRectangularSubmodelComponent(model, 0, "");
comp.setSubmodelScale(params.composition.innerScale);
comp.setSize(params.width, params.height);
for (InterfacePinParams iPinParams : params.interfacePins)
{
- comp.addSubmodelInterface(iPinParams.logicWidth, iPinParams.location.x, iPinParams.location.y);
+ comp.addSubmodelInterface(iPinParams.name, iPinParams.logicWidth, iPinParams.location.x, iPinParams.location.y);
}
- initSubmodelComponents(comp, params.composition);
return comp;
}
@SuppressWarnings("unused")
- private static void initSubmodelComponents(SubmodelComponent comp, GeneralComponentParams params)
+ private static void initInnerComponents(SubmodelComponent comp, ComponentCompositionParams params)
{
try
{
if (path.startsWith("class:"))
{
path = path.substring(6);
- components[i] = createInnerComponentFromClass(comp, path, cParams.logicWidth);
+ components[i] = createInnerComponentFromClass(comp, path, cParams.params);
components[i].moveTo(cParams.pos.x, cParams.pos.y);
} else if (path.startsWith("file:"))
{
{
InnerWireParams innerWire = params.innerWires[i];
new GUIWire(comp.submodelModifiable,
- comp.submodelModifiable.getComponents().get(innerWire.pin1.compId).getPins().get(innerWire.pin1.pinIndex),
- comp.submodelModifiable.getComponents().get(innerWire.pin2.compId).getPins().get(innerWire.pin2.pinIndex),
- innerWire.path);
+ comp.submodelModifiable.getComponents().get(innerWire.pin1.compId).getPin(innerWire.pin1.pinName),
+ comp.submodelModifiable.getComponents().get(innerWire.pin2.compId).getPin(innerWire.pin2.pinName), innerWire.path);
}
}
- catch (Exception e)
+ catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException | SecurityException
+ | ClassNotFoundException | IllegalArgumentException e)
{
- System.err.println("Failed to create custom component!");
+ System.err.println("Failed to initialize custom component!");
e.printStackTrace();
}
}
- private static GUIComponent createInnerComponentFromClass(SubmodelComponent parent, String classname, int logicWidth)
- throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
- NoSuchMethodException, SecurityException, ClassNotFoundException
+ private static GUIComponent createInnerComponentFromClass(SubmodelComponent parent, String classname, Map<String, Object> params)
+ throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, SecurityException,
+ ClassNotFoundException
{
Class<?> c = Class.forName(classname);
Object comp;
- try
+ if (SimpleRectangularGUIGate.class.isAssignableFrom(c) || WireCrossPoint.class.equals(c))
+ {
+ Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class, int.class);
+ comp = constructor.newInstance(parent.submodelModifiable,
+ ((Number) params.get(SimpleRectangularGUIGate.kLogicWidth)).intValue());
+ } else
{
Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class);
comp = constructor.newInstance(parent.submodelModifiable);
}
- catch (@SuppressWarnings("unused") NoSuchMethodException e)
- {
- Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class, int.class);
- comp = constructor.newInstance(parent.submodelModifiable, logicWidth);
- }
-
- if (comp instanceof GUIComponent)
- return (GUIComponent) comp;
- throw new IllegalArgumentException("Class given as subcomponent was not a GUIComponent!");
+ return (GUIComponent) comp;
}
}