Added file representation for SimpleRectangularSubmodelComponents
authorFabian Stemmler <stemmler@in.tum.de>
Mon, 10 Jun 2019 20:07:36 +0000 (22:07 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Mon, 10 Jun 2019 20:07:36 +0000 (22:07 +0200)
SimpleRectangularSubmodelComponents can now be saved into a .json file
(via ComponentParams writeJSON method)
GUICustomComponents can now be created from a .json file
This system does not yet support general SubmodelComponents and thus the
format is still subject to change.

net.mograsim.logic.ui/META-INF/MANIFEST.MF
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/ComponentParams.java [new file with mode: 0644]
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUICustomComponent.java [new file with mode: 0644]
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/SimpleRectangularSubmodelComponent.java
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/SubmodelComponent.java
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/GUIWire.java

index 24a1c9a..3bfa20a 100644 (file)
@@ -13,5 +13,6 @@ Export-Package: net.mograsim.logic.ui,
 Bundle-RequiredExecutionEnvironment: JavaSE-10
 Require-Bundle: org.eclipse.swt;bundle-version="3.110.0",
  SWTZoomableCanvas;bundle-version="1.0.0";visibility:=reexport,
- net.mograsim.logic.core;bundle-version="1.0.0";visibility:=reexport
+ net.mograsim.logic.core;bundle-version="1.0.0";visibility:=reexport,
+ com.google.gson;bundle-version="2.8.2"
 Automatic-Module-Name: net.mograsim.logic.ui
diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/ComponentParams.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/ComponentParams.java
new file mode 100644 (file)
index 0000000..1a273bd
--- /dev/null
@@ -0,0 +1,56 @@
+package net.mograsim.logic.ui.model.components;
+
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
+
+public class ComponentParams
+{
+       private static Gson parser = new GsonBuilder().setPrettyPrinting().create();
+       String displayName;
+       int inputCount, outputCount, logicWidth;
+       double innerScale;
+
+       InnerComponentParams[] subComps;
+       InnerWireParams[] innerWires;
+
+       public static class InnerComponentParams
+       {
+               Point pos;
+               String type;
+               int logicWidth;
+       }
+
+       public static class InnerWireParams
+       {
+               InnerPinParams pin1, pin2;
+               Point[] path;
+       }
+
+       public static class InnerPinParams
+       {
+               int compId, pinIndex;
+       }
+
+       @SuppressWarnings("resource")
+       public static ComponentParams readJSON(String path) throws IOException
+       {
+               FileReader reader = new FileReader(path);
+               ComponentParams params = parser.fromJson(new FileReader(path), ComponentParams.class);
+               reader.close();
+               return params;
+       }
+
+       public void writeJSON(String path) throws IOException
+       {
+               @SuppressWarnings("resource")
+               FileWriter writer = new FileWriter(path);
+               writer.write(parser.toJson(this));
+               writer.close();
+       }
+}
diff --git a/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUICustomComponent.java b/net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUICustomComponent.java
new file mode 100644 (file)
index 0000000..6f84daf
--- /dev/null
@@ -0,0 +1,111 @@
+package net.mograsim.logic.ui.model.components;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import net.mograsim.logic.ui.model.ViewModelModifiable;
+import net.mograsim.logic.ui.model.components.ComponentParams.InnerComponentParams;
+import net.mograsim.logic.ui.model.components.ComponentParams.InnerWireParams;
+import net.mograsim.logic.ui.model.wires.GUIWire;
+
+public class GUICustomComponent extends SimpleRectangularSubmodelComponent
+{
+       private String path = "NONE";
+
+       public static GUICustomComponent create(ViewModelModifiable model, String path)
+       {
+               try
+               {
+                       ComponentParams params = ComponentParams.readJSON(path);
+                       return create(model, params);
+               }
+               catch (IOException e)
+               {
+                       System.err.println(String.format("Failed to create custom component from invalid path: %s", path));
+                       e.printStackTrace();
+               }
+               return new GUICustomComponent(model, 0, "ERROR");
+       }
+
+       public static GUICustomComponent create(ViewModelModifiable model, ComponentParams params)
+       {
+               GUICustomComponent comp = new GUICustomComponent(model, params.logicWidth, params.displayName);
+               comp.setSubmodelScale(params.innerScale);
+               comp.setInputCount(params.inputCount);
+               comp.setOutputCount(params.outputCount);
+               comp.initSubmodelComponents(params);
+               return comp;
+       }
+
+       private GUICustomComponent(ViewModelModifiable model, int logicWidth, String displayName)
+       {
+               super(model, logicWidth, displayName);
+       }
+
+       @SuppressWarnings("unused")
+       private void initSubmodelComponents(ComponentParams params)
+       {
+               try
+               {
+                       GUIComponent[] components = new GUIComponent[params.subComps.length];
+                       for (int i = 0; i < components.length; i++)
+                       {
+                               InnerComponentParams cParams = params.subComps[i];
+                               String path = cParams.type;
+                               if (path.startsWith("class:"))
+                               {
+                                       path = path.substring(6);
+                                       components[i] = createComponent(path, cParams.logicWidth);
+                                       components[i].moveTo(cParams.pos.x, cParams.pos.y);
+                               } else if (path.startsWith("file:"))
+                               {
+                                       path = path.substring(5);
+                                       components[i] = create(submodelModifiable, path);
+                                       components[i].moveTo(cParams.pos.x, cParams.pos.y);
+                               } else
+                                       throw new IllegalArgumentException("Invalid submodel type! Type was neither prefixed by 'class:' nor by 'file:'");
+                       }
+
+                       for (int i = 0; i < params.innerWires.length; i++)
+                       {
+                               InnerWireParams innerWire = params.innerWires[i];
+                               new GUIWire(submodelModifiable,
+                                               submodelModifiable.getComponents().get(innerWire.pin1.compId).getPins().get(innerWire.pin1.pinIndex),
+                                               submodelModifiable.getComponents().get(innerWire.pin2.compId).getPins().get(innerWire.pin2.pinIndex),
+                                               innerWire.path);
+                       }
+               }
+               catch (Exception e)
+               {
+                       System.err.println("Failed to create custom component!");
+                       e.printStackTrace();
+               }
+       }
+
+       private GUIComponent createComponent(String classname, int logicWidth) throws InstantiationException, IllegalAccessException,
+                       IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException
+       {
+               Class<?> c = Class.forName(classname);
+               Object comp;
+               try
+               {
+                       Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class);
+                       comp = constructor.newInstance(submodelModifiable);
+               }
+               catch (@SuppressWarnings("unused") NoSuchMethodException e)
+               {
+                       Constructor<?> constructor = c.getConstructor(ViewModelModifiable.class, int.class);
+                       comp = constructor.newInstance(submodelModifiable, logicWidth);
+               }
+
+               if (comp instanceof GUIComponent)
+                       return (GUIComponent) comp;
+               throw new IllegalArgumentException("Class given as subcomponent was not a GUIComponent!");
+       }
+
+       public String getPath()
+       {
+               return path;
+       }
+}
index 89a55f0..f537eec 100644 (file)
@@ -2,6 +2,7 @@ package net.mograsim.logic.ui.model.components;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
 import net.haspamelodica.swt.helper.gcs.GeneralGC;
@@ -9,6 +10,10 @@ import net.haspamelodica.swt.helper.swtobjectwrappers.Font;
 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
 import net.mograsim.logic.ui.model.ViewModelModifiable;
+import net.mograsim.logic.ui.model.components.ComponentParams.InnerComponentParams;
+import net.mograsim.logic.ui.model.components.ComponentParams.InnerPinParams;
+import net.mograsim.logic.ui.model.components.ComponentParams.InnerWireParams;
+import net.mograsim.logic.ui.model.wires.GUIWire;
 import net.mograsim.logic.ui.model.wires.Pin;
 
 public class SimpleRectangularSubmodelComponent extends SubmodelComponent
@@ -122,4 +127,56 @@ public class SimpleRectangularSubmodelComponent extends SubmodelComponent
        {
                gc.drawRectangle(getBounds());
        }
+
+       public ComponentParams calculateParams()
+       {
+               ComponentParams params = new ComponentParams();
+               params.displayName = label;
+               params.inputCount = inputSupermodelPins.size();
+               params.outputCount = outputSubmodelPins.size();
+               params.logicWidth = logicWidth;
+               params.innerScale = getSubmodelScale();
+
+               List<GUIComponent> compList = submodelModifiable.getComponents();
+               Iterator<GUIComponent> componentIt = compList.iterator();
+               componentIt.next(); // Skip inner SubmodelInterface
+               InnerComponentParams[] comps = new InnerComponentParams[compList.size() - 1];
+               int i = 0;
+               while (componentIt.hasNext())
+               {
+                       GUIComponent component = componentIt.next();
+                       InnerComponentParams inner = new InnerComponentParams();
+                       comps[i] = inner;
+                       inner.logicWidth = component.getPins().get(0).logicWidth; // This could be done a little more elegantly
+                       Rectangle bounds = component.getBounds();
+                       inner.pos = new Point(bounds.x, bounds.y);
+                       if (component instanceof GUICustomComponent)
+                               inner.type = "file:" + ((GUICustomComponent) component).getPath();
+                       else
+                               inner.type = "class:" + component.getClass().getCanonicalName();
+                       i++;
+               }
+               params.subComps = comps;
+
+               List<GUIWire> wireList = submodelModifiable.getWires();
+               InnerWireParams wires[] = new InnerWireParams[wireList.size()];
+               i = 0;
+               for (GUIWire wire : wireList)
+               {
+                       InnerWireParams inner = new InnerWireParams();
+                       wires[i] = inner;
+                       InnerPinParams pin1Params = new InnerPinParams(), pin2Params = new InnerPinParams();
+
+                       pin1Params.pinIndex = wire.getPin1().component.getPins().indexOf(wire.getPin1());
+                       pin1Params.compId = compList.indexOf(wire.getPin1().component);
+                       pin2Params.pinIndex = wire.getPin2().component.getPins().indexOf(wire.getPin2());
+                       pin2Params.compId = compList.indexOf(wire.getPin2().component);
+                       inner.pin1 = pin1Params;
+                       inner.pin2 = pin2Params;
+                       inner.path = wire.getPath();
+                       i++;
+               }
+               params.innerWires = wires;
+               return params;
+       }
 }
\ No newline at end of file
index a4fe1aa..43ec22b 100644 (file)
@@ -58,6 +58,11 @@ public abstract class SubmodelComponent extends GUIComponent
                requestRedraw();// needed if there is no submodel interface pin
        }
 
+       protected double getSubmodelScale()
+       {
+               return submodelScale;
+       }
+
        /**
         * Returns the submodel pin.
         */
index 47f8517..eb7e8ab 100644 (file)
@@ -185,6 +185,11 @@ public class GUIWire
                return pin2;
        }
 
+       public Point[] getPath()
+       {
+               return path == null ? null : path.clone();
+       }
+
        // @formatter:off
        public void addRedrawListener   (Runnable listener) {redrawListeners         .add   (listener);}