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