Skip to content

Commit

Permalink
Implement pan and zoom with mouse
Browse files Browse the repository at this point in the history
  • Loading branch information
FeldrinH committed Sep 14, 2023
1 parent c123676 commit db96c1b
Showing 1 changed file with 110 additions and 2 deletions.
112 changes: 110 additions & 2 deletions src/main/java/ee/ut/dendroloj/GraphGUI.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
package ee.ut.dendroloj;

import org.graphstream.graph.Graph;

import org.graphstream.graph.implementations.SingleGraph;
import org.graphstream.ui.geom.Point2;
import org.graphstream.ui.geom.Point3;
import org.graphstream.ui.swing_viewer.SwingViewer;
import org.graphstream.ui.swing_viewer.util.DefaultMouseManager;
import org.graphstream.ui.view.View;
import org.graphstream.ui.view.camera.Camera;
import org.graphstream.ui.view.util.MouseManager;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class GraphGUI {
public static void init(double uiScale) {
Expand Down Expand Up @@ -42,6 +52,104 @@ public static void init(double uiScale) {
""", Math.sqrt(uiScale), uiScale * 12, uiScale + 1, Math.sqrt(uiScale) * 10, uiScale * 12, uiScale + 1));

SimpleTreeLayout.setGraph(graph);
graph.display(false);

SwingViewer viewer = new SwingViewer(graph, SwingViewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
View view = viewer.addDefaultView(false);
Component viewComponent = (Component) view;

// GraphStream DefaultMouseManager but with event handling enabled only for left click to prevent interference with panning.
MouseManager restrictedDefaultMouseManager = new DefaultMouseManager() {
@Override
public void mousePressed(MouseEvent event) {
if (SwingUtilities.isLeftMouseButton(event)) {
super.mousePressed(event);
}
}

@Override
public void mouseReleased(MouseEvent event) {
if (SwingUtilities.isLeftMouseButton(event)) {
super.mouseReleased(event);
}
}

@Override
public void mouseDragged(MouseEvent event) {
if (SwingUtilities.isLeftMouseButton(event)) {
if (curElement != null) {
elementMoving(curElement, event);
viewComponent.repaint(); // Doing this makes moving elements appear much smoother.
} else {
view.selectionGrowsAt(event.getX(), event.getY());
}
}
}
};
view.setMouseManager(restrictedDefaultMouseManager);

MouseAdapter zoomAndPanAdapter = new MouseAdapter() {
private static final double ZOOM_FACTOR = 1.25;

private final Point lastPxCursor = new Point();

@Override
public void mouseWheelMoved(MouseWheelEvent event) {
event.consume();

// Zoom towards cursor with scroll wheel. Adapted from https://stackoverflow.com/a/52929241.
int i = event.getWheelRotation();
double factor = Math.pow(ZOOM_FACTOR, i);
Camera cam = view.getCamera();
double zoom = cam.getViewPercent() * factor;
Point2 pxCenter = cam.transformGuToPx(cam.getViewCenter().x, cam.getViewCenter().y, 0);
Point3 guCursor = cam.transformPxToGu(event.getX(), event.getY());
double newRatioPx2Gu = cam.getMetrics().ratioPx2Gu / factor;
double x = guCursor.x + (pxCenter.x - event.getX()) / newRatioPx2Gu;
double y = guCursor.y - (pxCenter.y - event.getY()) / newRatioPx2Gu;
cam.setViewCenter(x, y, 0);
cam.setViewPercent(zoom);

viewComponent.repaint();
}

public void mousePressed(MouseEvent event) {
if (SwingUtilities.isRightMouseButton(event)) {
event.consume();

lastPxCursor.setLocation(event.getPoint());
}
}

@Override
public void mouseDragged(MouseEvent event) {
if (SwingUtilities.isRightMouseButton(event)) {
event.consume();

Point newPxCursor = event.getPoint();
Camera cam = view.getCamera();
Point2 viewCenter = cam.getViewCenter();
double ratioPx2Gu = cam.getMetrics().ratioPx2Gu;
double x = viewCenter.x + (lastPxCursor.x - newPxCursor.x) / ratioPx2Gu;
double y = viewCenter.y - (lastPxCursor.y - newPxCursor.y) / ratioPx2Gu;
cam.setViewCenter(x, y, 0);
lastPxCursor.setLocation(newPxCursor);

viewComponent.repaint();
}
}
};
viewComponent.addMouseListener(zoomAndPanAdapter);
viewComponent.addMouseMotionListener(zoomAndPanAdapter);
viewComponent.addMouseWheelListener(zoomAndPanAdapter);

JFrame root = new JFrame();
root.setTitle("dendroloj");
root.setLayout(new BorderLayout());
root.add(viewComponent, BorderLayout.CENTER);
root.setSize(800, 600);
root.setLocationRelativeTo(null);
root.addWindowListener((WindowListener) viewComponent);
root.addComponentListener((ComponentListener) viewComponent);
root.setVisible(true);
}
}

0 comments on commit db96c1b

Please sign in to comment.