]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.maps/src/org/simantics/maps/eclipse/MapPainter.java
Optimization of district scene graph node rendering
[simantics/district.git] / org.simantics.district.maps / src / org / simantics / maps / eclipse / MapPainter.java
index 3c4a9944fd628a95d979722b7fd2ee62267b9966..5e989546723e2966866dcb5ea78d0683cc5d8efd 100644 (file)
  *******************************************************************************/
 package org.simantics.maps.eclipse;
 
+import java.awt.Color;
+import java.awt.geom.AffineTransform;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
 import org.simantics.g2d.canvas.Hints;
 import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant;
 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
+import org.simantics.g2d.participant.MouseUtil;
+import org.simantics.maps.sg.MapAttributionNode;
+import org.simantics.maps.sg.MapInfoNode;
+import org.simantics.maps.sg.MapLocationInfoNode;
 import org.simantics.maps.sg.MapNode;
+import org.simantics.maps.sg.MapScaleNode;
+import org.simantics.maps.sg.commands.MapCommands;
 import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.g2d.events.Event;
 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
 import org.simantics.scenegraph.g2d.events.command.Commands;
 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
-import org.simantics.utils.datastructures.hints.IHintListener;
-import org.simantics.utils.datastructures.hints.IHintObservable;
 import org.simantics.utils.datastructures.hints.IHintContext.Key;
 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
+import org.simantics.utils.datastructures.hints.IHintListener;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.threads.AWTThread;
+import org.simantics.utils.threads.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * MapPainter is an ICanvasContext participant that uses the scene graph
@@ -37,11 +54,15 @@ import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
  */
 public class MapPainter extends AbstractCanvasParticipant {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(MapPainter.class);
+
     /**
      * Grid enabled status. Default value is True
      */
     public static final Key KEY_MAP_ENABLED  = new KeyOf(Boolean.class);
 
+    public static final Key KEY_MAP_BACKGROUND_COLOR  = new KeyOf(Object.class);
+
     public static final double ZOOM_IN_LIMIT = 10000000.0;
 
     public static final double ZOOM_OUT_LIMIT = 10.0;
@@ -56,23 +77,30 @@ public class MapPainter extends AbstractCanvasParticipant {
         }
     };
 
-    protected MapNode node = null;
+    private MapNode mapNode;
+    private MapLocationInfoNode locationInfoNode;
+    private MapScaleNode scaleNode;
+    private MapInfoNode attributionNode;
+
+    private AffineTransform transform;
 
-    private int scale;
+    private ScheduledFuture<?> schedule;
 
-    public MapPainter(int scale) {
-        this.scale = scale;
+    public MapPainter(AffineTransform transform) {
+        this.transform = transform;
     }
 
     @Override
     public void addedToContext(ICanvasContext ctx) {
         super.addedToContext(ctx);
         getHintStack().addKeyHintListener(getThread(), KEY_MAP_ENABLED, mapListener);
+        getHintStack().addKeyHintListener(getThread(), KEY_MAP_BACKGROUND_COLOR, mapListener);
     }
 
     @Override
     public void removedFromContext(ICanvasContext ctx) {
         getHintStack().removeKeyHintListener(getThread(), KEY_MAP_ENABLED, mapListener);
+        getHintStack().removeKeyHintListener(getThread(), KEY_MAP_BACKGROUND_COLOR, mapListener);
         super.removedFromContext(ctx);
     }
 
@@ -83,6 +111,12 @@ public class MapPainter extends AbstractCanvasParticipant {
             updateNode();
             setDirty();
             return true;
+        } else if (e.command.equals( MapCommands.MAP_BACKGROUND_COLOR_CHANGE )) {
+            ICanvasContext context = (ICanvasContext) e.getContext();
+            Color s = context.getHintStack().getHint(MapCommands.KEY_MAP_BACKGROUND_COLOR);
+            setBackgroundColor(s);
+            setDirty();
+            return true;
         } else if (e.command.equals( Commands.MAP_DISABLE )) {
             setEnabled(false);
             updateNode();
@@ -93,25 +127,71 @@ public class MapPainter extends AbstractCanvasParticipant {
             updateNode();
             setDirty();
             return true;
+        } else if (e.command.equals( Commands.ENABLE_PAINTING )) {
+            enablePainting();
+            updateNode();
+            setDirty();
+            return true;
+        }
+        return false;
+    }
+
+    @EventHandler(priority = 31)
+    public boolean handleEvent(Event e) {
+        if (e instanceof MouseMovedEvent) {
+            // here we should somehow re-render ?
+            if (locationInfoNode != null && locationInfoNode.isEnabled()) {
+                if (schedule == null || schedule.isDone()) {
+                    LOGGER.debug("current setDirty time" + System.currentTimeMillis());
+                    schedule = ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> {
+                        AWTThread.getThreadAccess().asyncExec(this::setDirty);
+                    }, 100, TimeUnit.MILLISECONDS);
+                } else {
+                    //LOGGER.debug("ingoring setDirty time" + System.currentTimeMillis());
+                }
+            }
         }
         return false;
     }
 
     @SGInit
     public void initSG(G2DParentNode parent) {
-        node = parent.addNode("map", MapNode.class);
-        node.setScale(scale);
-        node.setEnabled(true);
-        node.setZIndex(Integer.MIN_VALUE + 999); // Just under the grid
+        // Just under the grid
+        mapNode = parent.addNode("map", MapNode.class);
+        mapNode.setTransform(transform);
+        mapNode.setEnabled(true);
+        mapNode.setZIndex(Integer.MIN_VALUE + 999);
+
+        // On top of pretty much everything
+        attributionNode = parent.addNode("mapAttribution", MapAttributionNode.class);
+        attributionNode.setTransform(transform);
+        attributionNode.setZIndex(Integer.MAX_VALUE - 999);
+        attributionNode.setEnabled(true);
+
+        scaleNode = parent.addNode("mapScale", MapScaleNode.class);
+        scaleNode.setTransform(transform);
+        scaleNode.setZIndex(Integer.MAX_VALUE - 998);
+        scaleNode.setEnabled(true);
+
+        locationInfoNode = parent.addNode("mapLocationInfo", MapLocationInfoNode.class);
+        locationInfoNode.setTransform(transform);
+        locationInfoNode.setZIndex(Integer.MAX_VALUE - 997);
+        locationInfoNode.setEnabled(true);
+        locationInfoNode.setMouseUtil(getContext().getAtMostOneItemOfClass(MouseUtil.class));
     }
 
     @SGCleanup
     public void cleanupSG() {
-        node.remove();
+        mapNode.remove();
+        attributionNode.remove();
+        scaleNode.remove();
+        locationInfoNode.remove();
     }
 
     protected void updateNode() {
-        node.setEnabled(isPaintingEnabled());
+        mapNode.setEnabled(isPaintingEnabled());
+        mapNode.setEnabled(isMapEnabled());
+        mapNode.setBackgroundColor(getBackgroundColor());
     }
 
     boolean isPaintingEnabled() {
@@ -129,4 +209,15 @@ public class MapPainter extends AbstractCanvasParticipant {
         setHint(KEY_MAP_ENABLED, enabled);
     }
 
+    private void enablePainting() {
+        setHint(Hints.KEY_DISABLE_PAINTING, false);
+    }
+    
+    private void setBackgroundColor(Color backgroundColor) {
+        setHint(KEY_MAP_BACKGROUND_COLOR, backgroundColor);
+    }
+    
+    private Color getBackgroundColor() {
+        return getHint(KEY_MAP_BACKGROUND_COLOR);
+    }
 }