X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=net.mograsim.logic.model%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fmodel%2Fmodel%2Fcomponents%2Fsubmodels%2FSubmodelComponent.java;h=f67be7d3942cd829605c504e62138120c0fdfb04;hb=0a04a4ed66ecebd4254541c4977599f6052c115a;hp=b5c1762b3bb50b89785769ed2319bc6d9e80b810;hpb=a00663c79d0e26b494ff79eee4b6c049f086c7e0;p=Mograsim.git
diff --git a/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/submodels/SubmodelComponent.java b/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/submodels/SubmodelComponent.java
index b5c1762b..f67be7d3 100644
--- a/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/submodels/SubmodelComponent.java
+++ b/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/submodels/SubmodelComponent.java
@@ -4,6 +4,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.function.Consumer;
import net.haspamelodica.swt.helper.gcs.GCConfig;
import net.haspamelodica.swt.helper.gcs.GeneralGC;
@@ -15,12 +16,19 @@ import net.mograsim.logic.model.model.ViewModelModifiable;
import net.mograsim.logic.model.model.components.GUIComponent;
import net.mograsim.logic.model.model.wires.MovablePin;
import net.mograsim.logic.model.model.wires.Pin;
+import net.mograsim.logic.model.model.wires.PinUsage;
+import net.mograsim.logic.model.serializing.IdentifyParams;
+import net.mograsim.logic.model.serializing.IndirectGUIComponentCreator;
+import net.mograsim.logic.model.serializing.SubmodelComponentParams;
+import net.mograsim.logic.model.serializing.SubmodelComponentSerializer;
+import net.mograsim.logic.model.snippets.Renderer;
+import net.mograsim.logic.model.util.JsonHandler;
+import net.mograsim.preferences.Preferences;
/**
* A {@link GUIComponent} consisting of another model. A SubmodelComponent
can have so-called "interface pins" connecting the
* inner and outer models.
*/
-//TODO override getParams
public abstract class SubmodelComponent extends GUIComponent
{
public static final String SUBMODEL_INTERFACE_NAME = "_submodelinterface";
@@ -80,6 +88,15 @@ public abstract class SubmodelComponent extends GUIComponent
*/
private final LogicUIRenderer renderer;
+ /**
+ * The {@link Renderer} used to render the symbol of this SubmodelCoponent.
+ */
+ private Renderer symbolRenderer;
+ /**
+ * The {@link Renderer} used to render the outline of this SubmodelCoponent.
+ */
+ private Renderer outlineRenderer;
+
// creation and destruction
public SubmodelComponent(ViewModelModifiable model, String name)
@@ -96,11 +113,18 @@ public abstract class SubmodelComponent extends GUIComponent
this.submodelInterface = new SubmodelInterface(submodelModifiable, SUBMODEL_INTERFACE_NAME);
this.submodelScale = 1;
- this.maxVisibleRegionFillRatioForAlpha0 = 0.4;
- this.minVisibleRegionFillRatioForAlpha1 = 0.8;
+ this.maxVisibleRegionFillRatioForAlpha0 = 0.8;
+ this.minVisibleRegionFillRatioForAlpha1 = 0.9;
this.renderer = new LogicUIRenderer(submodelModifiable);
- submodelModifiable.addRedrawListener(this::requestRedraw);
+ Consumer redrawHandlerChangedListener = submodelModifiable::setRedrawHandler;
+ model.addRedrawHandlerChangedListener(redrawHandlerChangedListener);
+ model.addComponentRemovedListener(c ->
+ {
+ if (c == this)
+ model.removeRedrawHandlerChangedListener(redrawHandlerChangedListener);
+ });
+ submodelModifiable.setRedrawHandler(model.getRedrawHandler());
}
// pins
@@ -119,8 +143,24 @@ public abstract class SubmodelComponent extends GUIComponent
super.addPin(supermodelPin);// do this first to be fail-fast if the supermodel does not belong to this component
String name = supermodelPin.name;
- MovablePin submodelPin = new MovablePin(submodelInterface, name, supermodelPin.logicWidth, supermodelPin.getRelX() / submodelScale,
- supermodelPin.getRelY() / submodelScale);
+ // TODO if we upgrade to Java 12, replace with switch-expression
+ PinUsage submodelPinUsage;
+ switch (supermodelPin.usage)
+ {
+ case INPUT:
+ submodelPinUsage = PinUsage.OUTPUT;
+ break;
+ case OUTPUT:
+ submodelPinUsage = PinUsage.INPUT;
+ break;
+ case TRISTATE:
+ submodelPinUsage = PinUsage.TRISTATE;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown enum constant: " + supermodelPin.usage);
+ }
+ MovablePin submodelPin = new MovablePin(submodelInterface, name, supermodelPin.logicWidth, submodelPinUsage,
+ supermodelPin.getRelX() / submodelScale, supermodelPin.getRelY() / submodelScale);
submodelPin.addPinMovedListener(p ->
{
@@ -256,7 +296,7 @@ public abstract class SubmodelComponent extends GUIComponent
for (Entry e : supermodelPins.entrySet())
getSubmodelMovablePin(e.getKey()).setRelPos(e.getValue().getRelX() * submodelScale, e.getValue().getRelY() * submodelScale);
- requestRedraw();// needed if there is no submodel interface pin
+ model.requestRedraw();// needed if there is no submodel interface pin
}
/**
@@ -269,11 +309,64 @@ public abstract class SubmodelComponent extends GUIComponent
return submodelScale;
}
+ /**
+ * @see #renderSymbol(GeneralGC, Rectangle)
+ *
+ * @author Daniel Kirschten
+ */
+ protected void setSymbolRenderer(Renderer symbolRenderer)
+ {
+ this.symbolRenderer = symbolRenderer;
+ model.requestRedraw();
+ }
+
+ /**
+ * @see #renderSymbol(GeneralGC, Rectangle)
+ *
+ * @author Daniel Kirschten
+ */
+ public Renderer getSymbolRenderer()
+ {
+ return symbolRenderer;
+ }
+
+ /**
+ * @see #renderOutline(GeneralGC, Rectangle)
+ *
+ * @author Daniel Kirschten
+ */
+ protected void setOutlineRenderer(Renderer outlineRenderer)
+ {
+ this.outlineRenderer = outlineRenderer;
+ model.requestRedraw();
+ }
+
+ /**
+ * @see #renderOutline(GeneralGC, Rectangle)
+ *
+ * @author Daniel Kirschten
+ */
+ public Renderer getOutlineRenderer()
+ {
+ return outlineRenderer;
+ }
+
+ @Override
+ public boolean clicked(double x, double y)
+ {
+ double scaledX = (x - getPosX()) / submodelScale;
+ double scaledY = (y - getPosY()) / submodelScale;
+ for (GUIComponent component : submodel.getComponentsByName().values())
+ if (component.getBounds().contains(scaledX, scaledY) && component.clicked(scaledX, scaledY))
+ return true;
+ return false;
+ }
+
@Override
public void render(GeneralGC gc, Rectangle visibleRegion)
{
GCConfig conf = new GCConfig(gc);
- TranslatedGC tgc = new TranslatedGC(gc, getPosX(), getPosY(), submodelScale, true);
+ GeneralGC tgc = new TranslatedGC(gc, getPosX(), getPosY(), submodelScale, true);
conf.reset(tgc);
double visibleRegionFillRatio = Math.max(getWidth() / visibleRegion.width, getHeight() / visibleRegion.height);
double alphaFactor = map(visibleRegionFillRatio, maxVisibleRegionFillRatioForAlpha0, minVisibleRegionFillRatioForAlpha1, 0, 1);
@@ -293,39 +386,51 @@ public abstract class SubmodelComponent extends GUIComponent
renderSymbol(gc, visibleRegion);
}
conf.reset(gc);
+ // reset line width explicitly to avoid rounding errors causing weird glitches
+ gc.setLineWidth(Preferences.current().getDouble("net.mograsim.logic.model.linewidth.default"));
// draw the outline after all other operations to make interface pins look better
renderOutline(gc, visibleRegion);
}
- // TODO make this a path
/**
- * Render the outline of this {@link SubmodelComponent}, e.g. the graphical elements that should stay visible if the submodel is drawn.
+ * Render the symbol of this {@link SubmodelComponent}, e.g. the things that should be hidden if the submodel is drawn.
*
* @author Daniel Kirschten
*/
- protected abstract void renderOutline(GeneralGC gc, Rectangle visibleRegion);
+ protected void renderSymbol(GeneralGC gc, Rectangle visibleRegion)
+ {
+ if (symbolRenderer != null)
+ symbolRenderer.render(gc, visibleRegion);
+ }
/**
- * Render the symbol of this {@link SubmodelComponent}, e.g. the things that should be hidden if the submodel is drawn.
+ * Render the outline of this {@link SubmodelComponent}, e.g. the graphical elements that should stay visible if the submodel is drawn.
*
* @author Daniel Kirschten
*/
- protected abstract void renderSymbol(GeneralGC gc, Rectangle visibleRegion);
+ protected void renderOutline(GeneralGC gc, Rectangle visibleRegion)
+ {
+ if (outlineRenderer != null)
+ outlineRenderer.render(gc, visibleRegion);
+ }
private static double map(double val, double valMin, double valMax, double mapMin, double mapMax)
{
return mapMin + (val - valMin) * (mapMax - mapMin) / (valMax - valMin);
}
+ // serializing
+
@Override
- public boolean clicked(double x, double y)
+ public String getIDForSerializing(IdentifyParams idParams)
{
- double scaledX = (x - getPosX()) / submodelScale;
- double scaledY = (y - getPosY()) / submodelScale;
- for (GUIComponent component : submodel.getComponentsByName().values())
- if (component.getBounds().contains(scaledX, scaledY) && component.clicked(scaledX, scaledY))
- return true;
- return false;
+ return "submodel";// TODO what ID?
+ }
+
+ @Override
+ public SubmodelComponentParams getParamsForSerializing(IdentifyParams idParams)
+ {
+ return SubmodelComponentSerializer.serialize(this, idParams);
}
// operations no longer supported
@@ -341,4 +446,10 @@ public abstract class SubmodelComponent extends GUIComponent
{
throw new UnsupportedOperationException("Can't remove pins of a SubmodelComponent directly, call removeSubmodelInterface instead");
}
+
+ static
+ {
+ IndirectGUIComponentCreator.setComponentSupplier(SubmodelComponent.class.getCanonicalName(),
+ (m, p, n) -> SubmodelComponentSerializer.deserialize(m, JsonHandler.fromJsonTree(p, SubmodelComponentParams.class), n));
+ }
}
\ No newline at end of file