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.Font;
12 import net.haspamelodica.swt.helper.swtobjectwrappers.Point;
13 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
14 import net.mograsim.logic.ui.LogicUIRenderer;
15 import net.mograsim.logic.ui.model.ViewModel;
16 import net.mograsim.logic.ui.model.ViewModelModifiable;
17 import net.mograsim.logic.ui.model.wires.Pin;
19 public class SubmodelComponent extends GUIComponent
21 protected final ViewModelModifiable submodelModifiable;
22 public final ViewModel submodel;
23 private final Map<PinMovable, PinMovable> submodelPinsPerSupermodelPin;
24 private final Map<Pin, Pin> submodelPinsPerSupermodelPinUnmodifiable;
25 private final Map<PinMovable, PinMovable> supermodelPinsPerSubmodelPin;
26 private final Map<Pin, Pin> supermodelPinsPerSubmodelPinUnmodifiable;
27 private final SubmodelInterface submodelInterface;
29 private final String label;
30 private double submodelScale;
31 private double maxVisibleRegionFillRatioForAlpha0;
32 private double minVisibleRegionFillRatioForAlpha1;
33 private final LogicUIRenderer renderer;
35 public SubmodelComponent(ViewModelModifiable model, String label)
38 this.submodelModifiable = new ViewModelModifiable();
39 this.submodel = submodelModifiable;
40 this.submodelPinsPerSupermodelPin = new HashMap<>();
41 this.submodelPinsPerSupermodelPinUnmodifiable = Collections.unmodifiableMap(submodelPinsPerSupermodelPin);
42 this.supermodelPinsPerSubmodelPin = new HashMap<>();
43 this.supermodelPinsPerSubmodelPinUnmodifiable = Collections.unmodifiableMap(supermodelPinsPerSubmodelPin);
44 this.submodelInterface = new SubmodelInterface(submodelModifiable);
47 this.submodelScale = 1;
48 this.maxVisibleRegionFillRatioForAlpha0 = 0.4;
49 this.minVisibleRegionFillRatioForAlpha1 = 0.8;
50 this.renderer = new LogicUIRenderer(submodelModifiable);
52 submodelModifiable.addRedrawListener(this::requestRedraw);
55 protected void setSubmodelScale(double submodelScale)
57 this.submodelScale = submodelScale;
59 for (Entry<PinMovable, PinMovable> e : supermodelPinsPerSubmodelPin.entrySet())
60 e.getKey().setRelPos(e.getValue().getRelX() * submodelScale, e.getValue().getRelY() * submodelScale);
62 requestRedraw();// needed if there is no submodel interface pin
66 * Returns the submodel pin.
68 protected Pin addSubmodelInterface(int logicWidth, double relX, double relY)
70 PinMovable submodelPin = new PinMovable(submodelInterface, logicWidth, relX / submodelScale, relY / submodelScale);
71 submodelInterface.addPin(submodelPin);
73 PinMovable supermodelPin = new PinMovable(this, logicWidth, relX, relY);
74 addPin(supermodelPin);
76 submodelPinsPerSupermodelPin.put(supermodelPin, submodelPin);
77 supermodelPinsPerSubmodelPin.put(submodelPin, supermodelPin);
79 // no need to call requestRedraw() because addPin() will request a redraw
83 protected void moveSubmodelInterface(Pin supermodelPin, double relX, double relY)
85 PinMovable submodelPin = getSubmodelMovablePin(supermodelPin);
86 PinMovable supermodelPinMovable = getSupermodelMovablePin(submodelPin);
88 submodelPin.setRelPos(relX / submodelScale, relY / submodelScale);
89 supermodelPinMovable.setRelPos(relX, relY);
91 // no need to call requestRedraw() because setRelPos() will request a redraw
94 protected void removeSubmodelInterface(Pin supermodelPin)
96 removePin(supermodelPin);
97 Pin submodelPin = getSubmodelMovablePin(supermodelPin);
98 submodelInterface.removePin(submodelPin);
100 submodelPinsPerSupermodelPin.remove(supermodelPin);
101 supermodelPinsPerSubmodelPin.remove(submodelPin);
103 // no need to call requestRedraw() because removePin() will request a redraw
106 public Map<Pin, Pin> getSupermodelPinsPerSubmodelPin()
108 return supermodelPinsPerSubmodelPinUnmodifiable;
111 public Pin getSupermodelPin(Pin submodelPin)
113 return getSupermodelMovablePin(submodelPin);
116 protected PinMovable getSupermodelMovablePin(Pin submodelPin)
118 return supermodelPinsPerSubmodelPin.get(submodelPin);
121 public Map<Pin, Pin> getSubmodelPinsPerSupermodelPin()
123 return submodelPinsPerSupermodelPinUnmodifiable;
126 public Pin getSubmodelPin(Pin supermodelPin)
128 return getSubmodelMovablePin(supermodelPin);
131 protected PinMovable getSubmodelMovablePin(Pin supermodelPin)
133 return submodelPinsPerSupermodelPin.get(supermodelPin);
137 public void render(GeneralGC gc, Rectangle visibleRegion)
139 double posX = getBounds().x;
140 double posY = getBounds().y;
142 GCConfig conf = new GCConfig(gc);
143 TranslatedGC tgc = new TranslatedGC(gc, posX, posY, submodelScale, true);
145 double visibleRegionFillRatio = Math.max(getBounds().width / visibleRegion.width, getBounds().height / visibleRegion.height);
146 double alphaFactor = map(visibleRegionFillRatio, maxVisibleRegionFillRatioForAlpha0, minVisibleRegionFillRatioForAlpha1, 0, 1);
147 alphaFactor = Math.max(0, Math.min(1, alphaFactor));
148 // we need to take the old alpha into account to support nested submodules better.
149 int oldAlpha = gc.getAlpha();
150 int submodelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * alphaFactor)));
151 int labelAlpha = Math.max(0, Math.min(255, (int) (oldAlpha * (1 - alphaFactor))));
152 if (submodelAlpha != 0)
154 gc.setAlpha(submodelAlpha);
155 renderer.render(tgc, visibleRegion.translate(-posX, -posY, 1 / submodelScale));
159 gc.setAlpha(labelAlpha);
160 Font oldFont = gc.getFont();
161 Font labelFont = new Font(oldFont.getName(), 6, oldFont.getStyle());
162 gc.setFont(labelFont);
163 Point textExtent = gc.textExtent(label);
164 gc.drawText(label, posX + (getBounds().width - textExtent.x) / 2, posY + (getBounds().height - textExtent.y) / 2, true);
168 // draw the "bounding box" after all other operations to make interface pins look better
169 gc.drawRectangle(getBounds());
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 System.out.println(((x - getBounds().x) / submodelScale) + "|" + ((y - getBounds().y) / submodelScale));
185 private static class PinMovable extends Pin
187 public PinMovable(GUIComponent component, int logicWidth, double relX, double relY)
189 super(component, logicWidth, relX, relY);
193 protected void setRelPos(double relX, double relY)
195 super.setRelPos(relX, relY);