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 javax.swing.undo.AbstractUndoableEdit; import java.util.Collection; import java.util.Iterator; import maps.gml.GMLEdge; import maps.gml.GMLShape; import maps.gml.GMLCoordinates; import maps.gml.view.EdgeDecorator; import maps.gml.view.LineEdgeDecorator; /** A tool for toggling the passable flag on edges. */ public class TogglePassableTool extends AbstractTool { private static final Color HIGHLIGHT_COLOUR = Color.BLUE; private Listener listener; private EdgeDecorator highlight; private GMLEdge selected; /** Construct a TogglePassableTool. @param editor The editor instance. */ public TogglePassableTool(GMLEditor editor) { super(editor); highlight = new LineEdgeDecorator(HIGHLIGHT_COLOUR); listener = new Listener(); } @Override public String getName() { return "Toggle passable"; } @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().clearAllEdgeDecorators(); editor.getViewer().repaint(); } private void highlight(GMLEdge edge) { if (selected == edge) { return; } if (selected != null) { editor.getViewer().clearEdgeDecorator(selected); } selected = edge; if (selected != null) { editor.getViewer().setEdgeDecorator(highlight, selected); } editor.getViewer().repaint(); } private void toggle() { boolean isPassable = !selected.isPassable(); setPassable(selected, isPassable); editor.addEdit(new ToggleEdit(selected, isPassable)); } private void setPassable(GMLEdge edge, boolean passable) { edge.setPassable(passable); Collection<GMLShape> attached = editor.getMap().getAttachedShapes(edge); Iterator<GMLShape> it = attached.iterator(); GMLShape first = it.next(); GMLShape second = it.next(); if (passable) { first.setNeighbour(edge, second.getID()); second.setNeighbour(edge, first.getID()); } else { first.setNeighbour(edge, null); second.setNeighbour(edge, null); } editor.setChanged(); 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); GMLEdge edge = editor.getMap().findNearestEdge(c.getX(), c.getY()); if (editor.getMap().getAttachedShapes(edge).size() == 2) { highlight(edge); } } @Override public void mouseClicked(MouseEvent e) { if (selected == null) { return; } if (e.getButton() == MouseEvent.BUTTON1) { toggle(); highlight(null); } } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseDragged(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 ToggleEdit extends AbstractUndoableEdit { private GMLEdge edge; private boolean newPassable; public ToggleEdit(GMLEdge edge, boolean newPassable) { this.edge = edge; this.newPassable = newPassable; } @Override public void undo() { super.undo(); setPassable(edge, !newPassable); editor.getViewer().repaint(); } @Override public void redo() { super.redo(); setPassable(edge, newPassable); editor.getViewer().repaint(); } } }