/*
* GeoSolutions GeoSolutions Android Map Library - Digital mapping on Android based devices
* Copyright (C) 2013 GeoSolutions (www.geo-solutions.it)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.geosolutions.android.map.listeners;
import it.geosolutions.android.map.R;
import it.geosolutions.android.map.activities.GetFeatureInfoLayerListActivity;
import it.geosolutions.android.map.common.Constants;
import it.geosolutions.android.map.model.Layer;
import it.geosolutions.android.map.model.query.CircleQuery;
import it.geosolutions.android.map.model.query.BBoxQuery;
import it.geosolutions.android.map.overlay.managers.MultiSourceOverlayManager;
import it.geosolutions.android.map.utils.ConversionUtilities;
import it.geosolutions.android.map.view.AdvancedMapView;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
/**
* Listener that implements OnTouch Event on map.
*
* @author Lorenzo Natali (www.geo-solutions.it)
*/
public class MapInfoListener implements OnTouchListener {
// MODES
private int mode = Constants.Modes.MODE_EDIT;
private boolean dragStarted;
private float startX;
private float startY;
private float endX;
private float endY;
protected AdvancedMapView view;
private boolean isPinching;
private Activity activity;
private SharedPreferences pref; // Used to check shape of selection desired
/**
* Constructor for class MapInfoListener
*
* @param mapView
* @param activity
* @param Shape_Selection
*/
public MapInfoListener(AdvancedMapView mapView, Activity activity) {
view = mapView;
this.setActivity(activity);
pref = PreferenceManager.getDefaultSharedPreferences(activity
.getApplicationContext());
}
/**
* Create a FeatureQuery for rectangular selection and pass it via intent.
*
* @param n
* @param w
* @param s
* @param e
* @param zoomLevel
*/
protected void infoDialog(final double n, final double w, final double s,
final double e, byte zoomLevel) {
try {
ArrayList<Layer> layerNames = getLayers();
Intent i = new Intent(view.getContext(),
GetFeatureInfoLayerListActivity.class);
i.putExtra(Constants.ParamKeys.LAYERS, layerNames);
BBoxQuery query = new BBoxQuery();
query.setE(e);
query.setN(n);
query.setS(s);
query.setW(w);
query.setZoomLevel(zoomLevel);
query.setSrid("4326");
i.putExtra("query", query);
if (mode == Constants.Modes.MODE_EDIT) {
i.setAction(Intent.ACTION_PICK);
} else {
i.setAction(Intent.ACTION_VIEW);
}
getActivity().startActivityForResult(i,
GetFeatureInfoLayerListActivity.BBOX_REQUEST);
} catch (Exception ex) {
Log.e("MapInfoListener", Log.getStackTraceString(ex));
}
}
/**
* Get layers from the mapView
*
* @return an arrayList of layers
*/
protected ArrayList<Layer> getLayers() {
MultiSourceOverlayManager manager = view.getLayerManager();
ArrayList<Layer> layers = manager.getLayers();
ArrayList<Layer> result = new ArrayList<Layer>();
for (Layer layer : layers) {
if (layer.isVisibility()) {
result.add(layer);
}
}
return result;
}
/**
* Create a Feature Query for circular selection and pass it to an activity
* via intent.
*
* @param x
* @param y
* @param radius
* @param zoomLevel
*/
private void infoDialogCircle(final double x, final double y,
final double radius, byte zoomLevel) {
try {
ArrayList<Layer> layers = getLayers();
Intent i = new Intent(view.getContext(),
GetFeatureInfoLayerListActivity.class);
i.putExtra(Constants.ParamKeys.LAYERS, layers);
CircleQuery query = new CircleQuery();
query.setX(x);
query.setY(y);
query.setRadius(radius);
query.setSrid("4326");
query.setZoomLevel(zoomLevel);
i.putExtra("query", query);
if (mode == Constants.Modes.MODE_EDIT) {
i.setAction(Intent.ACTION_PICK);
} else {
i.setAction(Intent.ACTION_VIEW);
}
getActivity().startActivityForResult(i,
GetFeatureInfoLayerListActivity.CIRCLE_REQUEST);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Method to handle touch event on view.
*
* @param v
* @param event
* class that handle touch.
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
String[] array = getActivity().getResources().getStringArray(
R.array.preferences_selection_shape);
int action = event.getAction();
int pointerCount = event.getPointerCount(); // Number of pointer of
// device
// Try to skip pinch events
if (Log.isLoggable("MAPINFOTOOL", Log.DEBUG)) {// Log check to avoid
// string
// creation
Log.d("MAPINFOTOOL", "performed action:" + action + " on Info Tool");
}
if (action == MotionEvent.ACTION_DOWN) {
if (dragStarted && pointerCount > 1) {
setDragStarted(false);
Log.d("MAPINFOTOOL", "drag stopped");
isPinching = true;
}
}
if (action == MotionEvent.ACTION_MOVE) {
if (pointerCount > 1 || isPinching) {
setDragStarted(false);
Log.d("MAPINFOTOOL", "drag stopped");
return false;
}
// START DRAGGING
if (!dragStarted) {
startX = event.getX();
startY = event.getY();
}
setDragStarted(true);
Log.d("MAPINFOTOOL", "dragging started");
endX = event.getX();
endY = event.getY();
// Force redraw
view.redraw(false);
return true;
} else if (dragStarted && action == MotionEvent.ACTION_UP) {
if (pointerCount > 1) {
isPinching = true;
setDragStarted(false);
Log.d("MAPINFOTOOL", "drag stopped");
return false;
} else if (isPinching) {
isPinching = false;
setDragStarted(false);
Log.d("MAPINFOTOOL", "drag stopped");
return false;
}
endX = event.getX();
endY = event.getY();
if (endX == startX || endY == startY) {
setDragStarted(false);
isPinching = false;
return false;
}
// END DRAGGING EVENT
setDragStarted(false);
Log.d("MAPINFOTOOL", "drag stopped");
Log.d("MAPINFOTOOL", "start query layer");
// Use utility class to perform conversion from pixels to
// latitude/longitude.
if (pref.getString(
"selectionShape",
getActivity().getResources().getString(
R.string.preferences_selection_shape_default))
.equals(array[0])) {
double n = ConversionUtilities.convertFromPixelsToLatitude(
view, startY);
double w = ConversionUtilities.convertFromPixelsToLongitude(
view, startX);
double s = ConversionUtilities.convertFromPixelsToLatitude(
view, endY);
double e = ConversionUtilities.convertFromPixelsToLongitude(
view, endX);
Log.v("MAPINFOTOOL", "bbox:" + w + "," + s + "," + e + "," + n);
infoDialog(n, w, s, e, view.getMapViewPosition().getZoomLevel());
} else {
// Calculate radius and coordinates of circle
double y = ConversionUtilities.convertFromPixelsToLatitude(
view, startY);
double x = ConversionUtilities.convertFromPixelsToLongitude(
view, startX);
double fin_y = ConversionUtilities.convertFromPixelsToLatitude(
view, endY);
double fin_x = ConversionUtilities
.convertFromPixelsToLongitude(view, endX);
double rad_x = Math.abs(x - fin_x);
double rad_y = Math.abs(y - fin_y);
double radius = Math.sqrt((rad_x * rad_x) + (rad_y * rad_y));
Log.v("MAPINFOTOOL", "circle: center (" + x + "," + y
+ ") radius " + radius);
infoDialogCircle(x, y, radius, view.getMapViewPosition()
.getZoomLevel());
}
}
return false;
}
private void setDragStarted(boolean b) {
// if(dragStarted ^ b){
// if (dragStarted= true){
// this.view.thawOverlays();
// }else{
// this.view.freezeOverlays();
// }
// }
dragStarted = b;
}
/**
* Check if user start dragging
*
* @return
*/
public boolean isDragStarted() {
return dragStarted;
}
/**
* Return start x coordinate for selection
*
* @return
*/
public float getStartX() {
return startX;
}
/**
* Return start y coordinate for selection
*
* @return
*/
public float getStartY() {
return startY;
}
/**
* Return final x coordinate for selection
*
* @return
*/
public float getEndX() {
return endX;
}
/**
* Return final y coordinate for selection
*
* @return
*/
public float getEndY() {
return endY;
}
/**
* Return mode.
*
* @return
*/
public int getMode() {
return mode;
}
/**
* Set mode.
*
* @param mode
*/
public void setMode(int mode) {
this.mode = mode;
}
public Activity getActivity() {
return activity;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
}