/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.android.maps.inputhandling;
import org.mapsforge.android.maps.MapView;
import org.mapsforge.core.model.GeoPoint;
import android.content.Context;
import android.view.MotionEvent;
/**
* Implementation for single-touch capable devices.
*/
public class SingleTouchHandler extends TouchEventHandler {
SingleTouchHandler(Context context, MapView mapView) {
super(context, mapView);
}
@Override
public int getAction(MotionEvent motionEvent) {
return motionEvent.getAction();
}
private boolean onActionCancel() {
this.longPressDetector.pressStop();
return true;
}
private boolean onActionDown(MotionEvent motionEvent) {
this.longPressDetector.pressStart();
// save the position of the event
this.previousPositionX = motionEvent.getX();
this.previousPositionY = motionEvent.getY();
this.moveThresholdReached = false;
return true;
}
private boolean onActionMove(MotionEvent motionEvent) {
// calculate the distance between previous and current position
float moveX = motionEvent.getX() - this.previousPositionX;
float moveY = motionEvent.getY() - this.previousPositionY;
if (!this.moveThresholdReached) {
if (Math.abs(moveX) > this.mapMoveDelta || Math.abs(moveY) > this.mapMoveDelta) {
// the map movement threshold has been reached
this.longPressDetector.pressStop();
this.moveThresholdReached = true;
// save the position of the event
this.previousPositionX = motionEvent.getX();
this.previousPositionY = motionEvent.getY();
}
return true;
}
// save the position of the event
this.previousPositionX = motionEvent.getX();
this.previousPositionY = motionEvent.getY();
this.mapView.getFrameBuffer().matrixPostTranslate(moveX, moveY);
this.mapView.getMapPosition().moveMap(moveX, moveY);
this.mapView.redrawTiles();
return true;
}
private boolean onActionUp(MotionEvent motionEvent) {
this.longPressDetector.pressStop();
if (this.moveThresholdReached || this.longPressDetector.isEventHandled()) {
this.previousEventTap = false;
} else {
if (this.previousEventTap) {
// calculate the distance to the previous tap position
float tapDiffX = Math.abs(motionEvent.getX() - this.previousTapX);
float tapDiffY = Math.abs(motionEvent.getY() - this.previousTapY);
long tapDiffTime = motionEvent.getEventTime() - this.previousTapTime;
// check if a double-tap event occurred
if (tapDiffX < this.doubleTapDelta && tapDiffY < this.doubleTapDelta
&& tapDiffTime < this.doubleTapTimeout) {
// double-tap event
this.previousEventTap = false;
this.mapView.setCenter(this.mapView.getProjection().fromPixels((int) motionEvent.getX(),
(int) motionEvent.getY()));
this.mapView.zoom((byte) 1, 1);
return true;
}
} else {
this.previousEventTap = true;
}
// store the position and the time of this tap event
this.previousTapX = motionEvent.getX();
this.previousTapY = motionEvent.getY();
this.previousTapTime = motionEvent.getEventTime();
GeoPoint tapPoint = this.mapView.getProjection().fromPixels((int) motionEvent.getX(),
(int) motionEvent.getY());
synchronized (this.mapView.getOverlays()) {
for (int i = this.mapView.getOverlays().size() - 1; i >= 0; --i) {
if (this.mapView.getOverlays().get(i).onTap(tapPoint, this.mapView)) {
// the tap event has been handled
break;
}
}
}
}
return true;
}
@Override
boolean handleMotionEvent(MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
return onActionDown(motionEvent);
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
return onActionMove(motionEvent);
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
return onActionUp(motionEvent);
} else if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
return onActionCancel();
}
// the event was not handled
return false;
}
}