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();
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;