edu.uci.ics.jung.visualization.control.RotatingGraphMousePlugin Maven / Gradle / Ivy
/*
* Copyright (c) 2005, The JUNG Authors
*
* All rights reserved.
*
* This software is open-source under the BSD license; see either
* "license.txt" or
* https://github.com/jrtom/jung/blob/master/LICENSE for a description.
* Created on Mar 8, 2005
*
*/
package edu.uci.ics.jung.visualization.control;
import edu.uci.ics.jung.visualization.MultiLayerTransformer.Layer;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.transform.MutableTransformer;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.Collections;
/**
* RotatingGraphMouse provides the abiity to rotate the graph using the mouse. By default, it is
* activated by mouse button one drag with the shift key pressed. The modifiers can be overridden so
* that a different mouse/key combination activates the rotation
*
* @author Tom Nelson
*/
public class RotatingGraphMousePlugin extends AbstractGraphMousePlugin
implements MouseListener, MouseMotionListener {
/** create an instance with default modifier values */
public RotatingGraphMousePlugin() {
this(MouseEvent.BUTTON1_MASK | MouseEvent.SHIFT_MASK);
}
/**
* create an instance with passed zoom in/out values
*
* @param modifiers the event modifiers to trigger rotation
*/
public RotatingGraphMousePlugin(int modifiers) {
super(modifiers);
Dimension cd = Toolkit.getDefaultToolkit().getBestCursorSize(16, 16);
BufferedImage cursorImage = new BufferedImage(cd.width, cd.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = cursorImage.createGraphics();
g.addRenderingHints(
Collections.singletonMap(
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
g.setColor(new Color(0, 0, 0, 0));
g.fillRect(0, 0, 16, 16);
int left = 0;
int top = 0;
int right = 15;
int bottom = 15;
g.setColor(Color.white);
g.setStroke(new BasicStroke(3));
// top bent line
g.drawLine(left + 2, top + 6, right / 2 + 1, top);
g.drawLine(right / 2 + 1, top, right - 2, top + 5);
// bottom bent line
g.drawLine(left + 2, bottom - 6, right / 2, bottom);
g.drawLine(right / 2, bottom, right - 2, bottom - 6);
// top arrow
g.drawLine(left + 2, top + 6, left + 5, top + 6);
g.drawLine(left + 2, top + 6, left + 2, top + 3);
// bottom arrow
g.drawLine(right - 2, bottom - 6, right - 6, bottom - 6);
g.drawLine(right - 2, bottom - 6, right - 2, bottom - 3);
g.setColor(Color.black);
g.setStroke(new BasicStroke(1));
// top bent line
g.drawLine(left + 2, top + 6, right / 2 + 1, top);
g.drawLine(right / 2 + 1, top, right - 2, top + 5);
// bottom bent line
g.drawLine(left + 2, bottom - 6, right / 2, bottom);
g.drawLine(right / 2, bottom, right - 2, bottom - 6);
// top arrow
g.drawLine(left + 2, top + 6, left + 5, top + 6);
g.drawLine(left + 2, top + 6, left + 2, top + 3);
// bottom arrow
g.drawLine(right - 2, bottom - 6, right - 6, bottom - 6);
g.drawLine(right - 2, bottom - 6, right - 2, bottom - 3);
g.dispose();
cursor =
Toolkit.getDefaultToolkit().createCustomCursor(cursorImage, new Point(), "RotateCursor");
}
/**
* save the 'down' point and check the modifiers. If the modifiers are accepted, set the cursor to
* the 'hand' cursor
*
* @param e the event
*/
public void mousePressed(MouseEvent e) {
VisualizationViewer, ?> vv = (VisualizationViewer, ?>) e.getSource();
boolean accepted = checkModifiers(e);
down = e.getPoint();
if (accepted) {
vv.setCursor(cursor);
}
}
/** unset the down point and change the cursor back to the default */
public void mouseReleased(MouseEvent e) {
VisualizationViewer, ?> vv = (VisualizationViewer, ?>) e.getSource();
down = null;
vv.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
/** check the modifiers. If accepted, use the mouse drag motion to rotate the graph */
public void mouseDragged(MouseEvent e) {
if (down == null) {
return;
}
VisualizationViewer, ?> vv = (VisualizationViewer, ?>) e.getSource();
boolean accepted = checkModifiers(e);
if (accepted) {
MutableTransformer modelTransformer =
vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT);
// rotate
vv.setCursor(cursor);
Point2D center = vv.getCenter();
Point2D q = down;
Point2D p = e.getPoint();
Point2D v1 = new Point2D.Double(center.getX() - p.getX(), center.getY() - p.getY());
Point2D v2 = new Point2D.Double(center.getX() - q.getX(), center.getY() - q.getY());
double theta = angleBetween(v1, v2);
modelTransformer.rotate(
theta,
vv.getRenderContext().getMultiLayerTransformer().inverseTransform(Layer.VIEW, center));
down.x = e.getX();
down.y = e.getY();
e.consume();
}
}
/**
* Returns the angle between two vectors from the origin to points v1 and v2.
*
* @param v1 the first point
* @param v2 the second point
* @return the angle between two vectors from the origin through points v1 and v2
*/
protected double angleBetween(Point2D v1, Point2D v2) {
double x1 = v1.getX();
double y1 = v1.getY();
double x2 = v2.getX();
double y2 = v2.getY();
// cross product for direction
double cross = x1 * y2 - x2 * y1;
int cw = 1;
if (cross > 0) {
cw = -1;
}
// dot product for angle
double angle =
cw
* Math.acos(
(x1 * x2 + y1 * y2)
/ (Math.sqrt(x1 * x1 + y1 * y1) * Math.sqrt(x2 * x2 + y2 * y2)));
if (Double.isNaN(angle)) {
angle = 0;
}
return angle;
}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy