diff --git a/brouter-routing-app/build.gradle b/brouter-routing-app/build.gradle index 58dde91..2a01ef2 100644 --- a/brouter-routing-app/build.gradle +++ b/brouter-routing-app/build.gradle @@ -93,6 +93,7 @@ android { dependencies { implementation 'androidx.appcompat:appcompat:1.3.1' + implementation "androidx.constraintlayout:constraintlayout:2.1.2" implementation project(':brouter-mapaccess') implementation project(':brouter-core') diff --git a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerActivity.java b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerActivity.java index 35eef43..286142e 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerActivity.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerActivity.java @@ -14,9 +14,11 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; +import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.os.StatFs; +import android.text.format.Formatter; import android.view.View; import android.widget.Button; import android.widget.TextView; @@ -38,6 +40,9 @@ public class BInstallerActivity extends Activity { private View mDownloadInfo; private TextView mDownloadInfoText; private Button mButtonDownloadCancel; + private Button mButtonDownload; + private TextView mSummaryInfo; + private View mSegmentsView; public static long getAvailableSpace(String baseDir) { StatFs stat = new StatFs(baseDir); @@ -57,8 +62,16 @@ public class BInstallerActivity extends Activity { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); setContentView(R.layout.activity_binstaller); + mSummaryInfo = findViewById(R.id.textViewSegmentSummary); + mSegmentsView = findViewById(R.id.view_segments); mBInstallerView = findViewById(R.id.BInstallerView); - mBInstallerView.setOnClickListener( + mBInstallerView.setOnSelectListener( + () -> { + updateDownloadButton(); + } + ); + mButtonDownload = findViewById(R.id.buttonDownload); + mButtonDownload.setOnClickListener( view -> { if (mBInstallerView.getSelectedTiles(MASK_DELETED_RD5).size() > 0) { showConfirmDelete(); @@ -80,6 +93,37 @@ public class BInstallerActivity extends Activity { scanExistingFiles(); } + private String getSegmentsPlural(int count) { + Resources res = getResources(); + return res.getQuantityString(R.plurals.numberOfSegments, count, count); + } + + private void updateDownloadButton() { + final ArrayList selectedTilesDownload = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5); + final ArrayList selectedTilesUpdate = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5); + final ArrayList selectedTilesDelete = mBInstallerView.getSelectedTiles(MASK_DELETED_RD5); + mSummaryInfo.setText(""); + + if (selectedTilesDelete.size() > 0) { + mButtonDownload.setText(getString(R.string.action_delete, getSegmentsPlural(selectedTilesDelete.size()))); + mButtonDownload.setEnabled(true); + } else if (selectedTilesDownload.size() > 0) { + long tileSize = 0; + for (int tileIndex : selectedTilesDownload) { + tileSize += BInstallerSizes.getRd5Size(tileIndex); + } + mButtonDownload.setText(getString(R.string.action_download, getSegmentsPlural(selectedTilesDownload.size()))); + mButtonDownload.setEnabled(true); + mSummaryInfo.setText(getString(R.string.summary_segments, Formatter.formatFileSize(this, tileSize), Formatter.formatFileSize(this, getAvailableSpace(mBaseDir.getAbsolutePath())))); + } else if (selectedTilesUpdate.size() > 0) { + mButtonDownload.setText(getString(R.string.action_update, getSegmentsPlural(selectedTilesUpdate.size()))); + mButtonDownload.setEnabled(true); + } else { + mButtonDownload.setText(getString(R.string.action_select)); + mButtonDownload.setEnabled(false); + } + } + private void deleteRawTracks() { File modeDir = new File(mBaseDir, "brouter/modes"); String[] fileNames = modeDir.list(); @@ -103,7 +147,7 @@ public class BInstallerActivity extends Activity { urlparts.add(baseNameForTile(i)); } - mBInstallerView.setVisibility(View.GONE); + mSegmentsView.setVisibility(View.GONE); mDownloadInfo.setVisibility(View.VISIBLE); downloadCanceled = false; mDownloadInfoText.setText(R.string.download_info_start); @@ -175,12 +219,6 @@ public class BInstallerActivity extends Activity { if (secondary != null) { scanExistingFiles(secondary); } - - long availableSize = -1; - try { - availableSize = getAvailableSpace(mBaseDir.getAbsolutePath()); - } catch (Exception e) { /* ignore */ } - mBInstallerView.setAvailableSize(availableSize); } private void scanExistingFiles(File dir) { @@ -249,7 +287,7 @@ public class BInstallerActivity extends Activity { String txt = intent.getStringExtra("txt"); boolean ready = intent.getBooleanExtra("ready", false); if (!ready) { - mBInstallerView.setVisibility(View.VISIBLE); + mSegmentsView.setVisibility(View.VISIBLE); mDownloadInfo.setVisibility(View.GONE); scanExistingFiles(); } 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 3f5f76d..8a41b41 100644 --- a/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java +++ b/brouter-routing-app/src/main/java/btools/routingapp/BInstallerView.java @@ -15,13 +15,10 @@ import android.view.MotionEvent; import android.view.ScaleGestureDetector; import android.view.View; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; -import btools.router.RoutingHelper; - public class BInstallerView extends View { public static final int MASK_SELECTED_RD5 = 1; public static final int MASK_DELETED_RD5 = 2; @@ -31,35 +28,18 @@ public class BInstallerView extends View { 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 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; - private int imgwOrig; - private int imghOrig; - private float scaleOrig; - private int imgw; - private int imgh; + Paint paintGrid = new Paint(); + Paint paintTiles = new Paint(); private float viewscale; private boolean tilesVisible = false; - private long availableSize; - private long totalSize = 0; - private long rd5Tiles = 0; - private long delTiles = 0; - private OnClickListener mOnClickListener; + private OnSelectListener mOnSelectListener; public BInstallerView(Context context, AttributeSet attrs) { super(context, attrs); - File baseDir = ConfigHelper.getBaseDir(getContext()); - segmentDir = new File(baseDir, "brouter/segments4"); - try { AssetManager assetManager = getContext().getAssets(); InputStream istr = assetManager.open("world.png"); @@ -70,12 +50,15 @@ 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()); } + public void setOnSelectListener(OnSelectListener listener) { + mOnSelectListener = listener; + } + private void setRatio(float ratio, float focusX, float focusY) { mat.postScale(ratio, ratio, focusX, focusY); fitBounds(); @@ -89,12 +72,20 @@ public class BInstallerView extends View { setRatio(ratio, focusX, focusY); } - public void setAvailableSize(long availableSize) { - this.availableSize = availableSize; - } - public void setTileStatus(int tileIndex, int tileMask) { tileStatus[tileIndex] |= tileMask; + if (mOnSelectListener != null) { + mOnSelectListener.onSelect(); + } + invalidate(); + } + + public void toggleTileStatus(int tileIndex, int tileMask) { + tileStatus[tileIndex] ^= tileMask; + if (mOnSelectListener != null) { + mOnSelectListener.onSelect(); + } + invalidate(); } public void clearAllTilesStatus(int tileMask) { @@ -104,6 +95,9 @@ public class BInstallerView extends View { tileStatus[tileIndex] ^= tileStatus[tileIndex] & tileMask; } } + if (mOnSelectListener != null) { + mOnSelectListener.onSelect(); + } invalidate(); } @@ -121,11 +115,6 @@ public class BInstallerView extends View { return selectedTiles; } - @Override - public void setOnClickListener(OnClickListener listener) { - mOnClickListener = listener; - } - private int gridPos2Tileindex(int ix, int iy) { return (35 - iy) * 72 + (ix >= 70 ? ix - 70 : ix + 2); } @@ -139,30 +128,22 @@ public class BInstallerView extends View { // get back the current image scale private float currentScale() { - testVector[1] = 1.f; + testVector[0] = 1.f; mat.mapVectors(testVector); - return testVector[1] / viewscale; + return testVector[0] / viewscale; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); - imgwOrig = getWidth(); - imghOrig = getHeight(); - int im = Math.max(imgwOrig, imghOrig); - - scaleOrig = im / 480.f; - - matText.preScale(scaleOrig, scaleOrig); - - imgw = (int) (imgwOrig / scaleOrig); - imgh = (int) (imghOrig / scaleOrig); + int imgwOrig = getWidth(); + int imghOrig = getHeight(); float scaleX = imgwOrig / ((float) bmp.getWidth()); float scaleY = imghOrig / ((float) bmp.getHeight()); - viewscale = Math.min(scaleX, scaleY); + viewscale = Math.max(scaleX, scaleY); mat.postScale(viewscale, viewscale); tilesVisible = false; @@ -180,93 +161,47 @@ public class BInstallerView extends View { float fh = ih / 36.f; if (tilesVisible) { - pnt_1.setColor(Color.GREEN); - pnt_1.setStyle(Paint.Style.STROKE); + paintGrid.setColor(Color.GREEN); + paintGrid.setStyle(Paint.Style.STROKE); for (int ix = 0; ix < 72; ix++) { for (int iy = 0; iy < 36; iy++) { int tidx = gridPos2Tileindex(ix, iy); int tilesize = BInstallerSizes.getRd5Size(tidx); if (tilesize > 0) { - canvas.drawRect(fw * ix, fh * (iy + 1), fw * (ix + 1), fh * iy, pnt_1); + canvas.drawRect(fw * ix, fh * (iy + 1), fw * (ix + 1), fh * iy, paintGrid); } } } - } - rd5Tiles = 0; - delTiles = 0; - totalSize = 0; - int mask2 = MASK_SELECTED_RD5 | MASK_DELETED_RD5 | MASK_INSTALLED_RD5; - int mask3 = mask2 | MASK_CURRENT_RD5; + int mask2 = MASK_SELECTED_RD5 | MASK_DELETED_RD5 | MASK_INSTALLED_RD5; + int mask3 = mask2 | MASK_CURRENT_RD5; - pnt_2.setStyle(Paint.Style.STROKE); - pnt_2.setColor(Color.GRAY); - pnt_2.setStrokeWidth(1); - drawSelectedTiles(canvas, pnt_2, fw, fh, MASK_INSTALLED_RD5, mask3, false, false, tilesVisible); - pnt_2.setColor(Color.BLUE); - pnt_2.setStrokeWidth(1); - drawSelectedTiles(canvas, pnt_2, fw, fh, MASK_INSTALLED_RD5 | MASK_CURRENT_RD5, mask3, false, false, tilesVisible); - pnt_2.setColor(Color.GREEN); - pnt_2.setStrokeWidth(2); - drawSelectedTiles(canvas, pnt_2, fw, fh, MASK_SELECTED_RD5, mask2, true, false, tilesVisible); - pnt_2.setColor(Color.YELLOW); - pnt_2.setStrokeWidth(2); - drawSelectedTiles(canvas, pnt_2, fw, fh, MASK_SELECTED_RD5 | MASK_INSTALLED_RD5, mask2, true, false, tilesVisible); - pnt_2.setColor(Color.RED); - pnt_2.setStrokeWidth(2); - drawSelectedTiles(canvas, pnt_2, fw, fh, MASK_DELETED_RD5 | MASK_INSTALLED_RD5, mask2, false, true, tilesVisible); - - canvas.setMatrix(matText); - - paint.setColor(Color.RED); - - long mb = 1024 * 1024; - - if (!this.tilesVisible) { - paint.setTextSize(35); - canvas.drawText("Touch region to zoom in!", 30, (imgh / 3) * 2, paint); - } - paint.setTextSize(20); - - - String totmb = ((totalSize + mb - 1) / mb) + " MB"; - String freemb = availableSize >= 0 ? ((availableSize + mb - 1) / mb) + " MB" : "?"; - canvas.drawText("Selected segments=" + rd5Tiles, 10, 25, paint); - canvas.drawText("Size=" + totmb + " Free=" + freemb, 10, 45, paint); - - - String btnText = null; - if (delTiles > 0) btnText = "Delete " + delTiles + " tiles"; - else if (rd5Tiles > 0) btnText = "Start Download"; - else if (this.tilesVisible && - rd5Tiles == 0 && - RoutingHelper.hasDirectoryAnyDatafiles(segmentDir)) btnText = "Update all"; - - if (btnText != null) { - paint.setStyle(Paint.Style.STROKE); - canvas.drawRect(imgw - btnw, imgh - btnh, imgw - 2, imgh - 2, paint); - paint.setStyle(Paint.Style.FILL); - canvas.drawText(btnText, imgw - btnw + 5, imgh - 10, paint); + paintTiles.setStyle(Paint.Style.STROKE); + paintTiles.setColor(Color.GRAY); + paintTiles.setStrokeWidth(1); + drawSelectedTiles(canvas, paintTiles, fw, fh, MASK_INSTALLED_RD5, mask3); + paintTiles.setColor(Color.BLUE); + paintTiles.setStrokeWidth(1); + drawSelectedTiles(canvas, paintTiles, fw, fh, MASK_INSTALLED_RD5 | MASK_CURRENT_RD5, mask3); + paintTiles.setColor(Color.GREEN); + paintTiles.setStrokeWidth(2); + drawSelectedTiles(canvas, paintTiles, fw, fh, MASK_SELECTED_RD5, mask2); + paintTiles.setColor(Color.YELLOW); + paintTiles.setStrokeWidth(2); + drawSelectedTiles(canvas, paintTiles, fw, fh, MASK_SELECTED_RD5 | MASK_INSTALLED_RD5, mask2); + paintTiles.setColor(Color.RED); + paintTiles.setStrokeWidth(2); + drawSelectedTiles(canvas, paintTiles, fw, fh, MASK_DELETED_RD5 | MASK_INSTALLED_RD5, mask2); } } - private void drawSelectedTiles(Canvas canvas, Paint pnt, float fw, float fh, int status, int mask, boolean doCount, boolean cntDel, boolean doDraw) { + private void drawSelectedTiles(Canvas canvas, Paint pnt, float fw, float fh, int status, int mask) { for (int ix = 0; ix < 72; ix++) for (int iy = 0; iy < 36; iy++) { int tidx = gridPos2Tileindex(ix, iy); if ((tileStatus[tidx] & mask) == status) { int tilesize = BInstallerSizes.getRd5Size(tidx); if (tilesize > 0) { - if (doCount) { - rd5Tiles++; - totalSize += BInstallerSizes.getRd5Size(tidx); - } - if (cntDel) { - delTiles++; - totalSize += BInstallerSizes.getRd5Size(tidx); - } - if (!doDraw) - continue; // draw cross canvas.drawLine(fw * ix, fh * iy, fw * (ix + 1), fh * (iy + 1), pnt); canvas.drawLine(fw * ix, fh * (iy + 1), fw * (ix + 1), fh * iy, pnt); @@ -310,36 +245,31 @@ public class BInstallerView extends View { return retVal || super.onTouchEvent(event); } + interface OnSelectListener { + void onSelect(); + } + class GestureListener extends GestureDetector.SimpleOnGestureListener { @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; - } - if (tilesVisible) { Matrix imat = new Matrix(); if (mat.invert(imat)) { - float[] touchpoint = {e.getX(), e.getY()}; - imat.mapPoints(touchpoint); + float[] touchPoint = {e.getX(), e.getY()}; + imat.mapPoints(touchPoint); - int tidx = tileIndex(touchpoint[0], touchpoint[1]); + int tidx = tileIndex(touchPoint[0], touchPoint[1]); if (tidx != -1) { if ((tileStatus[tidx] & MASK_SELECTED_RD5) != 0) { - tileStatus[tidx] ^= MASK_SELECTED_RD5; + toggleTileStatus(tidx, MASK_SELECTED_RD5); if ((tileStatus[tidx] & MASK_INSTALLED_RD5) != 0) { - tileStatus[tidx] |= MASK_DELETED_RD5; + setTileStatus(tidx, MASK_DELETED_RD5); } } else if ((tileStatus[tidx] & MASK_DELETED_RD5) != 0) { - tileStatus[tidx] ^= MASK_DELETED_RD5; + toggleTileStatus(tidx, MASK_DELETED_RD5); } else { - tileStatus[tidx] ^= MASK_SELECTED_RD5; + toggleTileStatus(tidx, MASK_SELECTED_RD5); } } } diff --git a/brouter-routing-app/src/main/res/layout/activity_binstaller.xml b/brouter-routing-app/src/main/res/layout/activity_binstaller.xml index ccaa634..11e4a84 100644 --- a/brouter-routing-app/src/main/res/layout/activity_binstaller.xml +++ b/brouter-routing-app/src/main/res/layout/activity_binstaller.xml @@ -1,13 +1,44 @@ - + android:layout_height="match_parent"> + + + +