1 package net.mograsim.logic.ui.model.components;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
9 import java.util.TreeMap;
10 import java.util.function.Consumer;
11 import java.util.function.Supplier;
13 import net.haspamelodica.swt.helper.gcs.GeneralGC;
14 import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
15 import net.mograsim.logic.ui.model.ViewModelModifiable;
16 import net.mograsim.logic.ui.model.wires.Pin;
18 public abstract class GUIComponent
20 protected final ViewModelModifiable model;
21 private final Rectangle bounds;
22 private final Map<String, Pin> pinsByName;
23 protected final Collection<Pin> pinsUnmodifiable;
25 private final List<Consumer<? super GUIComponent>> componentMovedListeners;
26 private final List<Consumer<? super Pin>> pinAddedListeners;
27 private final List<Consumer<? super Pin>> pinRemovedListeners;
28 private final List<Runnable> redrawListeners;
30 private final Runnable redrawListenerForSubcomponents;
31 // Defines how the GUIComponent is referenced in SubmodelComponentParams
32 protected Supplier<String> identifierDelegate = () -> "class:".concat(getClass().getCanonicalName());
34 public GUIComponent(ViewModelModifiable model)
37 this.bounds = new Rectangle(0, 0, 0, 0);
38 this.pinsByName = new HashMap<>();
39 this.pinsUnmodifiable = Collections.unmodifiableCollection(pinsByName.values());
41 this.componentMovedListeners = new ArrayList<>();
42 this.pinAddedListeners = new ArrayList<>();
43 this.pinRemovedListeners = new ArrayList<>();
44 this.redrawListeners = new ArrayList<>();
46 redrawListenerForSubcomponents = this::callRedrawListeners;
48 model.componentCreated(this);
53 pinsByName.values().forEach(p -> pinRemovedListeners.forEach(l -> l.accept(p)));
54 model.componentDestroyed(this);
57 public void moveTo(double x, double y)
61 callComponentMovedListeners();
65 * Returns the bounds of this component. Used for calculating which component is clicked.
67 public Rectangle getBounds()
69 return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
72 public double getPosX()
77 public double getPosY()
82 public double getWidth()
87 public double getHeight()
93 * Called when this component is clicked. Absolute coordinates of the click are given. Returns true if this component consumed this
96 @SuppressWarnings({ "static-method", "unused" }) // this method is inteded to be overridden
97 public boolean clicked(double x, double y)
103 * Returns a collection of pins of this component.
105 public Collection<Pin> getPins()
107 return pinsUnmodifiable;
110 public Pin getPin(String name)
112 Pin pin = pinsByName.get(name);
114 throw new IllegalArgumentException("No pin with the name " + name);
119 public void addComponentMovedListener (Consumer<? super GUIComponent> listener) {componentMovedListeners.add (listener);}
120 public void addPinAddedListener (Consumer<? super Pin > listener) {pinAddedListeners .add (listener);}
121 public void addPinRemovedListener (Consumer<? super Pin > listener) {pinRemovedListeners .add (listener);}
122 public void addRedrawListener (Runnable listener) {redrawListeners .add (listener);}
124 public void removeComponentMovedListener(Consumer<? super GUIComponent> listener) {componentMovedListeners .remove(listener);}
125 public void removePinAddedListener (Consumer<? super Pin > listener) {pinAddedListeners .remove(listener);}
126 public void removePinRemovedListener (Consumer<? super Pin > listener) {pinRemovedListeners .remove(listener);}
127 public void removeRedrawListener (Runnable listener) {redrawListeners .remove(listener);}
129 private void callComponentMovedListeners( ) {componentMovedListeners.forEach(l -> l.accept(this));}
130 private void callPinAddedListeners (Pin p) {pinAddedListeners .forEach(l -> l.accept(p ));}
131 private void callPinRemovedListeners (Pin p) {pinRemovedListeners .forEach(l -> l.accept(p ));}
132 private void callRedrawListeners ( ) {redrawListeners .forEach(l -> l.run( ));}
136 * Render this component to the given gc.
138 public abstract void render(GeneralGC gc, Rectangle visibleRegion);
140 protected void requestRedraw()
142 callRedrawListeners();
145 protected void setSize(double width, double height)
147 bounds.width = width;
148 bounds.height = height;
149 callRedrawListeners();
152 protected void addPin(Pin pin)
154 if (pinsByName.containsKey(pin.name))
155 throw new IllegalArgumentException("Duplicate pin name: " + pin.name);
156 pinsByName.put(pin.name, pin);
157 callPinAddedListeners(pin);
158 pin.addRedrawListener(redrawListenerForSubcomponents);
159 callRedrawListeners();
162 protected void removePin(String name)
164 Pin pin = pinsByName.remove(name);
165 callPinRemovedListeners(pin);
166 pin.removeRedrawListener(redrawListenerForSubcomponents);
167 callRedrawListeners();
171 * @return an identifier used to reference this GUIComponent inside of {@link SubmodelComponentParams}
173 public String getIdentifier()
175 return identifierDelegate.get();
178 @SuppressWarnings("static-method")
179 public Map<String, Object> getInstantiationParameters()
181 return new TreeMap<>();