/*
* SelectionEditingTool.java
*
* Created on March 26, 2007, 12:07 AM
*
*/
package ika.map.tools;
import ika.geo.*;
import ika.gui.MapComponent;
import ika.gui.SelectionBox;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
/**
* An abstract base class for tools that interactively scale, rotate or move
* selected objects. Manages an AffineTransform that is used to draw selected
* objects while dragging. With this approach, the selected objects don't need
* to be copied and their geometry be transformed during an interactive dragging
* operation.
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich
*/
abstract public class SelectionEditingTool extends DoubleBufferedTool {
/**
* The box surounding all selected objects before dragging starts.
*/
protected Rectangle2D initialSelectionBox = null;
/**
* Remember the start location of the drag. This must be initialized by
* derived classes in the startDrag method with:
* this.startPoint = (Point2D.Double)point.clone();
*/
protected Point2D.Double startPoint;
/** Creates a new instance of SelectionEditingTool */
public SelectionEditingTool(MapComponent mapComponent) {
super(mapComponent);
}
public boolean isDragging() {
return initialSelectionBox != null;
}
/**
* Returns whether the passed point differs from the point where the
* user clicked to start the dragging.
*/
protected boolean differentFromStartPoint(Point2D point) {
if (this.startPoint == null)
return false;
return point.distanceSq(this.startPoint) > 0;
}
/**
* Returns an affine transformation that is applied on selected objects
* before drawing them during a dragging process.
*/
abstract protected AffineTransform computeTransform(Point2D.Double point,
MouseEvent evt);
/**
* The mouse location changed during a drag, while this MapTool was the active one.
* @param pointThe location of the mouse in world coordinates.
* @param evt The original event.
*/
public void updateDrag(Point2D.Double point, MouseEvent evt) {
if (!this.isDragging())
return;
// store the current affine transformation for the selected objects
// in the MapComponent. This transformation will be used to draw
// selected GeoObjects
AffineTransform trans = this.computeTransform(point, evt);
this.mapComponent.setTransformForSelectedObjects(trans);
// Force a redraw of the map.
this.mapComponent.repaint();
}
/**
* Release all allocated resources and reset variables. Derived classes must
* call this method in their endDrag method.
*/
protected void release() {
this.initialSelectionBox = null;
this.startPoint = null;
this.mapComponent.setTransformForSelectedObjects(null);
this.releaseBackground();
this.setDefaultCursor();
}
/**
* Draws the selected GeoObjects
*/
public void draw(RenderParams rp) {
if (!this.isDragging())
return;
AffineTransform originalTrans = rp.g2d.getTransform();
try {
// draw all selected GeoObjects of the map, but not the unselected ones.
this.mapComponent.shiftGraphics2DByBorderWidth(rp.g2d);
this.mapComponent.paintMap(rp.g2d, true);
// paint a box around all selected objects
SelectionBox.paintSelectionBox(initialSelectionBox, rp, false);
} finally {
rp.g2d.setTransform(originalTrans);
}
}
/**
* Treat escape key events.
* The event can be consumed (return true) or be delegated to other
* listeners (return false).
* @param keyEvent The new key event.
* @return True if the key event has been consumed, false otherwise.
*/
public boolean keyEvent(KeyEvent keyEvent) {
if (keyEvent.getKeyCode() != KeyEvent.VK_ESCAPE)
return false;
if (this.isDragging() == false)
return false;
this.release();
return true;
}
protected String getCursorName() {
return "arrow";
}
}