/* * Geopaparazzi - Digital field mapping on Android based devices * Copyright (C) 2016 HydroloGIS (www.hydrologis.com) * * 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 eu.geopaparazzi.core.maptools.tools; import android.app.ProgressDialog; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.os.AsyncTask; import android.view.MotionEvent; import android.widget.Toast; import com.vividsolutions.jts.geom.Geometry; import org.mapsforge.android.maps.MapView; import org.mapsforge.android.maps.Projection; import org.mapsforge.core.model.GeoPoint; import java.util.ArrayList; import java.util.List; import eu.geopaparazzi.library.style.ToolColors; import eu.geopaparazzi.library.database.GPLog; import eu.geopaparazzi.library.features.EditManager; import eu.geopaparazzi.library.features.Feature; import eu.geopaparazzi.library.features.ILayer; import eu.geopaparazzi.library.style.ColorUtilities; import eu.geopaparazzi.library.util.GPDialogs; import eu.geopaparazzi.library.util.LibraryConstants; import eu.geopaparazzi.spatialite.database.spatial.core.layers.SpatialVectorTableLayer; import eu.geopaparazzi.spatialite.database.spatial.core.tables.SpatialVectorTable; import eu.geopaparazzi.spatialite.database.spatial.util.SpatialiteUtilities; import eu.geopaparazzi.core.R; import eu.geopaparazzi.core.maptools.FeatureUtilities; import eu.geopaparazzi.core.maptools.MapTool; import eu.geopaparazzi.core.mapview.overlays.SliderDrawProjection; import jsqlite.Exception; import static java.lang.Math.abs; import static java.lang.Math.round; /** * A tool to select data. * * @author Andrea Antonello (www.hydrologis.com) */ public class SelectionTool extends MapTool { private static final int TOUCH_BOX_THRES = 10; private final Paint selectRectPaintStroke = new Paint(); private final Paint selectRectPaintFill = new Paint(); private final Rect rect = new Rect(); private float lastX = -1; private float lastY = -1; private final Point tmpP = new Point(); private final Point startP = new Point(); private float left; private float right; private float bottom; private float top; private ProgressDialog infoProgressDialog; private SliderDrawProjection editingViewProjection; /** * Constructor. * * @param mapView the mapview reference. */ public SelectionTool(MapView mapView) { super(mapView); editingViewProjection = new SliderDrawProjection(mapView, EditManager.INSTANCE.getEditingView()); int stroke = ColorUtilities.toColor(ToolColors.selection_stroke.getHex()); int fill = ColorUtilities.toColor(ToolColors.selection_fill.getHex()); selectRectPaintFill.setAntiAlias(true); selectRectPaintFill.setColor(fill); selectRectPaintFill.setAlpha(80); selectRectPaintFill.setStyle(Paint.Style.FILL); selectRectPaintStroke.setAntiAlias(true); selectRectPaintStroke.setStrokeWidth(1.5f); selectRectPaintStroke.setColor(stroke); selectRectPaintStroke.setStyle(Paint.Style.STROKE); } public void activate() { if (mapView != null) mapView.setClickable(false); } public void onToolDraw(Canvas canvas) { canvas.drawRect(rect, selectRectPaintFill); canvas.drawRect(rect, selectRectPaintStroke); } public boolean onToolTouchEvent(MotionEvent event) { if (mapView == null || mapView.isClickable()) { return false; } Projection pj = editingViewProjection; // handle drawing float currentX = event.getX(); float currentY = event.getY(); int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: GeoPoint startGeoPoint = pj.fromPixels(round(currentX), round(currentY)); pj.toPixels(startGeoPoint, startP); lastX = currentX; lastY = currentY; break; case MotionEvent.ACTION_MOVE: float dx = currentX - lastX; float dy = currentY - lastY; if (abs(dx) < 1 && abs(dy) < 1) { lastX = currentX; lastY = currentY; return true; } GeoPoint currentGeoPoint = pj.fromPixels(round(currentX), round(currentY)); pj.toPixels(currentGeoPoint, tmpP); left = Math.min(tmpP.x, startP.x); right = Math.max(tmpP.x, startP.x); bottom = Math.max(tmpP.y, startP.y); top = Math.min(tmpP.y, startP.y); rect.set((int) left, (int) top, (int) right, (int) bottom); EditManager.INSTANCE.invalidateEditingView(); break; case MotionEvent.ACTION_UP: float deltaY = abs(top - bottom); float deltaX = abs(right - left); if (deltaX > TOUCH_BOX_THRES && deltaY > TOUCH_BOX_THRES) { GeoPoint ul = pj.fromPixels((int) left, (int) top); GeoPoint lr = pj.fromPixels((int) right, (int) bottom); select(ul.getLatitude(), ul.getLongitude(), lr.getLatitude(), lr.getLongitude()); } break; } return true; } public void disable() { if (mapView != null) { mapView.setClickable(true); mapView = null; } } private void select(final double n, final double w, final double s, final double e) { ILayer editLayer = EditManager.INSTANCE.getEditLayer(); SpatialVectorTableLayer layer = (SpatialVectorTableLayer) editLayer; final SpatialVectorTable spatialVectorTable = layer.getSpatialVectorTable(); final Context context = EditManager.INSTANCE.getEditingView().getContext(); infoProgressDialog = new ProgressDialog(context); infoProgressDialog.setCancelable(true); infoProgressDialog.setTitle("SELECT"); infoProgressDialog.setMessage("Selecting features..."); infoProgressDialog.setCancelable(false); infoProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); infoProgressDialog.setIndeterminate(true); infoProgressDialog.show(); // TODO fix this asynctask new AsyncTask<String, Integer, String>() { private List<Feature> features = new ArrayList<>(); protected String doInBackground(String... params) { try { features.clear(); double north = n; double south = s; if (n - s == 0) { south = n - 1; } double west = w; double east = e; if (e - w == 0) { west = e - 1; } String query = SpatialiteUtilities.getBboxIntersectingFeaturesQuery(LibraryConstants.SRID_WGS84_4326, spatialVectorTable, north, south, east, west); features = FeatureUtilities.buildFeatures(query, spatialVectorTable); return ""; } catch (Exception e) { GPLog.error(this, null, e); //$NON-NLS-1$ return "ERROR: " + e.getLocalizedMessage(); } } protected void onProgressUpdate(Integer... progress) { // on UI thread! if (infoProgressDialog != null && infoProgressDialog.isShowing()) infoProgressDialog.incrementProgressBy(progress[0]); } protected void onPostExecute(String response) { // on UI thread! GPDialogs.dismissProgressDialog(infoProgressDialog); if (response.startsWith("ERROR")) { GPDialogs.warningDialog(context, response, null); } else if (response.startsWith("CANCEL")) { return; } else { if (features.size() > 0) { try { int geomsCount = 0; for (Feature feature : features) { Geometry geometry = FeatureUtilities.getGeometry(feature); if (geometry != null) geomsCount = geomsCount + geometry.getNumGeometries(); } if (spatialVectorTable.isPolygon()) { GPDialogs.toast(context, String.format(context.getString(R.string.selected_features_in_layer), features.size(), geomsCount), Toast.LENGTH_SHORT); PolygonOnSelectionToolGroup selectionGroup = new PolygonOnSelectionToolGroup(mapView, features); EditManager.INSTANCE.setActiveToolGroup(selectionGroup); } else if (spatialVectorTable.isLine()) { GPDialogs.toast(context, String.format(context.getString(R.string.selected_line_features_in_layer), features.size(), geomsCount), Toast.LENGTH_SHORT); LineOnSelectionToolGroup selectionGroup = new LineOnSelectionToolGroup(mapView, features); EditManager.INSTANCE.setActiveToolGroup(selectionGroup); } else if (spatialVectorTable.isPoint()) { GPDialogs.toast(context, String.format(context.getString(R.string.selected_point_features_in_layer), features.size(), geomsCount), Toast.LENGTH_SHORT); PointOnSelectionToolGroup selectionGroup = new PointOnSelectionToolGroup(mapView, features); EditManager.INSTANCE.setActiveToolGroup(selectionGroup); } } catch (java.lang.Exception e) { GPLog.error(this, null, e); //$NON-NLS-1$ } } else { rect.setEmpty(); EditManager.INSTANCE.invalidateEditingView(); } } } }.execute((String) null); } @Override public void onViewChanged() { // ignore } }