]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictPanZoomRotateHandler.java
Fix to zoom level handling in Map UI.
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / DistrictPanZoomRotateHandler.java
1 package org.simantics.district.network.ui;
2
3 import java.awt.geom.AffineTransform;
4 import java.awt.geom.Rectangle2D;
5 import java.util.Collection;
6 import java.util.List;
7 import java.util.Set;
8 import java.util.stream.Collectors;
9
10 import org.simantics.g2d.canvas.ICanvasContext;
11 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
12 import org.simantics.g2d.canvas.impl.DependencyReflection.Reference;
13 import org.simantics.g2d.diagram.DiagramHints;
14 import org.simantics.g2d.diagram.IDiagram;
15 import org.simantics.g2d.diagram.participant.Selection;
16 import org.simantics.g2d.element.ElementUtils;
17 import org.simantics.g2d.element.IElement;
18 import org.simantics.g2d.participant.CanvasBoundsParticipant;
19 import org.simantics.g2d.participant.PanZoomRotateHandler;
20 import org.simantics.maps.MapScalingTransform;
21 import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
22 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
23 import org.simantics.scenegraph.g2d.events.command.Command;
24 import org.simantics.scenegraph.g2d.events.command.CommandEvent;
25 import org.simantics.scenegraph.g2d.events.command.Commands;
26 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
27
28 public class DistrictPanZoomRotateHandler extends PanZoomRotateHandler {
29
30     public static final int DISTRICT_TRANSLATE_AMOUNT = 2;
31
32     @Dependency DistrictTransformUtil util;
33     @Reference  Selection selection;
34
35     public DistrictPanZoomRotateHandler() {
36     }
37     
38     @Override
39     public void addedToContext(ICanvasContext ctx) {
40         super.addedToContext(ctx);
41         setHint(KEY_TRANSLATE_AMOUNT, DISTRICT_TRANSLATE_AMOUNT);
42     }
43
44     @Override
45     protected Class<? extends NavigationNode> getNavigationNodeClass() {
46         return DistrictNavigationNode.class;
47     }
48
49     @Override
50     public double getTranslateAmount() {
51         return 15 * super.getTranslateAmount();
52     }
53     
54     @Override
55     public double limitScaleFactor(double scaleFactor) {
56         return scaleFactor;
57     }
58     
59     @Override
60     @EventHandler(priority = 1)
61     public boolean handleEvent(CommandEvent e) {
62         super.update();
63         Command c = e.command;
64         boolean zoomDisabled = Boolean.TRUE.equals(getHint(KEY_DISABLE_ZOOM)) ? true : false;
65         // custom handling of zoom to fit & selection
66         if (Commands.ZOOM_TO_FIT.equals(c) && !zoomDisabled) {
67             boolean result = zoomToFit();
68             if (!result)
69                 result = zoomToPage();
70             return result;
71         }
72         if (Commands.ZOOM_TO_PAGE.equals(c) && !zoomDisabled) {
73             return zoomToPage();
74         }
75         if (Commands.ZOOM_TO_SELECTION.equals(c) && !zoomDisabled) {
76             return zoomToSelection();
77         }
78         return super.handleEvent(e);
79     }
80
81     private boolean zoomToFit() {
82         CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
83         if (boundsParticipant == null)
84             return false;
85
86         final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
87         if (controlBounds == null || controlBounds.isEmpty())
88             return false;
89
90         IDiagram d = getHint(DiagramHints.KEY_DIAGRAM);
91         if (d == null)
92             return false;
93
94         Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(getMapElements(d.getElements()));
95         if (diagramRect == null)
96             return false;
97         if (diagramRect.isEmpty())
98             return false;
99
100         org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
101         
102         // System.out.println("zoomToFit(" + controlArea + ", " + diagramRect + ")");
103         util.fitArea(controlBounds, diagramRect, null);
104
105         return true;
106     }
107
108     protected static List<IElement> getMapElements(Collection<IElement> elements) {
109         List<IElement> justMapElements = elements.stream()
110                 .filter(e -> "DistrictNetworkEdgeElement".equals(e.getElementClass().getId())
111                           || "DistrictNetworkVertexElement".equals(e.getElementClass().getId()))
112                 .collect(Collectors.toList());
113         return justMapElements;
114     }
115
116     private boolean zoomToPage() {
117         int currentZoomLevel = MapScalingTransform.zoomLevel(util.getTransform());
118         
119         util.setTransform(new AffineTransform(2,0,0,2,270,270));
120         return true;
121     }
122     
123     private boolean zoomToSelection() {
124         CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
125         if (boundsParticipant == null)
126             return false;
127
128         final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
129         if (controlBounds == null || controlBounds.isEmpty())
130             return false;
131         
132         Set<IElement> selections = selection.getAllSelections();
133         if (selections == null || selections.isEmpty()) {
134             // no can do, 
135             return zoomToPage();
136         }
137         Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(getMapElements(selections));
138         
139         // Make sure that even empty bounds can be zoomed into.
140         org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
141         
142         util.fitArea(controlBounds, diagramRect, null);
143         return true;
144     }
145
146     public static class DistrictNavigationNode extends NavigationNode {
147
148         private static final long serialVersionUID = 5452897272925816875L;
149
150         public DistrictNavigationNode() {
151             setAdaptViewportToResizedControl(false);
152         }
153
154         @Override
155         public Double getZoomInLimit() {
156             return super.getZoomInLimit();
157         }
158
159         @Override
160         public Double getZoomOutLimit() {
161             return super.getZoomOutLimit();
162         }
163
164         @Override
165         public void setAdaptViewportToResizedControl(Boolean adapt) {
166             super.setAdaptViewportToResizedControl(false);
167             // no op
168         }
169
170         @Override
171         public boolean getAdaptViewportToResizedControl() {
172             return false;
173         }
174
175         @Override
176         public boolean mouseWheelMoved(MouseWheelMovedEvent me) {
177             if (navigationEnabled && zoomEnabled) {
178                 // check if min/max zoom already
179                 AffineTransform transform = getTransform();
180                 int zoomLevel = MapScalingTransform.zoomLevel(transform);
181                 
182                 if (0 < zoomLevel && zoomLevel < 20 || (zoomLevel == 0 && me.wheelRotation > 0) || (zoomLevel == 20 && me.wheelRotation < 0)) {
183                     double z;
184                     if (me.wheelRotation > 0) {
185                         z = DISTRICT_TRANSLATE_AMOUNT;
186                     } else {
187                         z = 1.0d / DISTRICT_TRANSLATE_AMOUNT;
188                     }
189                     //double scroll = Math.min(0.9, -me.wheelRotation / 20.0);
190                     //double z = 1 - scroll;
191                     double dx = (me.controlPosition.getX() - transform.getTranslateX()) / transform.getScaleX();
192                     double dy = (me.controlPosition.getY() - transform.getTranslateY()) / transform.getScaleY();
193                     dx = dx * (1 - z);
194                     dy = dy * (1 - z);
195 //                    double limitedScale = limitScaleFactor(z);
196 //                    if (limitedScale != 1.0) {
197                         translate(dx, dy);
198                         scale(z, z);
199                         transformChanged();
200                         dropQuality();
201                         repaint();
202 //                    }
203                 } else {
204                     // max zoom level reached
205                 }
206             }
207             return false;
208         }
209
210     }
211 }