import net.haspamelodica.swt.helper.gcs.GeneralGC;
import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
-import net.mograsim.logic.model.model.ViewModelModifiable;
+import net.mograsim.logic.model.model.LogicModelModifiable;
import net.mograsim.logic.model.model.wires.Pin;
import net.mograsim.logic.model.serializing.IdentifyParams;
import net.mograsim.logic.model.serializing.JSONSerializable;
/**
* The base class for all model components.<br>
- * A <code>ModelComponent</code> has a reference to the ViewModel it belongs to.<br>
+ * A <code>ModelComponent</code> has a reference to the LogicModel it belongs to.<br>
* A <code>ModelComponent</code> has a name. This name is unique in the model the <code>ModelComponent</code> belongs to.<br>
* A <code>ModelComponent</code> has a position and size. The size can only be modified by subclasses.
*
/**
* The model this component is a part of.
*/
- protected final ViewModelModifiable model;
+ protected final LogicModelModifiable model;
/**
- * The name of this component. Is unique for all components in its model.
+ * The name of this component. Is unique for all components in its model.<br>
+ * Does never change, but can't be final since it is set in {@link #init()}.
*/
- public final String name;
+ private String name;
private final Rectangle bounds;
/**
* The list of all pins of this component by name.
// creation and destruction
- public ModelComponent(ViewModelModifiable model, String name)
+ public ModelComponent(LogicModelModifiable model, String name)
+ {
+ this(model, name, true);
+ }
+
+ /**
+ * Creates a new {@link ModelComponent} and, if <code>callInit</code>, initializes the component (See {@link #init()}).<br>
+ * If <code>callInit==false</code>, make sure to call {@link #init()}!
+ *
+ * @author Daniel Kirschten
+ */
+ protected ModelComponent(LogicModelModifiable model, String name, boolean callInit)
{
this.model = model;
- this.name = name == null ? model.getDefaultComponentName(this) : name;
+ this.name = name;
this.bounds = new Rectangle(0, 0, 0, 0);
this.pinsByName = new HashMap<>();
this.pinsUnmodifiable = Collections.unmodifiableMap(pinsByName);
this.pinAddedListeners = new ArrayList<>();
this.pinRemovedListeners = new ArrayList<>();
- // TODO this will crash the high level state debug shell because submodel is not yet set.
- // The same problem exists in ViewModelModifiable.getDefaultComponentName; see there
+ if (callInit)
+ init();
+ }
+
+ /**
+ * Initializes this component. This method should be called exactly once in this component's constructor.<br>
+ * <ul>
+ * <li>If <code>{@link #name}==null</code>, sets {@link #name} to {@link LogicModelModifiable#getDefaultComponentName(ModelComponent)}.
+ * <li>Registers this component in the model.
+ * </ul>
+ */
+ protected void init()
+ {
+ if (name == null)
+ name = model.getDefaultComponentName(this);
model.componentCreated(this, this::destroyed);
}
+ // basic getters
+
+ public String getName()
+ {
+ return name;
+ }
+
/**
- * Destroys this component. This method is called from {@link ViewModelModifiable#componentDestroyed(ModelComponent) destroyComponent()}
- * of the model this component is a part of.<br>
+ * Destroys this component. This method is called from {@link LogicModelModifiable#componentDestroyed(ModelComponent)
+ * destroyComponent()} of the model this component is a part of.<br>
* When overriding, make sure to also call the original implementation.
*
* @author Daniel Kirschten
*/
protected void destroyed()
{
- pinsByName.values().forEach(p -> pinRemovedListeners.forEach(l -> l.accept(p)));
+ pinsByName.values().forEach(this::removePinWithoutRedraw);
}
// pins
*/
protected void removePin(String name)
{
- Pin pin = pinsByName.remove(name);
- callPinRemovedListeners(pin);
+ removePinWithoutRedraw(pinsByName.remove(name));
model.requestRedraw();
}
+ private void removePinWithoutRedraw(Pin pin)
+ {
+ pin.destroyed();
+ callPinRemovedListeners(pin);
+ }
+
/**
* Returns a collection of pins of this component.
*
* Returns the pin with the given name of this component.
*
* @throws IllegalArgumentException if there is no pin with the given name
+ * @see #getPinOrNull(String)
*
* @author Daniel Kirschten
*/
public Pin getPin(String name)
{
- Pin pin = pinsByName.get(name);
+ Pin pin = getPinOrNull(name);
if (pin == null)
throw new IllegalArgumentException("No pin with the name " + name);
return pin;
}
+ /**
+ * Returns the pin with the given name of this component, or <code>null</code> if there is no such pin.
+ *
+ * @see #getPin(String)
+ *
+ * @author Daniel Kirschten
+ */
+ public Pin getPinOrNull(String name)
+ {
+ return pinsByName.get(name);
+ }
+
// high-level access
/**