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
61 protected double getSubmodelScale()
67 * Returns the submodel pin.
69 protected Pin addSubmodelInterface(int logicWidth, double relX, double relY)
71 PinMovable submodelPin = new PinMovable(submodelInterface, logicWidth, relX / submodelScale, relY / submodelScale);
72 submodelInterface.addPin(submodelPin);
74 PinMovable supermodelPin = new PinMovable(this, logicWidth, relX, relY);
75 addPin(supermodelPin);
77 submodelPinsPerSupermodelPin.put(supermodelPin, submodelPin);
78 supermodelPinsPerSubmodelPin.put(submodelPin, supermodelPin);
80 // no need to call requestRedraw() because addPin() will request a redraw
84 protected void moveSubmodelInterface(Pin supermodelPin, double relX, double relY)
86 PinMovable submodelPin = getSubmodelMovablePin(supermodelPin);
87 PinMovable supermodelPinMovable = getSupermodelMovablePin(submodelPin);
89 submodelPin.setRelPos(relX / submodelScale, relY / submodelScale);
90 supermodelPinMovable.setRelPos(relX, relY);
92 // no need to call requestRedraw() because setRelPos() will request a redraw
95 protected void removeSubmodelInterface(Pin supermodelPin)
97 removePin(supermodelPin);
98 Pin submodelPin = getSubmodelMovablePin(supermodelPin);
99 submodelInterface.removePin(submodelPin);
101 submodelPinsPerSupermodelPin.remove(supermodelPin);
102 supermodelPinsPerSubmodelPin.remove(submodelPin);
104 // no need to call requestRedraw() because removePin() will request a redraw
107 public Map<Pin, Pin> getSupermodelPinsPerSubmodelPin()
109 return supermodelPinsPerSubmodelPinUnmodifiable;
112 public Pin getSupermodelPin(Pin submodelPin)
114 return getSupermodelMovablePin(submodelPin);
117 protected PinMovable getSupermodelMovablePin(Pin submodelPin)
119 return supermodelPinsPerSubmodelPin.get(submodelPin);
122 public Map<Pin, Pin> getSubmodelPinsPerSupermodelPin()
124 return submodelPinsPerSupermodelPinUnmodifiable;
127 public Pin getSubmodelPin(Pin supermodelPin)
129 return getSubmodelMovablePin(supermodelPin);
132 protected PinMovable getSubmodelMovablePin(Pin supermodelPin)
134 return submodelPinsPerSupermodelPin.get(supermodelPin);
138 public void render(GeneralGC gc, Rectangle visibleRegion)
140 double posX = getBounds().x;
141 double posY = getBounds().y;
143 GCConfig conf = new GCConfig(gc);
144 TranslatedGC tgc = new TranslatedGC(gc, posX, posY, submodelScale, true);
146 double visibleRegionFillRatio = Math.max(getBounds().width / visibleRegion.width, getBounds().height / visibleRegion.height);
147 double alphaFactor = map(visibleRegionFillRatio, maxVisibleRegionFillRatioForAlpha0, minVisibleRegionFillRatioForAlpha1, 0, 1);
148 alphaFactor = Math.max(0, Math.min(1, alphaFactor));
149 // we need to take the old alpha into account to support nested submodules better.
150 int oldAlpha = gc.getAlpha();
151 int submodelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * alphaFactor)));
152 int labelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * (1 - alphaFactor))));
153 if (submodelAlpha != 0)
155 gc.setAlpha(submodelAlpha);
156 renderer.render(tgc, visibleRegion.translate(posX / submodelScale, posY / submodelScale, 1 / submodelScale));
160 gc.setAlpha(labelAlpha);
161 renderSymbol(gc, visibleRegion);
164 // draw the outline after all other operations to make interface pins look better
165 renderOutline(gc, visibleRegion);
168 protected abstract void renderOutline(GeneralGC gc, Rectangle visibleRegion);
170 protected abstract void renderSymbol(GeneralGC gc, Rectangle visibleRegion);
172 private static double map(double val, double valMin, double valMax, double mapMin, double mapMax)
174 return mapMin + (val - valMin) * (mapMax - mapMin) / (valMax - valMin);
178 public boolean clicked(double x, double y)
181 double scaledX = (x - getBounds().x) / submodelScale;
182 double scaledY = (y - getBounds().y) / submodelScale;
183 double roundedScaledX = Math.round(scaledX / 5 * 2) * 5 / 2.;
184 double roundedScaledY = Math.round(scaledY / 5 * 2) * 5 / 2.;
185 System.out.println(scaledX + "|" + scaledY + ", rounded " + roundedScaledX + "|" + roundedScaledY);
189 private static class PinMovable extends Pin
191 public PinMovable(GUIComponent component, int logicWidth, double relX, double relY)
193 super(component, logicWidth, relX, relY);
197 protected void setRelPos(double relX, double relY)
199 super.setRelPos(relX, relY);