import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import org.eclipse.swt.SWT;
*/
public class LogicUICanvas extends ZoomableCanvas
{
- private static final boolean OPEN_DEBUG_SETHIGHLEVELSTATE_SHELL = false;
+ private static final boolean OPEN_DEBUG_SETHIGHLEVELSTATE_SHELL = true;
private final LogicModel model;
Combo componentSelector = new Combo(debugShell, SWT.DROP_DOWN | SWT.READ_ONLY);
componentSelector.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
List<ModelComponent> componentsByItemIndex = new ArrayList<>();
- Consumer<? super ModelComponent> compsChanged = c -> recalculateComponentSelector(componentsByItemIndex, componentSelector, model);
- model.addComponentAddedListener(compsChanged);
- model.addComponentRemovedListener(compsChanged);
- debugShell.addListener(SWT.Dispose, e ->
+ List<LogicModel> models = new ArrayList<>();
+ AtomicBoolean recalculateQueued = new AtomicBoolean();
+ AtomicReference<Consumer<? super ModelComponent>> compAdded = new AtomicReference<>();
+ AtomicReference<Consumer<? super ModelComponent>> compRemoved = new AtomicReference<>();
+ compAdded.set(c -> compsChanged(compAdded.get(), compRemoved.get(), c, models, componentsByItemIndex, componentSelector, model,
+ recalculateQueued, true));
+ compRemoved.set(c -> compsChanged(compAdded.get(), compRemoved.get(), c, models, componentsByItemIndex, componentSelector, model,
+ recalculateQueued, false));
+ iterateModelTree(compAdded.get(), compRemoved.get(), model, models, true);
+ debugShell.addListener(SWT.Dispose, e -> models.forEach(m ->
{
- model.removeComponentAddedListener(compsChanged);
- model.removeComponentRemovedListener(compsChanged);
- });
- recalculateComponentSelector(componentsByItemIndex, componentSelector, model);
+ m.removeComponentAddedListener(compAdded.get());
+ m.removeComponentRemovedListener(compRemoved.get());
+ }));
+ queueRecalculateComponentSelector(recalculateQueued, componentsByItemIndex, componentSelector, model);
new Label(debugShell, SWT.NONE).setText("Target state ID: ");
Text stateIDText = new Text(debugShell, SWT.SINGLE | SWT.LEAD | SWT.BORDER);
stateIDText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
debugShell.open();
}
- private void recalculateComponentSelector(List<ModelComponent> componentsByItemIndex, Combo componentSelector, LogicModel model)
+ private void compsChanged(Consumer<? super ModelComponent> compAdded, Consumer<? super ModelComponent> compRemoved, ModelComponent c,
+ List<LogicModel> models, List<ModelComponent> componentsByItemIndex, Combo componentSelector, LogicModel model,
+ AtomicBoolean recalculateQueued, boolean add)
+ {
+ iterateSubmodelTree(compAdded, compRemoved, c, models, add);
+ queueRecalculateComponentSelector(recalculateQueued, componentsByItemIndex, componentSelector, model);
+ }
+
+ private void iterateSubmodelTree(Consumer<? super ModelComponent> compAdded, Consumer<? super ModelComponent> compRemoved,
+ ModelComponent c, List<LogicModel> models, boolean add)
+ {
+ if (c instanceof SubmodelComponent)
+ iterateModelTree(compAdded, compRemoved, ((SubmodelComponent) c).submodel, models, add);
+ }
+
+ private void iterateModelTree(Consumer<? super ModelComponent> compAdded, Consumer<? super ModelComponent> compRemoved,
+ LogicModel model, List<LogicModel> models, boolean add)
+ {
+ if (add ^ models.contains(model))
+ {
+ if (add)
+ {
+ models.add(model);
+ model.addComponentAddedListener(compAdded);
+ model.addComponentRemovedListener(compRemoved);
+ } else
+ {
+ models.remove(model);
+ model.removeComponentAddedListener(compAdded);
+ model.removeComponentRemovedListener(compRemoved);
+ }
+ for (ModelComponent c : model.getComponentsByName().values())
+ iterateSubmodelTree(compAdded, compRemoved, c, models, add);
+ }
+ }
+
+ private void queueRecalculateComponentSelector(AtomicBoolean recalculateQueued, List<ModelComponent> componentsByItemIndex,
+ Combo componentSelector, LogicModel model)
+ {
+ if (recalculateQueued.compareAndSet(false, true))
+ getDisplay().asyncExec(() -> recalculateComponentSelector(recalculateQueued, componentsByItemIndex, componentSelector, model));
+ }
+
+ private void recalculateComponentSelector(AtomicBoolean recalculateQueued, List<ModelComponent> componentsByItemIndex,
+ Combo componentSelector, LogicModel model)
{
+ recalculateQueued.set(false);
componentsByItemIndex.clear();
componentSelector.setItems();
addComponentSelectorItems(componentsByItemIndex, "", componentSelector, model);
}
- private void addComponentSelectorItems(List<ModelComponent> componentsByItemIndex, String base, Combo componentSelector, LogicModel model)
+ private void addComponentSelectorItems(List<ModelComponent> componentsByItemIndex, String base, Combo componentSelector,
+ LogicModel model)
{
model.getComponentsByName().values().stream().sorted((c1, c2) -> c1.name.compareTo(c2.name)).forEach(c ->
{