X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=plugins%2Fnet.mograsim.logic.model%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fmodel%2Fmodel%2Fcomponents%2Fatomic%2FSimpleRectangularHardcodedModelComponent.java;fp=plugins%2Fnet.mograsim.logic.model%2Fsrc%2Fnet%2Fmograsim%2Flogic%2Fmodel%2Fmodel%2Fcomponents%2Fatomic%2FSimpleRectangularHardcodedModelComponent.java;h=427a179230c49cb36dd975e79dd76c1469bbb513;hb=69ec19d54ceb6d5abbb8b4faa55284af22174859;hp=8971285a59b48b29fcae1c464b0caf1117bbc4fc;hpb=f1933b06b5fe800902131e4dc34f002ac3fa17f0;p=Mograsim.git diff --git a/plugins/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/SimpleRectangularHardcodedModelComponent.java b/plugins/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/SimpleRectangularHardcodedModelComponent.java index 8971285a..427a1792 100644 --- a/plugins/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/SimpleRectangularHardcodedModelComponent.java +++ b/plugins/net.mograsim.logic.model/src/net/mograsim/logic/model/model/components/atomic/SimpleRectangularHardcodedModelComponent.java @@ -1,7 +1,10 @@ package net.mograsim.logic.model.model.components.atomic; +import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; import net.haspamelodica.swt.helper.gcs.GeneralGC; import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle; @@ -20,6 +23,7 @@ import net.mograsim.logic.model.snippets.symbolrenderers.CenteredTextSymbolRende import net.mograsim.logic.model.snippets.symbolrenderers.PinNamesSymbolRenderer; import net.mograsim.logic.model.snippets.symbolrenderers.PinNamesSymbolRenderer.PinNamesParams; import net.mograsim.logic.model.snippets.symbolrenderers.PinNamesSymbolRenderer.PinNamesParams.Position; +import net.mograsim.logic.model.util.ObservableAtomicReference; public abstract class SimpleRectangularHardcodedModelComponent extends ModelComponent { @@ -33,9 +37,11 @@ public abstract class SimpleRectangularHardcodedModelComponent extends ModelComp private final CenteredTextSymbolRenderer centerTextRenderer; private final PinNamesSymbolRenderer pinNamesRenderer; - private AtomicReference state; + private ObservableAtomicReference state; private Runnable recalculate; + private final Map, Consumer>>> stateObsPerHLSListenerPerStateID; + // creation and destruction public SimpleRectangularHardcodedModelComponent(LogicModelModifiable model, String id, String name, String centerText) @@ -57,31 +63,47 @@ public abstract class SimpleRectangularHardcodedModelComponent extends ModelComp pinNamesParams.pinLabelMargin = pinNamesMargin; this.pinNamesRenderer = new PinNamesSymbolRenderer(this, pinNamesParams); addPinRemovedListener(this::pinRemoved); + + this.stateObsPerHLSListenerPerStateID = new HashMap<>(); + setHighLevelStateHandler(new HighLevelStateHandler() { + @Override - public String getIDForSerializing(IdentifyParams idParams) + public Object get(String stateID) { - return null;// we don't need to serialize this; it's implicit since we are a SimpleRectangularHardcodedModelComponent + return getHighLevelState(state.get(), stateID); } @Override - public Object getParamsForSerializing(IdentifyParams idParams) + public void set(String stateID, Object newState) { - return null; + state.updateAndGet(s -> SimpleRectangularHardcodedModelComponent.this.setHighLevelState(s, stateID, newState)); + recalculate.run(); } @Override - public Object getHighLevelState(String stateID) + public void addListener(String stateID, Consumer stateChanged) { - return SimpleRectangularHardcodedModelComponent.this.getHighLevelState(state.get(), stateID); + addHighLevelStateListener(state.get(), stateID, stateChanged); } @Override - public void setHighLevelState(String stateID, Object newState) + public void removeListener(String stateID, Consumer stateChanged) { - state.updateAndGet(s -> SimpleRectangularHardcodedModelComponent.this.setHighLevelState(s, stateID, newState)); - recalculate.run(); + removeHighLevelStateListener(state.get(), stateID, stateChanged); + } + + @Override + public String getIDForSerializing(IdentifyParams idParams) + { + return null;// we don't need to serialize this; it's implicit since we are a SimpleRectangularHardcodedModelComponent + } + + @Override + public Object getParamsForSerializing(IdentifyParams idParams) + { + return null; } }); @@ -116,13 +138,36 @@ public abstract class SimpleRectangularHardcodedModelComponent extends ModelComp throw new IllegalArgumentException("No high level state with ID " + stateID); } + protected void addHighLevelStateListener(Object state, String stateID, Consumer stateChanged) + { + AtomicReference lastHLSRef = new AtomicReference<>(getHighLevelState(state, stateID)); + Consumer> refObs = r -> + { + Object newHLS = getHighLevelState(stateID); + if (!Objects.equals(lastHLSRef.getAndSet(newHLS), newHLS)) + stateChanged.accept(newHLS); + }; + stateObsPerHLSListenerPerStateID.computeIfAbsent(stateID, s -> new HashMap<>()).put(stateChanged, refObs); + this.state.addObserver(refObs); + } + + protected void removeHighLevelStateListener(Object state, String stateID, Consumer stateChanged) + { + getHighLevelState(state, stateID);// if this throws, we know there is no HLS with this name + var stateObsPerHLSListener = stateObsPerHLSListenerPerStateID.get(stateID); + if (stateObsPerHLSListener == null) + return; + Consumer> refObs = stateObsPerHLSListener.remove(stateChanged); + this.state.removeObserver(refObs); + } + // logic public abstract Object recalculate(Object lastState, Map readEnds, Map readWriteEnds); // core model binding - public void setCoreModelBindingAndResetState(AtomicReference state, Runnable recalculate) + public void setCoreModelBindingAndResetState(ObservableAtomicReference state, Runnable recalculate) { this.state = state; this.recalculate = recalculate;