Commented GUIWire
[Mograsim.git] / net.mograsim.logic.ui / src / net / mograsim / logic / ui / model / components / GUICustomComponentCreator.java
index 691f552..0e23feb 100644 (file)
@@ -3,95 +3,124 @@ package net.mograsim.logic.ui.model.components;
 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;
+import net.mograsim.logic.ui.model.components.SubmodelComponentParams.ComponentCompositionParams.InnerComponentParams;
+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.MovablePin;
+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);
+
+                       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(
+                                       new MovablePin(comp, 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
                {
@@ -103,7 +132,7 @@ public class GUICustomComponentCreator
                                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:"))
                                {
@@ -118,37 +147,34 @@ public class GUICustomComponentCreator
                        {
                                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;
        }
 }