1 package org.simantics.district.network.ui;
3 import java.awt.geom.AffineTransform;
4 import java.awt.geom.Rectangle2D;
5 import java.util.Collection;
8 import java.util.stream.Collectors;
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;
28 public class DistrictPanZoomRotateHandler extends PanZoomRotateHandler {
30 public static final int DISTRICT_TRANSLATE_AMOUNT = 2;
32 @Dependency DistrictTransformUtil util;
33 @Reference Selection selection;
35 public DistrictPanZoomRotateHandler() {
39 public void addedToContext(ICanvasContext ctx) {
40 super.addedToContext(ctx);
41 setHint(KEY_TRANSLATE_AMOUNT, DISTRICT_TRANSLATE_AMOUNT);
45 protected Class<? extends NavigationNode> getNavigationNodeClass() {
46 return DistrictNavigationNode.class;
50 public double getTranslateAmount() {
51 return 15 * super.getTranslateAmount();
55 public double limitScaleFactor(double scaleFactor) {
60 @EventHandler(priority = 1)
61 public boolean handleEvent(CommandEvent e) {
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();
69 result = zoomToPage();
72 if (Commands.ZOOM_TO_PAGE.equals(c) && !zoomDisabled) {
75 if (Commands.ZOOM_TO_SELECTION.equals(c) && !zoomDisabled) {
76 return zoomToSelection();
78 return super.handleEvent(e);
81 private boolean zoomToFit() {
82 CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
83 if (boundsParticipant == null)
86 final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
87 if (controlBounds == null || controlBounds.isEmpty())
90 IDiagram d = getHint(DiagramHints.KEY_DIAGRAM);
94 Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(getMapElements(d.getElements()));
95 if (diagramRect == null)
97 if (diagramRect.isEmpty())
100 org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
102 // System.out.println("zoomToFit(" + controlArea + ", " + diagramRect + ")");
103 util.fitArea(controlBounds, diagramRect, null);
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;
116 private boolean zoomToPage() {
117 int currentZoomLevel = MapScalingTransform.zoomLevel(util.getTransform());
119 util.setTransform(new AffineTransform(2,0,0,2,270,270));
123 private boolean zoomToSelection() {
124 CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
125 if (boundsParticipant == null)
128 final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
129 if (controlBounds == null || controlBounds.isEmpty())
132 Set<IElement> selections = selection.getAllSelections();
133 if (selections == null || selections.isEmpty()) {
137 Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(getMapElements(selections));
139 // Make sure that even empty bounds can be zoomed into.
140 org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
142 util.fitArea(controlBounds, diagramRect, null);
146 public static class DistrictNavigationNode extends NavigationNode {
148 private static final long serialVersionUID = 5452897272925816875L;
150 public DistrictNavigationNode() {
151 setAdaptViewportToResizedControl(false);
155 public Double getZoomInLimit() {
156 return super.getZoomInLimit();
160 public Double getZoomOutLimit() {
161 return super.getZoomOutLimit();
165 public void setAdaptViewportToResizedControl(Boolean adapt) {
166 super.setAdaptViewportToResizedControl(false);
171 public boolean getAdaptViewportToResizedControl() {
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);
182 if (0 < zoomLevel && zoomLevel < 20 || (zoomLevel == 0 && me.wheelRotation > 0) || (zoomLevel == 20 && me.wheelRotation < 0)) {
184 if (me.wheelRotation > 0) {
185 z = DISTRICT_TRANSLATE_AMOUNT;
187 z = 1.0d / DISTRICT_TRANSLATE_AMOUNT;
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();
195 // double limitedScale = limitScaleFactor(z);
196 // if (limitedScale != 1.0) {
204 // max zoom level reached