]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictPanZoomRotateHandler.java
Fix NPEs in tech type command handlers' canExecute()
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / DistrictPanZoomRotateHandler.java
index 1a4f83d8aaea80ddee799f399d4a0f68084bbbe3..ac0d22e3df34bb79b8ec17f07d44f25fb86d13ae 100644 (file)
 package org.simantics.district.network.ui;
 
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Reference;
+import org.simantics.g2d.diagram.DiagramHints;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.participant.Selection;
+import org.simantics.g2d.element.ElementUtils;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.participant.CanvasBoundsParticipant;
 import org.simantics.g2d.participant.PanZoomRotateHandler;
+import org.simantics.maps.MapScalingTransform;
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
+import org.simantics.scenegraph.g2d.events.command.Command;
+import org.simantics.scenegraph.g2d.events.command.CommandEvent;
+import org.simantics.scenegraph.g2d.events.command.Commands;
 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
 
 public class DistrictPanZoomRotateHandler extends PanZoomRotateHandler {
 
+    public static final int DISTRICT_TRANSLATE_AMOUNT = 2;
+
+    @Dependency DistrictTransformUtil util;
+    @Reference  Selection selection;
+
     public DistrictPanZoomRotateHandler() {
     }
+    
+    @Override
+    public void addedToContext(ICanvasContext ctx) {
+        super.addedToContext(ctx);
+        setHint(KEY_TRANSLATE_AMOUNT, DISTRICT_TRANSLATE_AMOUNT);
+    }
 
     @Override
     protected Class<? extends NavigationNode> getNavigationNodeClass() {
         return DistrictNavigationNode.class;
     }
 
+    @Override
+    public double getTranslateAmount() {
+        return 15 * super.getTranslateAmount();
+    }
+    
+    @Override
+    public double limitScaleFactor(double scaleFactor) {
+        return scaleFactor;
+    }
+    
+    @Override
+    @EventHandler(priority = 1)
+    public boolean handleEvent(CommandEvent e) {
+        super.update();
+        Command c = e.command;
+        boolean zoomDisabled = Boolean.TRUE.equals(getHint(KEY_DISABLE_ZOOM)) ? true : false;
+        // custom handling of zoom to fit & selection
+        if (Commands.ZOOM_TO_FIT.equals(c) && !zoomDisabled) {
+            boolean result = zoomToFit();
+            if (!result)
+                result = zoomToPage();
+            return result;
+        }
+        if (Commands.ZOOM_TO_PAGE.equals(c) && !zoomDisabled) {
+            return zoomToPage();
+        }
+        if (Commands.ZOOM_TO_SELECTION.equals(c) && !zoomDisabled) {
+            return zoomToSelection();
+        }
+        return super.handleEvent(e);
+    }
+
+    private boolean zoomToFit() {
+        CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
+        if (boundsParticipant == null)
+            return false;
+
+        final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
+        if (controlBounds == null || controlBounds.isEmpty())
+            return false;
+
+        IDiagram d = getHint(DiagramHints.KEY_DIAGRAM);
+        if (d == null)
+            return false;
+
+        Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(getMapElements(d.getElements()));
+        if (diagramRect == null)
+            return false;
+        if (diagramRect.isEmpty())
+            return false;
+
+        org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
+        
+        // System.out.println("zoomToFit(" + controlArea + ", " + diagramRect + ")");
+        util.fitArea(controlBounds, diagramRect, null);
+
+        return true;
+    }
+
+    protected static List<IElement> getMapElements(Collection<IElement> elements) {
+        List<IElement> justMapElements = elements.stream()
+                .filter(e -> "DistrictNetworkEdgeElement".equals(e.getElementClass().getId())
+                          || "DistrictNetworkVertexElement".equals(e.getElementClass().getId()))
+                .collect(Collectors.toList());
+        return justMapElements;
+    }
+
+    private boolean zoomToPage() {
+        util.setTransform(new AffineTransform(2,0,0,2,270,270));
+        return true;
+    }
+    
+    private boolean zoomToSelection() {
+        CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
+        if (boundsParticipant == null)
+            return false;
+
+        final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
+        if (controlBounds == null || controlBounds.isEmpty())
+            return false;
+        
+        Set<IElement> selections = selection.getAllSelections();
+        if (selections == null || selections.isEmpty()) {
+            // no can do, 
+            return zoomToPage();
+        }
+        Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(getMapElements(selections));
+        
+        // Make sure that even empty bounds can be zoomed into.
+        org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
+        
+        util.fitArea(controlBounds, diagramRect, null);
+        return true;
+    }
+
     public static class DistrictNavigationNode extends NavigationNode {
 
         private static final long serialVersionUID = 5452897272925816875L;
 
+        public DistrictNavigationNode() {
+            setAdaptViewportToResizedControl(false);
+        }
+
         @Override
         public Double getZoomInLimit() {
             return super.getZoomInLimit();
@@ -28,22 +159,47 @@ public class DistrictPanZoomRotateHandler extends PanZoomRotateHandler {
             return super.getZoomOutLimit();
         }
 
+        @Override
+        public void setAdaptViewportToResizedControl(Boolean adapt) {
+            super.setAdaptViewportToResizedControl(false);
+            // no op
+        }
+
+        @Override
+        public boolean getAdaptViewportToResizedControl() {
+            return false;
+        }
+
         @Override
         public boolean mouseWheelMoved(MouseWheelMovedEvent me) {
             if (navigationEnabled && zoomEnabled) {
-                double scroll = Math.min(0.9, -me.wheelRotation / 20.0);
-                double z = 1 - scroll;
-                double dx = (me.controlPosition.getX() - transform.getTranslateX()) / transform.getScaleX();
-                double dy = (me.controlPosition.getY() - transform.getTranslateY()) / transform.getScaleY();
-                dx = dx * (1 - z);
-                dy = dy * (1 - z);
-                double limitedScale = limitScaleFactor(z);
-                if (limitedScale != 1.0) {
-                    translate(dx, dy);
-                    scale(z, z);
-                    transformChanged();
-                    dropQuality();
-                    repaint();
+                // check if min/max zoom already
+                AffineTransform transform = getTransform();
+                int zoomLevel = MapScalingTransform.zoomLevel(transform);
+                
+                if (0 < zoomLevel && zoomLevel < 20 || (zoomLevel == 0 && me.wheelRotation > 0) || (zoomLevel == 20 && me.wheelRotation < 0)) {
+                    double z;
+                    if (me.wheelRotation > 0) {
+                        z = DISTRICT_TRANSLATE_AMOUNT;
+                    } else {
+                        z = 1.0d / DISTRICT_TRANSLATE_AMOUNT;
+                    }
+                    //double scroll = Math.min(0.9, -me.wheelRotation / 20.0);
+                    //double z = 1 - scroll;
+                    double dx = (me.controlPosition.getX() - transform.getTranslateX()) / transform.getScaleX();
+                    double dy = (me.controlPosition.getY() - transform.getTranslateY()) / transform.getScaleY();
+                    dx = dx * (1 - z);
+                    dy = dy * (1 - z);
+//                    double limitedScale = limitScaleFactor(z);
+//                    if (limitedScale != 1.0) {
+                        translate(dx, dy);
+                        scale(z, z);
+                        transformChanged();
+                        dropQuality();
+                        repaint();
+//                    }
+                } else {
+                    // max zoom level reached
                 }
             }
             return false;