--- /dev/null
+package org.simantics.diagram.profile;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.concurrent.TimeUnit;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+\r
+import org.simantics.diagram.elements.DiagramNodeUtil;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.scenegraph.INode;\r
+import org.simantics.scenegraph.g2d.G2DNode;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+\r
+class Updater implements Runnable {\r
+\r
+ private static Updater INSTANCE;\r
+ \r
+ Map<INode, ICanvasContext> requesters = new HashMap<INode, ICanvasContext>();\r
+ \r
+ AtomicBoolean state = new AtomicBoolean(false);\r
+ \r
+ private static long time = System.nanoTime();\r
+ \r
+ private Updater() {\r
+ }\r
+ \r
+ @Override\r
+ public void run() {\r
+\r
+ // Stop this if nothing is to be done, need synchonization since this is not AWT\r
+ synchronized(requesters) {\r
+ if(requesters.isEmpty()) {\r
+ state.set(false);\r
+ throw new RuntimeException();\r
+ }\r
+ }\r
+ \r
+ // TODO: in unit tests this should not be AWT\r
+ ThreadUtils.AWT_EDT.execute(new Runnable() {\r
+\r
+ @Override\r
+ public void run() {\r
+ \r
+ time = System.nanoTime();\r
+ \r
+ synchronized(requesters) {\r
+ HashSet<ICanvasContext> ctxSet = new HashSet<ICanvasContext>();\r
+ for(ICanvasContext ctx : requesters.values()) {\r
+ if(ctx != null) {\r
+ if(ctxSet.add(ctx)) ctx.getContentContext().setDirty();\r
+ }\r
+ }\r
+ }\r
+ \r
+ }\r
+ \r
+ });\r
+ \r
+ }\r
+ \r
+ public void register(INode node) {\r
+ // We use ths size of this map to determine whether updates are needed, this is done in AWT thread\r
+ synchronized(requesters) {\r
+ if(requesters.size() == 0) {\r
+ if(state.compareAndSet(false, true)) {\r
+ ThreadUtils.getNonBlockingWorkExecutor().scheduleAtFixedRate(this, 0, 500, TimeUnit.MILLISECONDS);\r
+ }\r
+ }\r
+ ICanvasContext context = DiagramNodeUtil.getPossibleCanvasContext((G2DNode)node);\r
+ requesters.put(node, context);\r
+ }\r
+ }\r
+ \r
+ public void unregister(INode node) {\r
+ synchronized(requesters) {\r
+ requesters.remove(node);\r
+ }\r
+ }\r
+ \r
+ public long getTime() {\r
+ return time;\r
+ }\r
+ \r
+ public static Updater getInstance() {\r
+ if(INSTANCE == null) {\r
+ INSTANCE = new Updater();\r
+ }\r
+ return INSTANCE;\r
+ }\r
+ \r
+}
\ No newline at end of file