]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/runtime/DiagramSelectionUpdater.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / synchronization / runtime / DiagramSelectionUpdater.java
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/runtime/DiagramSelectionUpdater.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/runtime/DiagramSelectionUpdater.java
new file mode 100644 (file)
index 0000000..e6e0d11
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************\r
+ * Copyright (c) 2011 Association for Decentralized Information Management in\r
+ * Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.diagram.synchronization.runtime;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Set;\r
+import java.util.concurrent.atomic.AtomicReference;\r
+\r
+import org.simantics.diagram.ui.DiagramModelHints;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.g2d.diagram.IDiagram;\r
+import org.simantics.g2d.diagram.handler.DataElementMap;\r
+import org.simantics.g2d.diagram.participant.Selection;\r
+import org.simantics.g2d.element.IElement;\r
+import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
+import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
+import org.simantics.utils.datastructures.hints.IHintObservable;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DiagramSelectionUpdater extends HintListenerAdapter {\r
+\r
+    private static final boolean    DEBUG_SELECTION_UPDATE = false;\r
+\r
+    private final ICanvasContext    ctx;\r
+    private final Selection         selection;\r
+    private final IDiagram          diagram;\r
+\r
+    private int                     selectionId;\r
+    private AtomicReference<Set<?>> newSelection           = new AtomicReference<Set<?>>();\r
+\r
+    private boolean                 oneshot                = false;\r
+    private boolean                 tracking               = false;\r
+\r
+    public DiagramSelectionUpdater(ICanvasContext ctx) {\r
+        this.ctx = ctx;\r
+        this.selection = ctx.getAtMostOneItemOfClass(Selection.class);\r
+        if (selection == null)\r
+            throw new IllegalArgumentException("no selection participant");\r
+        this.diagram = ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);\r
+        if (diagram == null)\r
+            throw new IllegalArgumentException("no diagram");\r
+    }\r
+\r
+    public DiagramSelectionUpdater(ICanvasContext ctx, IDiagram diagram) {\r
+        this.ctx = ctx;\r
+        this.selection = ctx.getAtMostOneItemOfClass(Selection.class);\r
+        if (selection == null)\r
+            throw new IllegalArgumentException("no selection participant");\r
+        this.diagram = diagram;\r
+        if (diagram == null)\r
+            throw new IllegalArgumentException("no diagram");\r
+    }\r
+\r
+    protected Selection getSelectionParticipant() {\r
+        return ctx.getSingleItem(Selection.class);\r
+    }\r
+\r
+    public DiagramSelectionUpdater setNewSelection(int selectionId, Set<?> newSelection) {\r
+        this.selectionId = selectionId;\r
+        this.newSelection.set(newSelection);\r
+        return this;\r
+    }\r
+\r
+    public Set<?> getNewSelection() {\r
+        return newSelection.get();\r
+    }\r
+\r
+    public DiagramSelectionUpdater setOneshot(boolean oneshot) {\r
+        this.oneshot = oneshot;\r
+        return this;\r
+    }\r
+\r
+    public DiagramSelectionUpdater track() {\r
+        if (!tracking) {\r
+            diagram.addKeyHintListener(DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED, this);\r
+            tracking = true;\r
+        }\r
+        return this;\r
+    }\r
+\r
+    public DiagramSelectionUpdater untrack() {\r
+        if (tracking) {\r
+            diagram.removeKeyHintListener(DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED, this);\r
+            tracking = false;\r
+        }\r
+        return this;\r
+    }\r
+\r
+    @Override\r
+    public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
+        if (!ctx.isDisposed() && key == DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED) {\r
+            if (DEBUG_SELECTION_UPDATE)\r
+                System.out.println(getClass().getSimpleName() + ": DIAGRAM UPDATED @" + System.currentTimeMillis() + ", selection to set: " + newSelection);\r
+            Set<?> ns = newSelection.getAndSet(null);\r
+            if (ns != null) {\r
+                scheduleSetDiagramSelection(2, ns);\r
+            }\r
+        }\r
+\r
+        if (oneshot) {\r
+            // Remove self from listening duties.\r
+            sender.removeHintListener(this);\r
+        }\r
+    }\r
+\r
+    private void scheduleSetDiagramSelection(final int tries, final Set<?> data) {\r
+        ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {\r
+            @Override\r
+            public void run() {\r
+                setDiagramSelectionToData(tries, data);\r
+            }\r
+        });\r
+    }\r
+\r
+    private void setDiagramSelectionToData(final int tries, final Set<?> data) {\r
+        if (DEBUG_SELECTION_UPDATE)\r
+            System.out.println("setDiagramSelectionToData(" + tries + ", " + data + ")");\r
+\r
+        DataElementMap dem = diagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class);\r
+        if (dem != null) {\r
+            final Collection<IElement> newSelection = new ArrayList<IElement>(data.size());\r
+            for (Object datum : data) {\r
+                IElement element = dem.getElement(diagram, datum);\r
+                if (DEBUG_SELECTION_UPDATE)\r
+                    System.out.println("  DATUM " + datum + " -> " + element);\r
+                if (element != null) {\r
+                    newSelection.add(element);\r
+                } else {\r
+                    if (tries > 0) {\r
+                        // Try later if there are tries left.\r
+                        ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {\r
+                            @Override\r
+                            public void run() {\r
+                                setDiagramSelectionToData(tries - 1, data);\r
+                            }\r
+                        });\r
+                        return;\r
+                    }\r
+                    // Otherwise select whatever is found.\r
+                }\r
+            }\r
+\r
+            if (DEBUG_SELECTION_UPDATE)\r
+                System.out.println("[" + tries + "] final new selection: " + newSelection);\r
+\r
+            if (!newSelection.isEmpty()) {\r
+                //for (IElement e : newSelection)\r
+                //    e.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);\r
+                selection.setSelection(selectionId, newSelection);\r
+            }\r
+        }\r
+    }\r
+\r
+}\r