diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java index c1ca7df..3f5f76d 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java @@ -1,5 +1,6 @@ package btools.routingapp; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; @@ -9,7 +10,9 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.util.AttributeSet; +import android.view.GestureDetector; import android.view.MotionEvent; +import android.view.ScaleGestureDetector; import android.view.View; import java.io.File; @@ -24,25 +27,25 @@ public class BInstallerView extends View { public static final int MASK_DELETED_RD5 = 2; public static final int MASK_INSTALLED_RD5 = 4; public static final int MASK_CURRENT_RD5 = 8; + private static final float SCALE_GRID_VISIBLE = 3; + private final Bitmap bmp; + private final float[] testVector = new float[2]; + private final int[] tileStatus; private final File segmentDir; private final Matrix mat; - private final Bitmap bmp; - private final int[] tileStatus; - private final float[] testVector = new float[2]; private final Matrix matText; + private final GestureDetector mGestureDetector; + private final ScaleGestureDetector mScaleGestureDetector; Paint pnt_1 = new Paint(); Paint pnt_2 = new Paint(); Paint paint = new Paint(); int btnh = 40; int btnw = 160; - float tx, ty; private int imgwOrig; private int imghOrig; private float scaleOrig; private int imgw; private int imgh; - private float lastDownX; - private float lastDownY; private float viewscale; private boolean tilesVisible = false; private long availableSize; @@ -69,6 +72,21 @@ public class BInstallerView extends View { tileStatus = new int[72 * 36]; matText = new Matrix(); mat = new Matrix(); + mGestureDetector = new GestureDetector(context, new GestureListener()); + mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener()); + } + + private void setRatio(float ratio, float focusX, float focusY) { + mat.postScale(ratio, ratio, focusX, focusY); + fitBounds(); + tilesVisible = currentScale() >= SCALE_GRID_VISIBLE; + + invalidate(); + } + + private void setScale(float scale, float focusX, float focusY) { + float ratio = scale / currentScale(); + setRatio(ratio, focusX, focusY); } public void setAvailableSize(long availableSize) { @@ -142,9 +160,9 @@ public class BInstallerView extends View { imgh = (int) (imghOrig / scaleOrig); float scaleX = imgwOrig / ((float) bmp.getWidth()); - float scaley = imghOrig / ((float) bmp.getHeight()); + float scaleY = imghOrig / ((float) bmp.getHeight()); - viewscale = Math.min(scaleX, scaley); + viewscale = Math.min(scaleX, scaleY); mat.postScale(viewscale, viewscale); tilesVisible = false; @@ -260,120 +278,55 @@ public class BInstallerView extends View { } } + private void fitBounds() { + float[] srcPoints = new float[]{ + 0, 0, + bmp.getWidth(), bmp.getHeight() + }; + float[] dstPoints = new float[srcPoints.length]; + float transX = 0; + float transY = 0; + mat.mapPoints(dstPoints, srcPoints); + if (dstPoints[0] > 0) { + transX = -dstPoints[0]; + } else if (dstPoints[2] < getWidth()) { + transX = getWidth() - dstPoints[2]; + } + if (dstPoints[1] > 0) { + transY = -dstPoints[1]; + } else if (dstPoints[3] < getHeight()) { + transY = getHeight() - dstPoints[3]; + } + if (transX != 0 || transY != 0) { + mat.postTranslate(transX, transY); + } + } + + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { + boolean retVal = mScaleGestureDetector.onTouchEvent(event); + retVal = mGestureDetector.onTouchEvent(event) || retVal; + return retVal || super.onTouchEvent(event); + } - // get masked (not specific to a pointer) action - int maskedAction = event.getActionMasked(); + class GestureListener extends GestureDetector.SimpleOnGestureListener { - switch (maskedAction) { - - case MotionEvent.ACTION_DOWN: - case MotionEvent.ACTION_POINTER_DOWN: { - lastDownX = event.getX(); - lastDownY = event.getY(); - - break; + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + // Download Button + if ((delTiles > 0 || rd5Tiles >= 0) && e.getX() > imgwOrig - btnw * scaleOrig && e.getY() > imghOrig - btnh * scaleOrig) { + if (mOnClickListener != null) { + mOnClickListener.onClick(null); + } + invalidate(); + return true; } - case MotionEvent.ACTION_MOVE: { // a pointer was moved - - int np = event.getPointerCount(); - int nh = event.getHistorySize(); - if (nh == 0) break; - - float x0 = event.getX(0); - float y0 = event.getY(0); - float hx0 = event.getHistoricalX(0, 0); - float hy0 = event.getHistoricalY(0, 0); - - if (np > 1) // multi-touch - { - float x1 = event.getX(1); - float y1 = event.getY(1); - float hx1 = event.getHistoricalX(1, 0); - float hy1 = event.getHistoricalY(1, 0); - - float r = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); - float hr = (float) Math.sqrt((hx1 - hx0) * (hx1 - hx0) + (hy1 - hy0) * (hy1 - hy0)); - - if (hr > 0.) { - float ratio = r / hr; - - float mx = (x1 + x0) / 2.f; - float my = (y1 + y0) / 2.f; - - float scale = currentScale(); - float newscale = scale * ratio; - - if (newscale > 10.f) ratio *= (10.f / newscale); - if (newscale < 0.5f) ratio *= (0.5f / newscale); - - mat.postScale(ratio, ratio, mx, my); - - mat.postScale(ratio, ratio, mx, my); - - boolean tilesv = currentScale() >= 3.f; - if (tilesVisible && !tilesv) { - clearAllTilesStatus(MASK_SELECTED_RD5 | MASK_DELETED_RD5); - } - tilesVisible = tilesv; - } - - break; - } - mat.postTranslate(x0 - hx0, y0 - hy0); - - break; - } - case MotionEvent.ACTION_UP: - - long downTime = event.getEventTime() - event.getDownTime(); - - if (downTime < 5 || downTime > 500) { - break; - } - - if (Math.abs(lastDownX - event.getX()) > 10 || Math.abs(lastDownY - event.getY()) > 10) { - break; - } - - // download button? - if ((delTiles > 0 || rd5Tiles >= 0) && event.getX() > imgwOrig - btnw * scaleOrig && event.getY() > imghOrig - btnh * scaleOrig) { - if (rd5Tiles == 0) { - for (int ix = 0; ix < 72; ix++) { - for (int iy = 0; iy < 36; iy++) { - int tidx = gridPos2Tileindex(ix, iy); - if (tidx != -1) { - if ((tileStatus[tidx] & MASK_INSTALLED_RD5) != 0) { - tileStatus[tidx] |= MASK_SELECTED_RD5; - } - } - - } - } - } - if (mOnClickListener != null) { - mOnClickListener.onClick(null); - } - invalidate(); - break; - } - - if (!tilesVisible) { - float scale = currentScale(); - if (scale > 0f && scale < 5f) { - float ratio = 5f / scale; - mat.postScale(ratio, ratio, event.getX(), event.getY()); - tilesVisible = true; - } - break; - } + if (tilesVisible) { Matrix imat = new Matrix(); if (mat.invert(imat)) { - float[] touchpoint = new float[2]; - touchpoint[0] = event.getX(); - touchpoint[1] = event.getY(); + float[] touchpoint = {e.getX(), e.getY()}; imat.mapPoints(touchpoint); int tidx = tileIndex(touchpoint[0], touchpoint[1]); @@ -389,23 +342,52 @@ public class BInstallerView extends View { tileStatus[tidx] ^= MASK_SELECTED_RD5; } } - - tx = touchpoint[0]; - ty = touchpoint[1]; } - - - break; - case MotionEvent.ACTION_POINTER_UP: - case MotionEvent.ACTION_CANCEL: { - // TODO use data - break; + invalidate(); } + return true; } - invalidate(); - return true; + @Override + public boolean onDoubleTap(MotionEvent e) { + if (!tilesVisible) { + setScale(5, e.getX(), e.getY()); + } else { + setScale(1, e.getX(), e.getY()); + } + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + mat.postTranslate(-distanceX, -distanceY); + fitBounds(); + invalidate(); + return true; + } } + class ScaleGestureListener implements ScaleGestureDetector.OnScaleGestureListener { + + @Override + public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) { + return true; + } + + @Override + public boolean onScale(ScaleGestureDetector scaleGestureDetector) { + float focusX = scaleGestureDetector.getFocusX(); + float focusY = scaleGestureDetector.getFocusY(); + float ratio = scaleGestureDetector.getScaleFactor(); + + setRatio(ratio, focusX, focusY); + + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) { + } + } }