package prefuse.controls; import java.awt.Cursor; import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import javax.swing.SwingUtilities; import prefuse.Display; import prefuse.data.Table; import prefuse.data.event.EventConstants; import prefuse.data.event.TableListener; import prefuse.visual.VisualItem; /** * Changes a node's location when dragged on screen. Other effects * include fixing a node's position when the mouse if over it, and * changing the mouse cursor to a hand when the mouse passes over an * item. * * @author <a href="http://jheer.org">jeffrey heer</a> */ public class DragControl extends ControlAdapter implements TableListener { private VisualItem activeItem; protected String action; protected Point2D down = new Point2D.Double(); protected Point2D temp = new Point2D.Double(); protected boolean dragged, wasFixed, resetItem; private boolean fixOnMouseOver = true; protected boolean repaint = true; /** * Creates a new drag control that issues repaint requests as an item * is dragged. */ public DragControl() { } /** * Creates a new drag control that optionally issues repaint requests * as an item is dragged. * @param repaint indicates whether or not repaint requests are issued * as drag events occur. This can be set to false if other activities * (for example, a continuously running force simulation) are already * issuing repaint events. */ public DragControl(boolean repaint) { this.repaint = repaint; } /** * Creates a new drag control that optionally issues repaint requests * as an item is dragged. * @param repaint indicates whether or not repaint requests are issued * as drag events occur. This can be set to false if other activities * (for example, a continuously running force simulation) are already * issuing repaint events. * @param fixOnMouseOver indicates if object positions should become * fixed (made stationary) when the mouse pointer is over an item. */ public DragControl(boolean repaint, boolean fixOnMouseOver) { this.repaint = repaint; this.fixOnMouseOver = fixOnMouseOver; } /** * Creates a new drag control that invokes an action upon drag events. * @param action the action to run when drag events occur. */ public DragControl(String action) { this.repaint = false; this.action = action; } /** * Creates a new drag control that invokes an action upon drag events. * @param action the action to run when drag events occur * @param fixOnMouseOver indicates if object positions should become * fixed (made stationary) when the mouse pointer is over an item. */ public DragControl(String action, boolean fixOnMouseOver) { this.repaint = false; this.fixOnMouseOver = fixOnMouseOver; this.action = action; } /** * Determines whether or not an item should have it's position fixed * when the mouse moves over it. * @param s whether or not item position should become fixed upon * mouse over. */ public void setFixPositionOnMouseOver(boolean s) { fixOnMouseOver = s; } /** * @see prefuse.controls.Control#itemEntered(prefuse.visual.VisualItem, java.awt.event.MouseEvent) */ public void itemEntered(VisualItem item, MouseEvent e) { Display d = (Display)e.getSource(); d.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); activeItem = item; if ( fixOnMouseOver ) { wasFixed = item.isFixed(); resetItem = true; item.setFixed(true); item.getTable().addTableListener(this); } } /** * @see prefuse.controls.Control#itemExited(prefuse.visual.VisualItem, java.awt.event.MouseEvent) */ public void itemExited(VisualItem item, MouseEvent e) { if ( activeItem == item ) { activeItem = null; item.getTable().removeTableListener(this); if ( resetItem ) item.setFixed(wasFixed); } Display d = (Display)e.getSource(); d.setCursor(Cursor.getDefaultCursor()); } // /** * @see prefuse.controls.Control#itemPressed(prefuse.visual.VisualItem, java.awt.event.MouseEvent) */ public void itemPressed(VisualItem item, MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e)) return; if ( !fixOnMouseOver ) { wasFixed = item.isFixed(); resetItem = true; item.setFixed(true); item.getTable().addTableListener(this); } dragged = false; Display d = (Display)e.getComponent(); d.getAbsoluteCoordinate(e.getPoint(), down); } /** * @see prefuse.controls.Control#itemReleased(prefuse.visual.VisualItem, java.awt.event.MouseEvent) */ public void itemReleased(VisualItem item, MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e)) return; if ( dragged ) { activeItem = null; item.getTable().removeTableListener(this); if ( resetItem ) item.setFixed(wasFixed); dragged = false; } } /** * @see prefuse.controls.Control#itemDragged(prefuse.visual.VisualItem, java.awt.event.MouseEvent) */ public void itemDragged(VisualItem item, MouseEvent e) { if (!SwingUtilities.isLeftMouseButton(e)) return; dragged = true; Display d = (Display)e.getComponent(); d.getAbsoluteCoordinate(e.getPoint(), temp); double dx = temp.getX()-down.getX(); double dy = temp.getY()-down.getY(); double x = item.getX(); double y = item.getY(); item.setStartX(x); item.setStartY(y); item.setX(x+dx); item.setY(y+dy); item.setEndX(x+dx); item.setEndY(y+dy); if ( repaint ) item.getVisualization().repaint(); down.setLocation(temp); if ( action != null ) d.getVisualization().run(action); } /** * @see prefuse.data.event.TableListener#tableChanged(prefuse.data.Table, int, int, int, int) */ public void tableChanged(Table t, int start, int end, int col, int type) { if ( activeItem == null || type != EventConstants.UPDATE || col != t.getColumnNumber(VisualItem.FIXED) ) return; int row = activeItem.getRow(); if ( row >= start && row <= end ) resetItem = false; } } // end of class DragControl