package maps.gml.editor; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.Color; import java.awt.Point; import java.awt.Insets; import maps.gml.view.NodeDecorator; import maps.gml.view.SquareNodeDecorator; import maps.gml.GMLNode; import maps.gml.GMLCoordinates; import javax.swing.undo.AbstractUndoableEdit; /** A tool for moving nodes. */ public class MoveNodeTool extends AbstractTool { private static final Color HIGHLIGHT_COLOUR = Color.BLACK; private static final int HIGHLIGHT_SIZE = 6; private Listener listener; private NodeDecorator highlight; private GMLNode selected; private GMLCoordinates pressCoords; private GMLCoordinates originalCoords; /** Construct a MoveNodeTool. @param editor The editor instance. */ public MoveNodeTool(GMLEditor editor) { super(editor); listener = new Listener(); highlight = new SquareNodeDecorator(HIGHLIGHT_COLOUR, HIGHLIGHT_SIZE); selected = null; } @Override public String getName() { return "Move node"; } @Override public void activate() { editor.getViewer().addMouseListener(listener); editor.getViewer().addMouseMotionListener(listener); selected = null; } @Override public void deactivate() { editor.getViewer().removeMouseListener(listener); editor.getViewer().removeMouseMotionListener(listener); editor.getViewer().clearAllNodeDecorators(); editor.getViewer().repaint(); } private void highlightNode(GMLNode node) { if (selected == node) { return; } if (selected != null) { editor.getViewer().clearNodeDecorator(selected); } selected = node; if (selected != null) { editor.getViewer().setNodeDecorator(highlight, selected); } editor.getViewer().repaint(); } private class Listener implements MouseListener, MouseMotionListener { @Override public void mouseMoved(MouseEvent e) { Point p = fixEventPoint(e.getPoint()); GMLCoordinates c = editor.getViewer().getCoordinatesAtPoint(p.x, p.y); GMLNode node = editor.getMap().findNearestNode(c.getX(), c.getY()); highlightNode(node); } @Override public void mousePressed(MouseEvent e) { if (selected == null) { return; } if (e.getButton() == MouseEvent.BUTTON1) { Point p = fixEventPoint(e.getPoint()); pressCoords = editor.getViewer().getCoordinatesAtPoint(p.x, p.y); originalCoords = new GMLCoordinates(selected.getCoordinates()); } } @Override public void mouseReleased(MouseEvent e) { pressCoords = null; editor.addEdit(new MoveNodeEdit(selected, originalCoords, new GMLCoordinates(selected.getCoordinates()))); } @Override public void mouseDragged(MouseEvent e) { if (selected == null) { return; } if (pressCoords == null) { return; } Point p = fixEventPoint(e.getPoint()); GMLCoordinates dragCoords = editor.getViewer().getCoordinatesAtPoint(p.x, p.y); double dx = dragCoords.getX() - pressCoords.getX(); double dy = dragCoords.getY() - pressCoords.getY(); GMLCoordinates result = new GMLCoordinates(originalCoords.getX() + dx, originalCoords.getY() + dy); editor.snap(result); selected.setCoordinates(result); editor.setChanged(); editor.getViewer().repaint(); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } private Point fixEventPoint(Point p) { Insets insets = editor.getViewer().getInsets(); return new Point(p.x - insets.left, p.y - insets.top); } } private class MoveNodeEdit extends AbstractUndoableEdit { private GMLNode node; private GMLCoordinates oldPosition; private GMLCoordinates newPosition; public MoveNodeEdit(GMLNode node, GMLCoordinates oldPosition, GMLCoordinates newPosition) { this.node = node; this.oldPosition = oldPosition; this.newPosition = newPosition; } @Override public void undo() { super.undo(); node.setCoordinates(oldPosition); editor.getViewer().repaint(); } @Override public void redo() { super.redo(); node.setCoordinates(newPosition); editor.getViewer().repaint(); } } }