General SubmodelComponents can now be saved to a json format
[Mograsim.git] / net.mograsim.logic.ui / src / net / mograsim / logic / ui / model / components / SubmodelComponent.java
index 4b67650..b9939af 100644 (file)
@@ -2,10 +2,12 @@ package net.mograsim.logic.ui.model.components;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import net.haspamelodica.swt.helper.gcs.GCDefaultConfig;
+import net.haspamelodica.swt.helper.gcs.GCConfig;
 import net.haspamelodica.swt.helper.gcs.GeneralGC;
 import net.haspamelodica.swt.helper.gcs.TranslatedGC;
 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
@@ -13,9 +15,16 @@ import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
 import net.mograsim.logic.ui.LogicUIRenderer;
 import net.mograsim.logic.ui.model.ViewModel;
 import net.mograsim.logic.ui.model.ViewModelModifiable;
+import net.mograsim.logic.ui.model.components.params.GeneralComponentParams;
+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.InnerPinParams;
+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.wires.GUIWire;
 import net.mograsim.logic.ui.model.wires.Pin;
 
-public class SubmodelComponent extends GUIComponent
+public abstract class SubmodelComponent extends GUIComponent
 {
        protected final ViewModelModifiable submodelModifiable;
        public final ViewModel submodel;
@@ -25,13 +34,12 @@ public class SubmodelComponent extends GUIComponent
        private final Map<Pin, Pin> supermodelPinsPerSubmodelPinUnmodifiable;
        private final SubmodelInterface submodelInterface;
 
-       private final String label;
        private double submodelScale;
        private double maxVisibleRegionFillRatioForAlpha0;
        private double minVisibleRegionFillRatioForAlpha1;
        private final LogicUIRenderer renderer;
 
-       public SubmodelComponent(ViewModelModifiable model, String label)
+       public SubmodelComponent(ViewModelModifiable model)
        {
                super(model);
                this.submodelModifiable = new ViewModelModifiable();
@@ -42,9 +50,8 @@ public class SubmodelComponent extends GUIComponent
                this.supermodelPinsPerSubmodelPinUnmodifiable = Collections.unmodifiableMap(supermodelPinsPerSubmodelPin);
                this.submodelInterface = new SubmodelInterface(submodelModifiable);
 
-               this.label = label;
                this.submodelScale = 1;
-               this.maxVisibleRegionFillRatioForAlpha0 = 0.1;
+               this.maxVisibleRegionFillRatioForAlpha0 = 0.4;
                this.minVisibleRegionFillRatioForAlpha1 = 0.8;
                this.renderer = new LogicUIRenderer(submodelModifiable);
 
@@ -61,6 +68,11 @@ public class SubmodelComponent extends GUIComponent
                requestRedraw();// needed if there is no submodel interface pin
        }
 
+       protected double getSubmodelScale()
+       {
+               return submodelScale;
+       }
+
        /**
         * Returns the submodel pin.
         */
@@ -138,7 +150,7 @@ public class SubmodelComponent extends GUIComponent
                double posX = getBounds().x;
                double posY = getBounds().y;
 
-               GCDefaultConfig conf = new GCDefaultConfig(gc);
+               GCConfig conf = new GCConfig(gc);
                TranslatedGC tgc = new TranslatedGC(gc, posX, posY, submodelScale, true);
                conf.reset(tgc);
                double visibleRegionFillRatio = Math.max(getBounds().width / visibleRegion.width, getBounds().height / visibleRegion.height);
@@ -146,21 +158,44 @@ public class SubmodelComponent extends GUIComponent
                alphaFactor = Math.max(0, Math.min(1, alphaFactor));
                // we need to take the old alpha into account to support nested submodules better.
                int oldAlpha = gc.getAlpha();
-               gc.setAlpha(Math.max(0, Math.min(255, (int) (oldAlpha * alphaFactor))));
-               renderer.render(tgc, visibleRegion.translate(posX, posY, submodelScale));
-               gc.setAlpha(Math.max(0, Math.min(255, (int) (oldAlpha * (1 - alphaFactor)))));
-               Point textExtent = gc.textExtent(label);
-               gc.drawText(label, posX + (getBounds().width - textExtent.x) / 2, posY + (getBounds().height - textExtent.y) / 2, true);
+               int submodelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * alphaFactor)));
+               int labelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * (1 - alphaFactor))));
+               if (submodelAlpha != 0)
+               {
+                       gc.setAlpha(submodelAlpha);
+                       renderer.render(tgc, visibleRegion.translate(posX / submodelScale, posY / submodelScale, 1 / submodelScale));
+               }
+               if (labelAlpha != 0)
+               {
+                       gc.setAlpha(labelAlpha);
+                       renderSymbol(gc, visibleRegion);
+               }
                conf.reset(gc);
-               // draw the "bounding box" after all other operations to make interface pins look better
-               gc.drawRectangle(getBounds());
+               // draw the outline after all other operations to make interface pins look better
+               renderOutline(gc, visibleRegion);
        }
 
+       protected abstract void renderOutline(GeneralGC gc, Rectangle visibleRegion);
+
+       protected abstract void renderSymbol(GeneralGC gc, Rectangle visibleRegion);
+
        private static double map(double val, double valMin, double valMax, double mapMin, double mapMax)
        {
                return mapMin + (val - valMin) * (mapMax - mapMin) / (valMax - valMin);
        }
 
+       @Override
+       public boolean clicked(double x, double y)
+       {
+               // TODO
+               double scaledX = (x - getBounds().x) / submodelScale;
+               double scaledY = (y - getBounds().y) / submodelScale;
+               double roundedScaledX = Math.round(scaledX / 5 * 2) * 5 / 2.;
+               double roundedScaledY = Math.round(scaledY / 5 * 2) * 5 / 2.;
+               System.out.println(scaledX + "|" + scaledY + ", rounded " + roundedScaledX + "|" + roundedScaledY);
+               return true;
+       }
+
        private static class PinMovable extends Pin
        {
                public PinMovable(GUIComponent component, int logicWidth, double relX, double relY)
@@ -174,4 +209,73 @@ public class SubmodelComponent extends GUIComponent
                        super.setRelPos(relX, relY);
                }
        }
+
+       public SubComponentParams calculateParams()
+       {
+               SubComponentParams params = new SubComponentParams();
+               params.composition = calculateCompositionParams();
+
+               Rectangle bounds = getBounds();
+               params.width = bounds.width;
+               params.height = bounds.height;
+
+               List<Pin> pinList = pinsUnmodifiable;
+               InterfacePinParams[] iPins = new InterfacePinParams[pinList.size()];
+               int i = 0;
+               for (Pin p : pinList)
+               {
+                       InterfacePinParams iPinParams = new InterfacePinParams();
+                       iPins[i] = iPinParams;
+                       iPinParams.location = p.getRelPos();
+                       iPinParams.logicWidth = p.logicWidth;
+                       i++;
+               }
+               params.interfacePins = iPins;
+               return params;
+       }
+
+       protected GeneralComponentParams calculateCompositionParams()
+       {
+               GeneralComponentParams params = new GeneralComponentParams();
+               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);
+                       inner.type = component.getIdentifier();
+                       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