1 /*******************************************************************************
2 * Copyright (c) 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.synchronization.runtime;
14 import java.util.ArrayList;
15 import java.util.Collection;
17 import java.util.concurrent.atomic.AtomicReference;
19 import org.simantics.diagram.ui.DiagramModelHints;
20 import org.simantics.g2d.canvas.ICanvasContext;
21 import org.simantics.g2d.diagram.DiagramHints;
22 import org.simantics.g2d.diagram.IDiagram;
23 import org.simantics.g2d.diagram.handler.DataElementMap;
24 import org.simantics.g2d.diagram.participant.Selection;
25 import org.simantics.g2d.element.IElement;
26 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
27 import org.simantics.utils.datastructures.hints.IHintContext.Key;
28 import org.simantics.utils.datastructures.hints.IHintObservable;
29 import org.simantics.utils.threads.ThreadUtils;
32 * @author Tuukka Lehtonen
34 public class DiagramSelectionUpdater extends HintListenerAdapter {
36 private static final boolean DEBUG_SELECTION_UPDATE = false;
38 private final ICanvasContext ctx;
39 private final Selection selection;
40 private final IDiagram diagram;
42 private int selectionId;
43 private AtomicReference<Set<?>> newSelection = new AtomicReference<Set<?>>();
45 private boolean oneshot = false;
46 private boolean tracking = false;
48 public DiagramSelectionUpdater(ICanvasContext ctx) {
50 this.selection = ctx.getAtMostOneItemOfClass(Selection.class);
51 if (selection == null)
52 throw new IllegalArgumentException("no selection participant");
53 this.diagram = ctx.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM);
55 throw new IllegalArgumentException("no diagram");
58 public DiagramSelectionUpdater(ICanvasContext ctx, IDiagram diagram) {
60 this.selection = ctx.getAtMostOneItemOfClass(Selection.class);
61 if (selection == null)
62 throw new IllegalArgumentException("no selection participant");
63 this.diagram = diagram;
65 throw new IllegalArgumentException("no diagram");
68 protected Selection getSelectionParticipant() {
69 return ctx.getSingleItem(Selection.class);
72 public DiagramSelectionUpdater setNewSelection(int selectionId, Set<?> newSelection) {
73 this.selectionId = selectionId;
74 this.newSelection.set(newSelection);
78 public Set<?> getNewSelection() {
79 return newSelection.get();
82 public DiagramSelectionUpdater setOneshot(boolean oneshot) {
83 this.oneshot = oneshot;
87 public DiagramSelectionUpdater track() {
89 diagram.addKeyHintListener(DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED, this);
95 public DiagramSelectionUpdater untrack() {
97 diagram.removeKeyHintListener(DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED, this);
104 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
105 if (!ctx.isDisposed() && key == DiagramModelHints.KEY_DIAGRAM_CONTENTS_UPDATED) {
106 if (DEBUG_SELECTION_UPDATE)
107 System.out.println(getClass().getSimpleName() + ": DIAGRAM UPDATED @" + System.currentTimeMillis() + ", selection to set: " + newSelection);
108 Set<?> ns = newSelection.getAndSet(null);
110 scheduleSetDiagramSelection(2, ns);
115 // Remove self from listening duties.
116 sender.removeHintListener(this);
120 private void scheduleSetDiagramSelection(final int tries, final Set<?> data) {
121 ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {
124 setDiagramSelectionToData(tries, data);
129 private void setDiagramSelectionToData(final int tries, final Set<?> data) {
130 if (DEBUG_SELECTION_UPDATE)
131 System.out.println("setDiagramSelectionToData(" + tries + ", " + data + ")");
133 DataElementMap dem = diagram.getDiagramClass().getAtMostOneItemOfClass(DataElementMap.class);
135 final Collection<IElement> newSelection = new ArrayList<IElement>(data.size());
136 for (Object datum : data) {
137 IElement element = dem.getElement(diagram, datum);
138 if (DEBUG_SELECTION_UPDATE)
139 System.out.println(" DATUM " + datum + " -> " + element);
140 if (element != null) {
141 newSelection.add(element);
144 // Try later if there are tries left.
145 ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {
148 setDiagramSelectionToData(tries - 1, data);
153 // Otherwise select whatever is found.
157 if (DEBUG_SELECTION_UPDATE)
158 System.out.println("[" + tries + "] final new selection: " + newSelection);
160 if (!newSelection.isEmpty()) {
161 //for (IElement e : newSelection)
162 // e.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
163 selection.setSelection(selectionId, newSelection);