1 package net.mograsim.logic.ui.model.components;
3 import java.util.Collections;
4 import java.util.HashMap;
6 import java.util.Map.Entry;
8 import net.haspamelodica.swt.helper.gcs.GCConfig;
9 import net.haspamelodica.swt.helper.gcs.GeneralGC;
10 import net.haspamelodica.swt.helper.gcs.TranslatedGC;
11 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
12 import net.mograsim.logic.ui.LogicUIRenderer;
13 import net.mograsim.logic.ui.model.ViewModel;
14 import net.mograsim.logic.ui.model.ViewModelModifiable;
15 import net.mograsim.logic.ui.model.wires.Pin;
17 public abstract class SubmodelComponent extends GUIComponent
19 protected final ViewModelModifiable submodelModifiable;
20 public final ViewModel submodel;
21 private final Map<PinMovable, PinMovable> submodelPinsPerSupermodelPin;
22 private final Map<Pin, Pin> submodelPinsPerSupermodelPinUnmodifiable;
23 private final Map<PinMovable, PinMovable> supermodelPinsPerSubmodelPin;
24 private final Map<Pin, Pin> supermodelPinsPerSubmodelPinUnmodifiable;
25 private final SubmodelInterface submodelInterface;
27 private double submodelScale;
28 private double maxVisibleRegionFillRatioForAlpha0;
29 private double minVisibleRegionFillRatioForAlpha1;
30 private final LogicUIRenderer renderer;
32 public SubmodelComponent(ViewModelModifiable model)
35 this.submodelModifiable = new ViewModelModifiable();
36 this.submodel = submodelModifiable;
37 this.submodelPinsPerSupermodelPin = new HashMap<>();
38 this.submodelPinsPerSupermodelPinUnmodifiable = Collections.unmodifiableMap(submodelPinsPerSupermodelPin);
39 this.supermodelPinsPerSubmodelPin = new HashMap<>();
40 this.supermodelPinsPerSubmodelPinUnmodifiable = Collections.unmodifiableMap(supermodelPinsPerSubmodelPin);
41 this.submodelInterface = new SubmodelInterface(submodelModifiable);
43 this.submodelScale = 1;
44 this.maxVisibleRegionFillRatioForAlpha0 = 0.4;
45 this.minVisibleRegionFillRatioForAlpha1 = 0.8;
46 this.renderer = new LogicUIRenderer(submodelModifiable);
48 submodelModifiable.addRedrawListener(this::requestRedraw);
51 protected void setSubmodelScale(double submodelScale)
53 this.submodelScale = submodelScale;
55 for (Entry<PinMovable, PinMovable> e : supermodelPinsPerSubmodelPin.entrySet())
56 e.getKey().setRelPos(e.getValue().getRelX() * submodelScale, e.getValue().getRelY() * submodelScale);
58 requestRedraw();// needed if there is no submodel interface pin
62 * Returns the submodel pin.
64 protected Pin addSubmodelInterface(int logicWidth, double relX, double relY)
66 PinMovable submodelPin = new PinMovable(submodelInterface, logicWidth, relX / submodelScale, relY / submodelScale);
67 submodelInterface.addPin(submodelPin);
69 PinMovable supermodelPin = new PinMovable(this, logicWidth, relX, relY);
70 addPin(supermodelPin);
72 submodelPinsPerSupermodelPin.put(supermodelPin, submodelPin);
73 supermodelPinsPerSubmodelPin.put(submodelPin, supermodelPin);
75 // no need to call requestRedraw() because addPin() will request a redraw
79 protected void moveSubmodelInterface(Pin supermodelPin, double relX, double relY)
81 PinMovable submodelPin = getSubmodelMovablePin(supermodelPin);
82 PinMovable supermodelPinMovable = getSupermodelMovablePin(submodelPin);
84 submodelPin.setRelPos(relX / submodelScale, relY / submodelScale);
85 supermodelPinMovable.setRelPos(relX, relY);
87 // no need to call requestRedraw() because setRelPos() will request a redraw
90 protected void removeSubmodelInterface(Pin supermodelPin)
92 removePin(supermodelPin);
93 Pin submodelPin = getSubmodelMovablePin(supermodelPin);
94 submodelInterface.removePin(submodelPin);
96 submodelPinsPerSupermodelPin.remove(supermodelPin);
97 supermodelPinsPerSubmodelPin.remove(submodelPin);
99 // no need to call requestRedraw() because removePin() will request a redraw
102 public Map<Pin, Pin> getSupermodelPinsPerSubmodelPin()
104 return supermodelPinsPerSubmodelPinUnmodifiable;
107 public Pin getSupermodelPin(Pin submodelPin)
109 return getSupermodelMovablePin(submodelPin);
112 protected PinMovable getSupermodelMovablePin(Pin submodelPin)
114 return supermodelPinsPerSubmodelPin.get(submodelPin);
117 public Map<Pin, Pin> getSubmodelPinsPerSupermodelPin()
119 return submodelPinsPerSupermodelPinUnmodifiable;
122 public Pin getSubmodelPin(Pin supermodelPin)
124 return getSubmodelMovablePin(supermodelPin);
127 protected PinMovable getSubmodelMovablePin(Pin supermodelPin)
129 return submodelPinsPerSupermodelPin.get(supermodelPin);
133 public void render(GeneralGC gc, Rectangle visibleRegion)
135 double posX = getBounds().x;
136 double posY = getBounds().y;
138 GCConfig conf = new GCConfig(gc);
139 TranslatedGC tgc = new TranslatedGC(gc, posX, posY, submodelScale, true);
141 double visibleRegionFillRatio = Math.max(getBounds().width / visibleRegion.width, getBounds().height / visibleRegion.height);
142 double alphaFactor = map(visibleRegionFillRatio, maxVisibleRegionFillRatioForAlpha0, minVisibleRegionFillRatioForAlpha1, 0, 1);
143 alphaFactor = Math.max(0, Math.min(1, alphaFactor));
144 // we need to take the old alpha into account to support nested submodules better.
145 int oldAlpha = gc.getAlpha();
146 int submodelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * alphaFactor)));
147 int labelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * (1 - alphaFactor))));
148 if (submodelAlpha != 0)
150 gc.setAlpha(submodelAlpha);
151 renderer.render(tgc, visibleRegion.translate(-posX, -posY, 1 / submodelScale));
155 gc.setAlpha(labelAlpha);
159 // draw the outline after all other operations to make interface pins look better
163 protected abstract void renderOutline(GeneralGC gc);
165 protected abstract void renderSymbol(GeneralGC gc);
167 private static double map(double val, double valMin, double valMax, double mapMin, double mapMax)
169 return mapMin + (val - valMin) * (mapMax - mapMin) / (valMax - valMin);
173 public boolean clicked(double x, double y)
176 double scaledX = (x - getBounds().x) / submodelScale;
177 double scaledY = (y - getBounds().y) / submodelScale;
178 double roundedScaledX = Math.round(scaledX / 5 * 2) * 5 / 2.;
179 double roundedScaledY = Math.round(scaledY / 5 * 2) * 5 / 2.;
180 System.out.println(scaledX + "|" + scaledY + ", rounded " + roundedScaledX + "|" + roundedScaledY);
184 private static class PinMovable extends Pin
186 public PinMovable(GUIComponent component, int logicWidth, double relX, double relY)
188 super(component, logicWidth, relX, relY);
192 protected void setRelPos(double relX, double relY)
194 super.setRelPos(relX, relY);