Skip to content

Commit

Permalink
Merge branch 'improved_offset_display'
Browse files Browse the repository at this point in the history
  • Loading branch information
simonpoole committed Sep 23, 2023
2 parents 4f9afd3 + e12ea3a commit 13464c5
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import de.blau.android.Main;
import de.blau.android.Map;
import de.blau.android.MockTileServer;
import de.blau.android.Mode;
import de.blau.android.R;
import de.blau.android.TestUtils;
import de.blau.android.exception.OsmException;
Expand Down Expand Up @@ -96,6 +97,7 @@ public void teardown() {
if (main != null) {
TestUtils.zoomToNullIsland(logic, map);
TestUtils.resetOffsets(main.getMap());
logic.setMode(main, Mode.MODE_EASYEDIT);
main.deleteDatabase(TileLayerDatabase.DATABASE_NAME);
main.finish();
} else {
Expand Down Expand Up @@ -214,6 +216,7 @@ public void abortOffset() {
}
zoomLevel = map.getZoomLevel();
offset = tileLayerConfiguration.getOffset(zoomLevel);
assertNull(offset);
assertEquals(0D, offset.getDeltaLat(), 0.1E-4);
assertEquals(0D, offset.getDeltaLon(), 0.1E-4);
}
}
130 changes: 130 additions & 0 deletions src/androidTest/java/de/blau/android/imageryoffset/SaveResumeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package de.blau.android.imageryoffset;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.content.Context;
import androidx.lifecycle.Lifecycle.State;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import de.blau.android.App;
import de.blau.android.Logic;
import de.blau.android.Main;
import de.blau.android.Map;
import de.blau.android.MockTileServer;
import de.blau.android.R;
import de.blau.android.TestUtils;
import de.blau.android.exception.OsmException;
import de.blau.android.layer.LayerDialogTest;
import de.blau.android.osm.BoundingBox;
import de.blau.android.prefs.AdvancedPrefDatabase;
import de.blau.android.prefs.Preferences;
import de.blau.android.util.GeoMath;
import okhttp3.mockwebserver.MockWebServer;

/**
* 1st attempts at testing lifecycle related aspects
*
* @author simon
*
*/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SaveResumeTest {

Context context = null;
AdvancedPrefDatabase prefDB = null;
Main main = null;
UiDevice device = null;
Map map = null;
Logic logic = null;
MockWebServer tileServer = null;
ActivityScenario<Main> scenario = null;

@Rule
public ActivityScenarioRule<Main> activityScenarioRule = new ActivityScenarioRule<>(Main.class);

/**
* Pre-test setup
*/
@Before
public void setup() {
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
context = instrumentation.getTargetContext();
ActivityMonitor monitor = instrumentation.addMonitor(Main.class.getName(), null, false);
scenario = ActivityScenario.launch(Main.class);
main = (Main) instrumentation.waitForMonitorWithTimeout(monitor, 30000);
instrumentation.removeMonitor(monitor);
Preferences prefs = new Preferences(context);

tileServer = MockTileServer.setupTileServer(main, "ersatz_background.mbt", true);

map = main.getMap();
map.setPrefs(main, prefs);
logic = App.getLogic();
logic.setPrefs(prefs);
TestUtils.resetOffsets(main.getMap());
TestUtils.grantPermissons(device);
TestUtils.dismissStartUpDialogs(device, main);
TestUtils.stopEasyEdit(main);
TestUtils.zoomToNullIsland(logic, map);
main.invalidateOptionsMenu(); // to be sure that the menu entry is actually shown
}

/**
* Post-test teardown
*/
@After
public void teardown() {
try {
tileServer.close();
} catch (IOException e) {
// ignore
}

scenario.moveToState(State.DESTROYED);
}

/**
* Start the alignment mode then recreate
*/
@Test
public void startResumeMode() {
TestUtils.zoomToLevel(device, main, 18);
try {
BoundingBox bbox = GeoMath.createBoundingBoxForCoordinates(47.390339D, 8.38782D, 50D);
App.getLogic().getViewBox().setBorders(map, bbox);
map.setViewBox(App.getLogic().getViewBox());
map.invalidate();
try {
Thread.sleep(5000); // NOSONAR
} catch (InterruptedException e) {
}
main.invalidateOptionsMenu();
} catch (OsmException e) {
fail(e.getMessage());
}
UiObject2 menuButton = TestUtils.getLayerButton(device, "Vespucci Test", LayerDialogTest.MENU_BUTTON);
menuButton.click();
assertTrue(TestUtils.clickText(device, false, main.getString(R.string.menu_layers_background_align), true, false));
assertTrue(TestUtils.findText(device, false, main.getString(R.string.menu_tools_background_align)));
scenario.recreate();
assertTrue(TestUtils.findText(device, false, main.getString(R.string.menu_tools_background_align), 10000));
}
}
47 changes: 19 additions & 28 deletions src/main/java/de/blau/android/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
import de.blau.android.filter.Filter;
import de.blau.android.gpx.Track;
import de.blau.android.imageryoffset.ImageryAlignmentActionModeCallback;
import de.blau.android.imageryoffset.Offset;
import de.blau.android.layer.MapViewLayer;
import de.blau.android.osm.BoundingBox;
import de.blau.android.osm.DiscardedTags;
Expand Down Expand Up @@ -102,7 +101,6 @@
import de.blau.android.prefs.Preferences;
import de.blau.android.resources.DataStyle;
import de.blau.android.resources.DataStyle.FeatureStyle;
import de.blau.android.resources.TileLayerSource;
import de.blau.android.tasks.Note;
import de.blau.android.tasks.Task;
import de.blau.android.tasks.TransferTasks;
Expand Down Expand Up @@ -579,10 +577,7 @@ public void zoom(final boolean zoomIn) {
} else {
viewBox.zoomOut();
}
DataStyle.updateStrokes(strokeWidth(viewBox.getWidth()));
if (rotatingWay) {
showCrosshairsForCentroid();
}
onZoomChanged(map);
map.postInvalidate();
}

Expand All @@ -594,9 +589,20 @@ public void zoom(final boolean zoomIn) {
*/
public void setZoom(Map map, int z) {
viewBox.setZoom(map, z);
onZoomChanged(map);
}

/**
* Call this if zoom has changed
*
* @param map the current Map object
*/
private void onZoomChanged(@NonNull Map map) {
DataStyle.updateStrokes(strokeWidth(viewBox.getWidth()));
if (rotatingWay) {
showCrosshairsForCentroid();
} else if (mode == Mode.MODE_ALIGN_BACKGROUND) {
performBackgroundOffset((Main) map.getContext(), map.getZoomLevel(), 0, 0);
}
}

Expand Down Expand Up @@ -1520,13 +1526,11 @@ synchronized void handleTouchEventMove(@NonNull Main main, final float absoluteX
startY = absoluteY;
startX = absoluteX;
main.getEasyEditManager().invalidate(); // if we are in an action mode update menubar
} else if (mode == Mode.MODE_ALIGN_BACKGROUND) {
performBackgroundOffset(main, map.getZoomLevel(), relativeX, relativeY);
} else {
if (mode == Mode.MODE_ALIGN_BACKGROUND) {
performBackgroundOffset(main, relativeX, relativeY);
} else {
performTranslation(map, relativeX, relativeY);
main.getEasyEditManager().invalidateOnDownload();
}
performTranslation(map, relativeX, relativeY);
main.getEasyEditManager().invalidateOnDownload();
}
invalidateMap();
}
Expand Down Expand Up @@ -1592,27 +1596,14 @@ private void performTranslation(@NonNull Map map, final float screenTransX, fina
* Converts screen-coords to gps-coords and offsets background layer.
*
* @param main current instance of Main
* @param zoomLevel the current zoom level
* @param screenTransX Movement on the screen.
* @param screenTransY Movement on the screen.
*/
private void performBackgroundOffset(@NonNull Main main, final float screenTransX, final float screenTransY) {
private void performBackgroundOffset(@NonNull Main main, int zoomLevel, final float screenTransX, final float screenTransY) {
ImageryAlignmentActionModeCallback callback = main.getImageryAlignmentActionModeCallback();
if (callback != null) {
TileLayerSource osmts = callback.getLayerSource();
int height = map.getHeight();
int lon = xToLonE7(screenTransX);
int lat = yToLatE7(height - screenTransY);
int relativeLon = lon - viewBox.getLeft();
int relativeLat = lat - viewBox.getBottom();

double lonOffset = 0d;
double latOffset = 0d;
Offset o = osmts.getOffset(map.getZoomLevel());
if (o != null) {
lonOffset = o.getDeltaLon();
latOffset = o.getDeltaLat();
}
osmts.setOffset(map.getZoomLevel(), lonOffset - relativeLon / 1E7d, latOffset - relativeLat / 1E7d);
callback.setOffset(zoomLevel, screenTransX, screenTransY);
} else {
Log.e(DEBUG_TAG, "performBackgroundOffset callback null");
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/de/blau/android/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,8 @@ protected void onResume() {
} else if (mode.elementsEditable()) {
// de-select everything
logic.deselectAll();
} else if (mode == Mode.MODE_ALIGN_BACKGROUND) {
ImageryAlignmentActionModeCallback.restart(Main.this);
}
Intent intent = getIntent();
if (rcData != null || geoData != null || contentUri != null || shortcutExtras != null || (intent != null && intent.getAction() != null)) {
Expand Down Expand Up @@ -1419,6 +1421,9 @@ protected void onPause() {

// always save editing state
App.getLogic().saveEditingState(this);
if (imageryAlignmentActionModeCallback != null) {
imageryAlignmentActionModeCallback.saveState();
}
// save tag clipboard
App.getTagClipboard(this).save(this);
super.onPause();
Expand Down
47 changes: 29 additions & 18 deletions src/main/java/de/blau/android/Map.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
Expand All @@ -21,6 +20,7 @@
import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import android.text.DynamicLayout;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
Expand All @@ -29,8 +29,8 @@
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import de.blau.android.exception.OsmException;
import de.blau.android.imageryoffset.ImageryAlignmentActionModeCallback;
import de.blau.android.imageryoffset.ImageryOffsetUtils;
import de.blau.android.imageryoffset.Offset;
import de.blau.android.layer.AttributionInterface;
import de.blau.android.layer.ClickableInterface;
import de.blau.android.layer.LayerConfig;
Expand All @@ -47,7 +47,6 @@
import de.blau.android.prefs.AdvancedPrefDatabase;
import de.blau.android.prefs.Preferences;
import de.blau.android.resources.DataStyle;
import de.blau.android.resources.DataStyle.FeatureStyle;
import de.blau.android.resources.TileLayerSource;
import de.blau.android.resources.TileLayerSource.TileType;
import de.blau.android.services.TrackerService;
Expand Down Expand Up @@ -139,8 +138,6 @@ public class Map extends View implements IMapView {
private Location displayLocation = null;
private boolean isFollowingGPS = false;

private Paint textPaint;

/**
* support for display a crosshairs at a position
*/
Expand All @@ -162,6 +159,9 @@ public class Map extends View implements IMapView {
private Paint gpsAccuracyPaint;
private Paint boxPaint;

private int distance2side;
private int offsetPos;

private long timeToStale = 60 * ONE_SECOND_IN_NS;

private TrackerService tracker = null;
Expand Down Expand Up @@ -875,16 +875,16 @@ private void paintStats(@NonNull final Canvas canvas, final float fps) {
* @param canvas canvas to draw on
*/
private void paintZoomAndOffset(@NonNull final Canvas canvas) {
int pos = ThemeUtils.getActionBarHeight(context) + 5 + (int) de.blau.android.layer.grid.MapOverlay.LONGTICKS_DP * 3;
Offset o = ((Main) context).getImageryAlignmentActionModeCallback().getLayerSource().getOffset(zoomLevel);
String text = context.getString(R.string.zoom_and_offset, zoomLevel, o != null ? String.format(Locale.US, "%.5f", o.getDeltaLon()) : "0.00000",
o != null ? String.format(Locale.US, "%.5f", o.getDeltaLat()) : "0.00000");
float textSize = textPaint.getTextSize();
float textWidth = textPaint.measureText(text);
FontMetrics fm = textPaint.getFontMetrics();
float yOffset = pos + textSize;
canvas.drawRect(5, yOffset + fm.bottom, 5 + textWidth, yOffset - textSize, labelBackground);
canvas.drawText(text, 5, pos + textSize, textPaint);
ImageryAlignmentActionModeCallback callback = ((Main) context).getImageryAlignmentActionModeCallback();
if (callback != null) {
DynamicLayout layout = callback.getZoomAndOffsetLayout();
canvas.save();
canvas.translate(distance2side, offsetPos);
canvas.drawRect(0, 0, layout.getWidth(), layout.getHeight(), labelBackground);
canvas.translate((rtlLayout() ? -1f : 1f) * distance2side, 0); // padding
layout.draw(canvas);
canvas.restore();
}
}

/**
Expand Down Expand Up @@ -1093,17 +1093,19 @@ public static boolean activeOverlay(@NonNull String layerId) {
public void updateStyle() {
// changes when profile changes
labelBackground = DataStyle.getInternal(DataStyle.LABELTEXT_BACKGROUND).getPaint();
FeatureStyle fs = DataStyle.getInternal(DataStyle.LABELTEXT_NORMAL);
textPaint = fs.getPaint();
gpsPosFollowPaint = DataStyle.getInternal(DataStyle.GPS_POS_FOLLOW).getPaint();
gpsPosPaint = DataStyle.getInternal(DataStyle.GPS_POS).getPaint();
gpsPosFollowPaintStale = DataStyle.getInternal(DataStyle.GPS_POS_FOLLOW_STALE).getPaint();
gpsPosPaintStale = DataStyle.getInternal(DataStyle.GPS_POS_STALE).getPaint();
gpsAccuracyPaint = DataStyle.getInternal(DataStyle.GPS_ACCURACY).getPaint();
boxPaint = DataStyle.getInternal(DataStyle.VIEWBOX).getPaint();
for (MapViewLayer layer : getLayers(LayerType.OSMDATA, null)) {
((de.blau.android.layer.data.MapOverlay) layer).updateStyle();
((de.blau.android.layer.data.MapOverlay<?>) layer).updateStyle();
}
// offset display positioning
distance2side = (int) Density.dpToPx(getContext(), de.blau.android.layer.grid.MapOverlay.DISTANCE2SIDE_DP);
int longTicks = (int) Density.dpToPx(getContext(), de.blau.android.layer.grid.MapOverlay.LONGTICKS_DP);
offsetPos = ThemeUtils.getActionBarHeight(context) + distance2side + longTicks;
}

/**
Expand Down Expand Up @@ -1289,4 +1291,13 @@ void setTracker(@Nullable TrackerService tracker) {
public TrackerService getTracker() {
return this.tracker;
}

/**
* Check if we have RTL layout
*
* @return true if RTL
*/
public boolean rtlLayout() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1 && getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}
}
Loading

0 comments on commit 13464c5

Please sign in to comment.