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
--- /dev/null
+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();
+ }
+}
--- /dev/null
+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;
+ }
+}
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import net.haspamelodica.swt.helper.gcs.GeneralGC;
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
{
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
requestRedraw();// needed if there is no submodel interface pin
}
+ protected double getSubmodelScale()
+ {
+ return submodelScale;
+ }
+
/**
* Returns the submodel pin.
*/
return pin2;
}
+ public Point[] getPath()
+ {
+ return path == null ? null : path.clone();
+ }
+
// @formatter:off
public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);}