/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt.client.controller;
import java.util.Date;
import org.geomajas.geometry.Coordinate;
import org.geomajas.gwt.client.gfx.paintable.Rectangle;
import org.geomajas.gwt.client.gfx.style.ShapeStyle;
import org.geomajas.gwt.client.spatial.Bbox;
import org.geomajas.gwt.client.spatial.WorldViewTransformer;
import org.geomajas.gwt.client.widget.MapWidget;
import org.geomajas.gwt.client.widget.MapWidget.RenderGroup;
import org.geomajas.gwt.client.widget.MapWidget.RenderStatus;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.smartgwt.client.widgets.menu.Menu;
/**
* Base controller which handles the display of the rectangle which allows selection.
*
* @author Joachim Van der Auwera
*/
public abstract class AbstractRectangleController extends AbstractGraphicsController {
protected Rectangle rectangle;
protected boolean dragging;
protected long timestamp;
protected Coordinate begin;
protected Bbox bounds;
protected boolean shift;
protected boolean leftWidget;
protected ShapeStyle rectangleStyle = new ShapeStyle("#FF9900", 0.2f, "#FF9900", 1f, 2);
protected Menu menu;
public AbstractRectangleController(MapWidget mapWidget) {
super(mapWidget);
}
public ShapeStyle getRectangleStyle() {
return rectangleStyle;
}
public void setRectangleStyle(ShapeStyle rectangleStyle) {
this.rectangleStyle = rectangleStyle;
}
/**
* Start dragging, register base for selection rectangle.
*
* @param event
* event
*/
@Override
public void onMouseDown(MouseDownEvent event) {
if (dragging && leftWidget) {
// mouse was moved outside of widget
doSelect(event);
} else if (event.getNativeButton() != NativeEvent.BUTTON_RIGHT) {
// no point trying to select when there is no active layer
dragging = true;
leftWidget = false;
timestamp = new Date().getTime();
begin = getScreenPosition(event);
bounds = new Bbox(begin.getX(), begin.getY(), 0.0, 0.0);
shift = event.isShiftKeyDown();
rectangle = new Rectangle("selectionRectangle");
rectangle.setStyle(rectangleStyle);
rectangle.setBounds(bounds);
mapWidget.render(rectangle, RenderGroup.SCREEN, RenderStatus.UPDATE);
}
}
/**
* Finish selection using rectangle.
*
* @param event
* event
*/
@Override
public void onMouseUp(MouseUpEvent event) {
// assure dragging or clicking started inside this widget
if (dragging) {
doSelect(event);
}
}
private void doSelect(MouseEvent<?> event) {
dragging = false;
shift |= event.isShiftKeyDown(); // shift is used when depressed either at beginning or end
updateRectangle(event);
WorldViewTransformer transformer = new WorldViewTransformer(mapWidget.getMapModel().getMapView());
Bbox worldBounds = transformer.viewToWorld(bounds);
selectRectangle(worldBounds);
mapWidget.render(rectangle, RenderGroup.SCREEN, RenderStatus.DELETE);
}
/**
* Overwrite this method to handle the actual selection. The bounds variable contains the selected area.
*
* @param worldBounds
* bounds in world coordinates
*/
protected abstract void selectRectangle(Bbox worldBounds);
@Override
public void onMouseMove(MouseMoveEvent event) {
if (dragging) {
updateRectangle(event);
mapWidget.render(rectangle, RenderGroup.SCREEN, RenderStatus.UPDATE);
}
}
@Override
public void onMouseOut(MouseOutEvent event) {
leftWidget = true;
// stopDragging();
}
protected void stopDragging() {
if (dragging) {
dragging = false;
mapWidget.render(rectangle, RenderGroup.SCREEN, RenderStatus.DELETE);
}
}
private void updateRectangle(MouseEvent<?> event) {
Coordinate pos = getScreenPosition(event);
double x = begin.getX();
double y = begin.getY();
double width = pos.getX() - x;
double height = pos.getY() - y;
if (width < 0) {
x = pos.getX();
width = -width;
}
if (height < 0) {
y = pos.getY();
height = -height;
}
bounds.setX(x);
bounds.setY(y);
bounds.setWidth(width);
bounds.setHeight(height);
}
@Override
public void onDeactivate() {
super.onDeactivate();
// make sure to clean up
stopDragging();
}
}