1 package org.simantics.diagram.profile;
3 import java.util.HashMap;
4 import java.util.HashSet;
6 import java.util.concurrent.TimeUnit;
7 import java.util.concurrent.atomic.AtomicBoolean;
9 import org.simantics.diagram.elements.DiagramNodeUtil;
10 import org.simantics.g2d.canvas.ICanvasContext;
11 import org.simantics.scenegraph.INode;
12 import org.simantics.scenegraph.g2d.G2DNode;
13 import org.simantics.utils.threads.ThreadUtils;
15 class Updater implements Runnable {
17 private static Updater INSTANCE;
19 Map<INode, ICanvasContext> requesters = new HashMap<INode, ICanvasContext>();
21 AtomicBoolean state = new AtomicBoolean(false);
23 private static long time = System.nanoTime();
31 // Stop this if nothing is to be done, need synchonization since this is not AWT
32 synchronized(requesters) {
33 if(requesters.isEmpty()) {
35 throw new RuntimeException();
39 // TODO: in unit tests this should not be AWT
40 ThreadUtils.AWT_EDT.execute(new Runnable() {
45 time = System.nanoTime();
47 synchronized(requesters) {
48 HashSet<ICanvasContext> ctxSet = new HashSet<ICanvasContext>();
49 for(ICanvasContext ctx : requesters.values()) {
51 if(ctxSet.add(ctx)) ctx.getContentContext().setDirty();
62 public void register(INode node) {
63 // We use ths size of this map to determine whether updates are needed, this is done in AWT thread
64 synchronized(requesters) {
65 if(requesters.size() == 0) {
66 if(state.compareAndSet(false, true)) {
67 ThreadUtils.getNonBlockingWorkExecutor().scheduleAtFixedRate(this, 0, 500, TimeUnit.MILLISECONDS);
70 ICanvasContext context = DiagramNodeUtil.getPossibleCanvasContext((G2DNode)node);
71 requesters.put(node, context);
75 public void unregister(INode node) {
76 synchronized(requesters) {
77 requesters.remove(node);
81 public long getTime() {
85 public static Updater getInstance() {
86 if(INSTANCE == null) {
87 INSTANCE = new Updater();