package maps.gml.editor; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.Point; import java.awt.Insets; import java.awt.Color; import maps.gml.GMLNode; import maps.gml.GMLEdge; import maps.gml.GMLRoad; import maps.gml.GMLBuilding; import maps.gml.GMLSpace; import maps.gml.GMLShape; import maps.gml.GMLObject; import maps.gml.GMLCoordinates; import maps.gml.view.FilledShapeDecorator; import maps.gml.view.NodeDecorator; import maps.gml.view.EdgeDecorator; import maps.gml.view.SquareNodeDecorator; import maps.gml.view.LineEdgeDecorator; import rescuecore2.misc.geometry.Point2D; import rescuecore2.misc.geometry.Line2D; import rescuecore2.misc.geometry.GeometryTools2D; /** A tool for inspecting objects. */ public class InspectTool extends AbstractTool { /** Distance in pixels to consider an object "nearby". */ private static final int NEARBY = 5; private static final Color HIGHLIGHT_COLOUR = Color.BLUE; private static final int NODE_SIZE = 5; private Listener listener; private NodeDecorator nodeHighlight; private EdgeDecorator edgeHighlight; private FilledShapeDecorator shapeHighlight; /** Construct an InspectTool. @param editor The editor instance. */ public InspectTool(GMLEditor editor) { super(editor); listener = new Listener(); nodeHighlight = new SquareNodeDecorator(HIGHLIGHT_COLOUR, NODE_SIZE); edgeHighlight = new LineEdgeDecorator(HIGHLIGHT_COLOUR); shapeHighlight = new FilledShapeDecorator(HIGHLIGHT_COLOUR, HIGHLIGHT_COLOUR, HIGHLIGHT_COLOUR); } @Override public String getName() { return "Inspect object"; } @Override public void activate() { editor.getViewer().addMouseListener(listener); editor.getViewer().addMouseMotionListener(listener); } @Override public void deactivate() { editor.getViewer().removeMouseListener(listener); editor.getViewer().removeMouseMotionListener(listener); editor.getViewer().clearAllNodeDecorators(); editor.getViewer().clearAllEdgeDecorators(); editor.getViewer().clearAllBuildingDecorators(); editor.getViewer().clearAllRoadDecorators(); editor.getViewer().clearAllSpaceDecorators(); editor.getViewer().repaint(); } private void highlight(GMLObject object) { editor.getViewer().clearAllNodeDecorators(); editor.getViewer().clearAllEdgeDecorators(); editor.getViewer().clearAllBuildingDecorators(); editor.getViewer().clearAllRoadDecorators(); editor.getViewer().clearAllSpaceDecorators(); if (object instanceof GMLNode) { editor.getViewer().setNodeDecorator(nodeHighlight, (GMLNode)object); } if (object instanceof GMLEdge) { editor.getViewer().setEdgeDecorator(edgeHighlight, (GMLEdge)object); } if (object instanceof GMLBuilding) { editor.getViewer().setBuildingDecorator(shapeHighlight, (GMLBuilding)object); } if (object instanceof GMLRoad) { editor.getViewer().setRoadDecorator(shapeHighlight, (GMLRoad)object); } if (object instanceof GMLSpace) { editor.getViewer().setSpaceDecorator(shapeHighlight, (GMLSpace)object); } editor.getViewer().repaint(); } private boolean closeEnough(GMLNode node, Point p) { GMLCoordinates lowerLeft = editor.getViewer().getCoordinatesAtPoint(p.x - NEARBY, p.y + NEARBY); GMLCoordinates topRight = editor.getViewer().getCoordinatesAtPoint(p.x + NEARBY, p.y - NEARBY); return (node.getX() > lowerLeft.getX() && node.getX() < topRight.getX() && node.getY() > lowerLeft.getY() && node.getY() < topRight.getY()); } private boolean closeEnough(GMLEdge edge, Point p) { Point start = editor.getViewer().getScreenCoordinates(edge.getStart().getCoordinates()); Point end = editor.getViewer().getScreenCoordinates(edge.getEnd().getCoordinates()); Point2D startPoint = new Point2D(start.x, start.y); Point2D endPoint = new Point2D(end.x, end.y); Line2D line = new Line2D(startPoint, endPoint); Point2D testPoint = new Point2D(p.x, p.y); Point2D closest = GeometryTools2D.getClosestPointOnSegment(line, testPoint); return GeometryTools2D.getDistance(testPoint, closest) < NEARBY; } private class Listener implements MouseListener, MouseMotionListener { @Override public void mouseClicked(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { Point p = fixEventPoint(e.getPoint()); editor.getInspector().inspect(findNearbyObject(p)); } } @Override public void mouseMoved(MouseEvent e) { Point p = fixEventPoint(e.getPoint()); highlight(findNearbyObject(p)); } @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 GMLObject findNearbyObject(Point p) { GMLCoordinates c = editor.getViewer().getCoordinatesAtPoint(p.x, p.y); GMLNode node = editor.getMap().findNearestNode(c.getX(), c.getY()); GMLEdge edge = editor.getMap().findNearestEdge(c.getX(), c.getY()); GMLShape shape = editor.getMap().findShapeUnder(c.getX(), c.getY()); // If the node is close enough inspect that // Otherwise, if the edge is close enough // Otherwise the shape if (node != null && closeEnough(node, p)) { return node; } else if (edge != null && closeEnough(edge, p)) { return edge; } else { return shape; } } private Point fixEventPoint(Point p) { Insets insets = editor.getViewer().getInsets(); return new Point(p.x - insets.left, p.y - insets.top); } } }