]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************\r
2  * Copyright (c) 2011 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.diagram.synchronization.runtime;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.Set;\r
17 import java.util.concurrent.atomic.AtomicReference;\r
18 \r
19 import org.simantics.diagram.ui.DiagramModelHints;\r
20 import org.simantics.g2d.canvas.ICanvasContext;\r
21 import org.simantics.g2d.diagram.DiagramHints;\r
22 import org.simantics.g2d.diagram.IDiagram;\r
23 import org.simantics.g2d.diagram.handler.DataElementMap;\r
24 import org.simantics.g2d.diagram.participant.Selection;\r
25 import org.simantics.g2d.element.IElement;\r
26 import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
27 import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
28 import org.simantics.utils.datastructures.hints.IHintObservable;\r
29 import org.simantics.utils.threads.ThreadUtils;\r
30 \r
31 /**\r
32  * @author Tuukka Lehtonen\r
33  */\r
34 public class DiagramSelectionUpdater extends HintListenerAdapter {\r
35 \r
36     private static final boolean    DEBUG_SELECTION_UPDATE = false;\r
37 \r
38     private final ICanvasContext    ctx;\r
39     private final Selection         selection;\r
40     private final IDiagram          diagram;\r
41 \r
42     private int                     selectionId;\r
43     private AtomicReference<Set<?>> newSelection           = new AtomicReference<Set<?>>();\r
44 \r
45     private boolean                 oneshot                = false;\r
46     private boolean                 tracking               = false;\r
47 \r
48     public DiagramSelectionUpdater(ICanvasContext ctx) {\r
49         this.ctx = ctx;\r
50         this.selection = ctx.getAtMostOneItemOfClass(Selection.class);\r
51         if (selection == null)\r
52             throw new IllegalArgumentException("no selection participant");\r
53         this.diagram = ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);\r
54         if (diagram == null)\r
55             throw new IllegalArgumentException("no diagram");\r
56     }\r
57 \r
58     public DiagramSelectionUpdater(ICanvasContext ctx, IDiagram diagram) {\r
59         this.ctx = ctx;\r
60         this.selection = ctx.getAtMostOneItemOfClass(Selection.class);\r
61         if (selection == null)\r
62             throw new IllegalArgumentException("no selection participant");\r
63         this.diagram = diagram;\r
64         if (diagram == null)\r
65             throw new IllegalArgumentException("no diagram");\r
66     }\r
67 \r
68     protected Selection getSelectionParticipant() {\r
69         return ctx.getSingleItem(Selection.class);\r
70     }\r
71 \r
72     public DiagramSelectionUpdater setNewSelection(int selectionId, Set<?> newSelection) {\r
73         this.selectionId = selectionId;\r
74         this.newSelection.set(newSelection);\r
75         return this;\r
76     }\r
77 \r
78     public Set<?> getNewSelection() {\r
79         return newSelection.get();\r
80     }\r
81 \r
82     public DiagramSelectionUpdater setOneshot(boolean oneshot) {\r
83         this.oneshot = oneshot;\r
84         return this;\r
85     }\r
86 \r
87     public DiagramSelectionUpdater track() {\r
88         if (!tracking) {\r
89             diagram.addKeyHintListener(DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED, this);\r
90             tracking = true;\r
91         }\r
92         return this;\r
93     }\r
94 \r
95     public DiagramSelectionUpdater untrack() {\r
96         if (tracking) {\r
97             diagram.removeKeyHintListener(DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED, this);\r
98             tracking = false;\r
99         }\r
100         return this;\r
101     }\r
102 \r
103     @Override\r
104     public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
105         if (!ctx.isDisposed() && key == DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED) {\r
106             if (DEBUG_SELECTION_UPDATE)\r
107                 System.out.println(getClass().getSimpleName() + ": DIAGRAM UPDATED @" + System.currentTimeMillis() + ", selection to set: " + newSelection);\r
108             Set<?> ns = newSelection.getAndSet(null);\r
109             if (ns != null) {\r
110                 scheduleSetDiagramSelection(2, ns);\r
111             }\r
112         }\r
113 \r
114         if (oneshot) {\r
115             // Remove self from listening duties.\r
116             sender.removeHintListener(this);\r
117         }\r
118     }\r
119 \r
120     private void scheduleSetDiagramSelection(final int tries, final Set<?> data) {\r
121         ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {\r
122             @Override\r
123             public void run() {\r
124                 setDiagramSelectionToData(tries, data);\r
125             }\r
126         });\r
127     }\r
128 \r
129     private void setDiagramSelectionToData(final int tries, final Set<?> data) {\r
130         if (DEBUG_SELECTION_UPDATE)\r
131             System.out.println("setDiagramSelectionToData(" + tries + ", " + data + ")");\r
132 \r
133         DataElementMap dem = diagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class);\r
134         if (dem != null) {\r
135             final Collection<IElement> newSelection = new ArrayList<IElement>(data.size());\r
136             for (Object datum : data) {\r
137                 IElement element = dem.getElement(diagram, datum);\r
138                 if (DEBUG_SELECTION_UPDATE)\r
139                     System.out.println("  DATUM " + datum + " -> " + element);\r
140                 if (element != null) {\r
141                     newSelection.add(element);\r
142                 } else {\r
143                     if (tries > 0) {\r
144                         // Try later if there are tries left.\r
145                         ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {\r
146                             @Override\r
147                             public void run() {\r
148                                 setDiagramSelectionToData(tries - 1, data);\r
149                             }\r
150                         });\r
151                         return;\r
152                     }\r
153                     // Otherwise select whatever is found.\r
154                 }\r
155             }\r
156 \r
157             if (DEBUG_SELECTION_UPDATE)\r
158                 System.out.println("[" + tries + "] final new selection: " + newSelection);\r
159 \r
160             if (!newSelection.isEmpty()) {\r
161                 //for (IElement e : newSelection)\r
162                 //    e.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);\r
163                 selection.setSelection(selectionId, newSelection);\r
164             }\r
165         }\r
166     }\r
167 \r
168 }\r