diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 69f4c6506e..6e56121d61 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,7 @@ --> + Distance by tap Routing could avoid strong uphills. Application restart required to apply some settings. On pause diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java index 442e2f41a1..8c0d09f150 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java @@ -57,7 +57,8 @@ import net.osmand.plus.views.layers.POIMapLayer; import net.osmand.plus.views.layers.PointLocationLayer; import net.osmand.plus.views.layers.PointNavigationLayer; import net.osmand.plus.views.layers.RouteLayer; -import net.osmand.plus.views.layers.RulerControlLayer; +import net.osmand.plus.views.layers.RadiusRulerControlLayer; +import net.osmand.plus.views.layers.DistanceRulerControlLayer; import net.osmand.plus.views.layers.TransportStopsLayer; import net.osmand.plus.views.mapwidgets.MapWidgetRegistry; @@ -82,7 +83,8 @@ public class MapActivityLayers { private FavouritesLayer mFavouritesLayer; private TransportStopsLayer transportStopsLayer; private PointLocationLayer locationLayer; - private RulerControlLayer rulerControlLayer; + private RadiusRulerControlLayer radiusRulerControlLayer; + private DistanceRulerControlLayer distanceRulerControlLayer; private PointNavigationLayer navigationLayer; private MapMarkersLayer mapMarkersLayer; private ImpassableRoadsLayer impassableRoadsLayer; @@ -94,7 +96,7 @@ public class MapActivityLayers { private DownloadedRegionsLayer downloadedRegionsLayer; private MapWidgetRegistry mapWidgetRegistry; private MeasurementToolLayer measurementToolLayer; - + private StateChangedListener transparencyListener; public MapActivityLayers(MapActivity activity) { @@ -168,9 +170,12 @@ public class MapActivityLayers { // 7.5 Impassible roads impassableRoadsLayer = new ImpassableRoadsLayer(activity); mapView.addLayer(impassableRoadsLayer, 7.5f); - // 7.8 ruler control layer - rulerControlLayer = new RulerControlLayer(activity); - mapView.addLayer(rulerControlLayer, 7.8f); + // 7.8 radius ruler control layer + radiusRulerControlLayer = new RadiusRulerControlLayer(activity); + mapView.addLayer(radiusRulerControlLayer, 7.8f); + // 7.9 ruler by tap control layer + distanceRulerControlLayer = new DistanceRulerControlLayer(activity); + mapView.addLayer(distanceRulerControlLayer, 7.9f); // 8. context menu layer // 9. map info layer mapInfoLayer = new MapInfoLayer(activity, routeLayer); @@ -302,7 +307,7 @@ public class MapActivityLayers { public void onClick(DialogInterface dialog, int which) { for (int i = 0; i < listAdapter.getCount(); i++) { ContextMenuItem item = listAdapter.getItem(i); - PoiUIFilter filter = list.get(i); + PoiUIFilter filter = list.get(i); if (item.getSelected()) { if (filter.isStandardFilter()) { filter.removeUnsavedFilterByName(); @@ -567,7 +572,7 @@ public class MapActivityLayers { } return app.getDaynightHelper().isNightModeForMapControls(); } - + private int getThemeRes(OsmandApplication app) { return isNightMode(app) ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; } @@ -612,8 +617,12 @@ public class MapActivityLayers { return locationLayer; } - public RulerControlLayer getRulerControlLayer() { - return rulerControlLayer; + public RadiusRulerControlLayer getRadiusRulerControlLayer() { + return radiusRulerControlLayer; + } + + public DistanceRulerControlLayer getDistanceRulerControlLayer() { + return distanceRulerControlLayer; } public MapInfoLayer getMapInfoLayer() { @@ -643,7 +652,7 @@ public class MapActivityLayers { public POIMapLayer getPoiMapLayer() { return poiMapLayer; } - + public TransportStopsLayer getTransportStopsLayer() { return transportStopsLayer; } diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java b/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java index efb02fefc0..3694f59add 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java @@ -41,7 +41,7 @@ import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_NEXT_NEX import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_NEXT_TURN; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_NEXT_TURN_SMALL; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_PLAIN_TIME; -import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_RULER; +import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_RADIUS_RULER; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_SPEED; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_TIME; @@ -188,13 +188,13 @@ public class ApplicationMode { private static void initRegVisibility() { // DEFAULT, CAR, BICYCLE, PEDESTRIAN, PUBLIC_TRANSPORT, BOAT, AIRCRAFT, SKI, TRUCK - ApplicationMode[] exceptDefault = new ApplicationMode[] {CAR, BICYCLE, PEDESTRIAN, PUBLIC_TRANSPORT, BOAT, AIRCRAFT, SKI, TRUCK, MOTORCYCLE}; + ApplicationMode[] exceptDefault = new ApplicationMode[]{CAR, BICYCLE, PEDESTRIAN, PUBLIC_TRANSPORT, BOAT, AIRCRAFT, SKI, TRUCK, MOTORCYCLE}; ApplicationMode[] all = null; - ApplicationMode[] none = new ApplicationMode[] {}; + ApplicationMode[] none = new ApplicationMode[]{}; // left - ApplicationMode[] navigationSet1 = new ApplicationMode[] {CAR, BICYCLE, BOAT, SKI, TRUCK, MOTORCYCLE}; - ApplicationMode[] navigationSet2 = new ApplicationMode[] {PEDESTRIAN, PUBLIC_TRANSPORT, AIRCRAFT}; + ApplicationMode[] navigationSet1 = new ApplicationMode[]{CAR, BICYCLE, BOAT, SKI, TRUCK, MOTORCYCLE}; + ApplicationMode[] navigationSet2 = new ApplicationMode[]{PEDESTRIAN, PUBLIC_TRANSPORT, AIRCRAFT}; regWidgetVisibility(WIDGET_NEXT_TURN, navigationSet1); regWidgetVisibility(WIDGET_NEXT_TURN_SMALL, navigationSet2); @@ -226,7 +226,7 @@ public class ApplicationMode { regWidgetAvailability(WIDGET_GPS_INFO, all); regWidgetAvailability(WIDGET_BATTERY, all); regWidgetAvailability(WIDGET_BEARING, all); - regWidgetAvailability(WIDGET_RULER, all); + regWidgetAvailability(WIDGET_RADIUS_RULER, all); regWidgetAvailability(WIDGET_PLAIN_TIME, all); // top diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index 9652fc3bad..50c55e316c 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -54,7 +54,7 @@ import net.osmand.plus.rastermaps.LayerTransparencySeekbarMode; import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.routing.RouteProvider.RouteService; import net.osmand.plus.srtmplugin.TerrainMode; -import net.osmand.plus.views.layers.RulerControlLayer.RulerMode; +import net.osmand.plus.views.layers.RadiusRulerControlLayer.RadiusRulerMode; import net.osmand.plus.voice.CommandPlayer; import net.osmand.plus.wikipedia.WikiArticleShowImages; import net.osmand.render.RenderingRulesStorage; @@ -507,7 +507,7 @@ public class OsmandSettings { public ApplicationMode getApplicationMode() { return APPLICATION_MODE.get(); } - + public boolean hasAvailableApplicationMode() { int currentModeCount = ApplicationMode.values(ctx).size(); if (currentModeCount == 0 || currentModeCount == 1 && getApplicationMode() == ApplicationMode.DEFAULT) { @@ -700,9 +700,9 @@ public class OsmandSettings { return false; } - public final CommonPreference RULER_MODE = new EnumStringPreference<>(this, "ruler_mode", RulerMode.FIRST, RulerMode.values()).makeGlobal().makeShared(); - + public final CommonPreference RADIUS_RULER_MODE = new EnumStringPreference<>(this, "ruler_mode", RadiusRulerMode.FIRST, RadiusRulerMode.values()).makeGlobal().makeShared(); public final OsmandPreference SHOW_COMPASS_CONTROL_RULER = new BooleanPreference(this, "show_compass_ruler", true).makeGlobal().makeShared(); + public final OsmandPreference SHOW_DISTANCE_RULER = new BooleanPreference(this, "show_distance_ruler", false).makeProfile(); public final CommonPreference SHOW_LINES_TO_FIRST_MARKERS = new BooleanPreference(this, "show_lines_to_first_markers", false).makeProfile(); public final CommonPreference SHOW_ARROWS_TO_FIRST_MARKERS = new BooleanPreference(this, "show_arrows_to_first_markers", false).makeProfile(); @@ -1049,7 +1049,7 @@ public class OsmandSettings { // this value string is synchronized with settings_pref.xml preference name public final OsmandPreference ACCESSIBILITY_SMART_AUTOANNOUNCE = - new BooleanAccessibilityPreference(this, "accessibility_smart_autoannounce", true).makeProfile(); + new BooleanAccessibilityPreference(this, "accessibility_smart_autoannounce", true).makeProfile(); // this value string is synchronized with settings_pref.xml preference name // cache of metrics constants as they are used very often @@ -1206,6 +1206,7 @@ public class OsmandSettings { // this value string is synchronized with settings_pref.xml preference name public final CommonPreference AUTO_ZOOM_MAP = new BooleanPreference(this, "auto_zoom_map_on_off", false).makeProfile().cache(); + { AUTO_ZOOM_MAP.setModeDefaultValue(ApplicationMode.CAR, true); AUTO_ZOOM_MAP.setModeDefaultValue(ApplicationMode.BICYCLE, false); @@ -1215,6 +1216,7 @@ public class OsmandSettings { public final CommonPreference AUTO_ZOOM_MAP_SCALE = new EnumStringPreference(this, "auto_zoom_map_scale", AutoZoomMap.FAR, AutoZoomMap.values()).makeProfile().cache(); + { AUTO_ZOOM_MAP_SCALE.setModeDefaultValue(ApplicationMode.CAR, AutoZoomMap.FAR); AUTO_ZOOM_MAP_SCALE.setModeDefaultValue(ApplicationMode.BICYCLE, AutoZoomMap.CLOSE); @@ -1323,6 +1325,7 @@ public class OsmandSettings { public final OsmandPreference SPEAK_STREET_NAMES = new BooleanPreference(this, "speak_street_names", true).makeProfile().cache(); public final CommonPreference SPEAK_TRAFFIC_WARNINGS = new BooleanPreference(this, "speak_traffic_warnings", true).makeProfile().cache(); + { SPEAK_TRAFFIC_WARNINGS.setModeDefaultValue(ApplicationMode.CAR, true); } @@ -2064,7 +2067,7 @@ public class OsmandSettings { } public void setMapLocationToShow(double latitude, double longitude, int zoom, PointDescription pointDescription, - boolean addToHistory, Object toShow) { + boolean addToHistory, Object toShow) { SettingsEditor edit = settingsAPI.edit(globalPreferences); edit.putFloat(MAP_LAT_TO_SHOW, (float) latitude); edit.putFloat(MAP_LON_TO_SHOW, (float) longitude); @@ -2593,7 +2596,7 @@ public class OsmandSettings { public static final String VOICE_PROVIDER_NOT_USE = "VOICE_PROVIDER_NOT_USE"; - public static final String[] TTS_AVAILABLE_VOICES = new String[] { + public static final String[] TTS_AVAILABLE_VOICES = new String[]{ "de", "en", "es", "fr", "it", "ja", "nl", "pl", "pt", "ru", "zh" }; // this value string is synchronized with settings_pref.xml preference name diff --git a/OsmAnd/src/net/osmand/plus/views/layers/DistanceRulerControlLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/DistanceRulerControlLayer.java new file mode 100644 index 0000000000..e509ae335a --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/views/layers/DistanceRulerControlLayer.java @@ -0,0 +1,273 @@ +package net.osmand.plus.views.layers; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.Path; +import android.graphics.PathMeasure; +import android.graphics.PointF; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Message; +import android.view.MotionEvent; + +import net.osmand.Location; +import net.osmand.data.LatLon; +import net.osmand.data.RotatedTileBox; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.views.OsmandMapLayer; +import net.osmand.plus.views.OsmandMapTileView; +import net.osmand.plus.views.layers.geometry.GeometryWay; +import net.osmand.util.MapUtils; + +import java.util.ArrayList; +import java.util.List; + +public class DistanceRulerControlLayer extends OsmandMapLayer { + + private static final int VERTICAL_OFFSET = 15; + private static final long DRAW_TIME = 2000; + private static final long DELAY_BEFORE_DRAW = 500; + private static final int DISTANCE_TEXT_SIZE = 16; + + private final MapActivity mapActivity; + private OsmandApplication app; + private OsmandMapTileView view; + + private boolean showTwoFingersDistance; + private boolean showDistBetweenFingerAndLocation; + private boolean touchOutside; + private int acceptableTouchRadius; + + private long cacheMultiTouchEndTime; + private LatLon touchPointLatLon; + private PointF touchPoint; + private long touchStartTime; + private long touchEndTime; + private boolean touched; + private boolean wasZoom; + + private final List tx = new ArrayList<>(); + private final List ty = new ArrayList<>(); + private final Path linePath = new Path(); + + private Bitmap centerIconDay; + private Bitmap centerIconNight; + private Paint bitmapPaint; + + private RenderingLineAttributes lineAttrs; + private RenderingLineAttributes lineFontAttrs; + + private Handler handler; + + public DistanceRulerControlLayer(MapActivity mapActivity) { + this.mapActivity = mapActivity; + } + + @Override + public void initLayer(final OsmandMapTileView view) { + app = mapActivity.getMyApplication(); + this.view = view; + touchPoint = new PointF(); + acceptableTouchRadius = mapActivity.getResources().getDimensionPixelSize(R.dimen.acceptable_touch_radius); + + centerIconDay = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_day); + centerIconNight = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_night); + + bitmapPaint = new Paint(); + bitmapPaint.setAntiAlias(true); + bitmapPaint.setDither(true); + bitmapPaint.setFilterBitmap(true); + + lineAttrs = new RenderingLineAttributes("rulerLine"); + + float lineTextSize = DISTANCE_TEXT_SIZE * mapActivity.getResources().getDisplayMetrics().density; + + lineFontAttrs = new RenderingLineAttributes("rulerLineFont"); + lineFontAttrs.paint.setTextSize(lineTextSize); + lineFontAttrs.paint2.setTextSize(lineTextSize); + + handler = new Handler() { + @Override + public void handleMessage(Message msg) { + view.refreshMap(); + } + }; + + } + + @Override + public boolean isMapGestureAllowed(MapGestureType type) { + return !rulerModeOn() || type != MapGestureType.TWO_POINTERS_ZOOM_OUT; + } + + @Override + public boolean onTouchEvent(MotionEvent event, RotatedTileBox tileBox) { + if (rulerModeOn() && !showTwoFingersDistance) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + touched = true; + touchOutside = false; + touchPoint.set(event.getX(), event.getY()); + touchPointLatLon = tileBox.getLatLonFromPixel(event.getX(), event.getY()); + touchStartTime = System.currentTimeMillis(); + wasZoom = false; + } else if (event.getAction() == MotionEvent.ACTION_MOVE && !touchOutside && + !(touched && showDistBetweenFingerAndLocation)) { + double d = Math.sqrt(Math.pow(event.getX() - touchPoint.x, 2) + Math.pow(event.getY() - touchPoint.y, 2)); + if (d > acceptableTouchRadius) { + touchOutside = true; + } + } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + touched = false; + touchEndTime = System.currentTimeMillis(); + refreshMapDelayed(); + } + } + return false; + } + + @Override + public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings settings) { + if (rulerModeOn()) { + OsmandApplication app = view.getApplication(); + lineAttrs.updatePaints(app, settings, tb); + lineFontAttrs.updatePaints(app, settings, tb); + lineFontAttrs.paint.setStyle(Style.FILL); + final long currentTime = System.currentTimeMillis(); + + if (cacheMultiTouchEndTime != view.getMultiTouchEndTime()) { + cacheMultiTouchEndTime = view.getMultiTouchEndTime(); + refreshMapDelayed(); + } + if (touched && view.isMultiTouch()) { + touched = false; + touchEndTime = currentTime; + } + if (tb.isZoomAnimated()) { + wasZoom = true; + } + + showTwoFingersDistance = !tb.isZoomAnimated() && + !view.isWasZoomInMultiTouch() && + currentTime - view.getMultiTouchStartTime() > DELAY_BEFORE_DRAW && + (view.isMultiTouch() || currentTime - cacheMultiTouchEndTime < DRAW_TIME); + + showDistBetweenFingerAndLocation = !wasZoom && + !showTwoFingersDistance && + !view.isMultiTouch() && + !touchOutside && + touchStartTime - view.getMultiTouchStartTime() > DELAY_BEFORE_DRAW && + currentTime - touchStartTime > DELAY_BEFORE_DRAW && + (touched || currentTime - touchEndTime < DRAW_TIME); + + Location currentLoc = app.getLocationProvider().getLastKnownLocation(); + if (showDistBetweenFingerAndLocation && currentLoc != null) { + drawDistBetweenFingerAndLocation(canvas, tb, currentLoc, settings.isNightMode()); + } else if (showTwoFingersDistance) { + drawTwoFingersDistance(canvas, tb, view.getFirstTouchPointLatLon(), + view.getSecondTouchPointLatLon(), settings.isNightMode()); + } + } + } + + public boolean rulerModeOn() { + return app.getSettings().SHOW_DISTANCE_RULER.get(); + } + + private void refreshMapDelayed() { + handler.sendEmptyMessageDelayed(0, DRAW_TIME + 50); + } + + private void drawTwoFingersDistance(Canvas canvas, RotatedTileBox tb, LatLon firstTouch, + LatLon secondTouch, boolean nightMode) { + float x1 = tb.getPixXFromLatLon(firstTouch.getLatitude(), firstTouch.getLongitude()); + float y1 = tb.getPixYFromLatLon(firstTouch.getLatitude(), firstTouch.getLongitude()); + float x2 = tb.getPixXFromLatLon(secondTouch.getLatitude(), secondTouch.getLongitude()); + float y2 = tb.getPixYFromLatLon(secondTouch.getLatitude(), secondTouch.getLongitude()); + + Path path = new Path(); + path.moveTo(x1, y1); + path.lineTo(x2, y2); + + String text = OsmAndFormatter.getFormattedDistance((float) MapUtils.getDistance(firstTouch, secondTouch), app); + + canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); + canvas.drawPath(path, lineAttrs.paint); + drawFingerTouchIcon(canvas, x1, y1, nightMode); + drawFingerTouchIcon(canvas, x2, y2, nightMode); + drawTextOnCenterOfPath(canvas, x1, x2, path, text); + canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); + } + + private void drawTextOnCenterOfPath(Canvas canvas, float x1, float x2, Path path, String text) { + PathMeasure pm = new PathMeasure(path, false); + Rect bounds = new Rect(); + lineFontAttrs.paint.getTextBounds(text, 0, text.length(), bounds); + float hOffset = pm.getLength() / 2 - bounds.width() / 2f; + + if (x1 >= x2) { + float[] pos = new float[2]; + pm.getPosTan(pm.getLength() / 2, pos, null); + canvas.rotate(180, pos[0], pos[1]); + canvas.drawTextOnPath(text, path, hOffset, bounds.height() + VERTICAL_OFFSET, lineFontAttrs.paint2); + canvas.drawTextOnPath(text, path, hOffset, bounds.height() + VERTICAL_OFFSET, lineFontAttrs.paint); + canvas.rotate(-180, pos[0], pos[1]); + } else { + canvas.drawTextOnPath(text, path, hOffset, -VERTICAL_OFFSET, lineFontAttrs.paint2); + canvas.drawTextOnPath(text, path, hOffset, -VERTICAL_OFFSET, lineFontAttrs.paint); + } + } + + private void drawFingerTouchIcon(Canvas canvas, float x, float y, boolean nightMode) { + if (nightMode) { + canvas.drawBitmap(centerIconNight, x - centerIconNight.getWidth() / 2f, + y - centerIconNight.getHeight() / 2f, bitmapPaint); + + } else { + canvas.drawBitmap(centerIconDay, x - centerIconDay.getWidth() / 2f, + y - centerIconDay.getHeight() / 2f, bitmapPaint); + } + } + + private void drawDistBetweenFingerAndLocation(Canvas canvas, RotatedTileBox tb, Location currLoc, boolean night) { + float x = tb.getPixXFromLatLon(touchPointLatLon.getLatitude(), touchPointLatLon.getLongitude()); + float y = tb.getPixYFromLatLon(touchPointLatLon.getLatitude(), touchPointLatLon.getLongitude()); + float currX = tb.getPixXFromLatLon(currLoc.getLatitude(), currLoc.getLongitude()); + float currY = tb.getPixYFromLatLon(currLoc.getLatitude(), currLoc.getLongitude()); + + linePath.reset(); + tx.clear(); + ty.clear(); + + tx.add(x); + ty.add(y); + tx.add(currX); + ty.add(currY); + + GeometryWay.calculatePath(tb, tx, ty, linePath); + + float dist = (float) MapUtils.getDistance(touchPointLatLon, currLoc.getLatitude(), currLoc.getLongitude()); + String text = OsmAndFormatter.getFormattedDistance(dist, app); + + canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); + canvas.drawPath(linePath, lineAttrs.paint); + drawFingerTouchIcon(canvas, x, y, night); + drawTextOnCenterOfPath(canvas, x, currX, linePath, text); + canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); + } + + @Override + public void destroyLayer() { + + } + + @Override + public boolean drawInScreenPixels() { + return false; + } +} diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java index 22eb448670..8fa3f2bf50 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java @@ -780,7 +780,7 @@ public class MapControlsLayer extends OsmandMapLayer { if (app.getRoutingHelper().isFollowingMode() || app.getRoutingHelper().isPauseNavigation() || mapActivity.getMeasurementToolFragment() != null || mapActivity.getPlanRouteFragment() != null - || mapActivity.getMapLayers().getRulerControlLayer().rulerModeOn()) { + || mapActivity.getMapLayers().getDistanceRulerControlLayer().rulerModeOn()) { return; } if (isMapControlsVisible()) { @@ -893,7 +893,7 @@ public class MapControlsLayer extends OsmandMapLayer { layersHud.update(app, isNight); } boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls - && !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode() + && !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode() && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode(); layersHud.updateVisibility(showTopButtons); quickSearchHud.updateVisibility(showTopButtons); @@ -1069,7 +1069,7 @@ public class MapControlsLayer extends OsmandMapLayer { } } - public void updateTransparencySlider () { + public void updateTransparencySlider() { LayerTransparencySeekbarMode seekbarMode = settings.LAYER_TRANSPARENCY_SEEKBAR_MODE.get(); if (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) != null) { if (seekbarMode == LayerTransparencySeekbarMode.OVERLAY && settings.MAP_OVERLAY.get() != null) { @@ -1081,7 +1081,7 @@ public class MapControlsLayer extends OsmandMapLayer { } public void showTransparencyBar(CommonPreference transparenPreference, - boolean isTransparencyBarEnabled) { + boolean isTransparencyBarEnabled) { this.isTransparencyBarEnabled = isTransparencyBarEnabled; ApplicationMode appMode = app.getSettings().getApplicationMode(); if (MapControlsLayer.transparencySetting != transparenPreference) { @@ -1357,7 +1357,7 @@ public class MapControlsLayer extends OsmandMapLayer { } private boolean isInFollowTrackMode() { - return MapRouteInfoMenu.followTrackVisible; + return MapRouteInfoMenu.followTrackVisible; } public static View.OnLongClickListener getOnClickMagnifierListener(final OsmandMapTileView view) { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapInfoLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapInfoLayer.java index 2189c2b26e..282cd598c3 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapInfoLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapInfoLayer.java @@ -58,7 +58,7 @@ import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_NEXT_NEX import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_NEXT_TURN; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_NEXT_TURN_SMALL; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_PLAIN_TIME; -import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_RULER; +import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_RADIUS_RULER; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_SPEED; import static net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WIDGET_TIME; @@ -85,16 +85,16 @@ public class MapInfoLayer extends OsmandMapLayer { private TopToolbarView topToolbarView; private TopCoordinatesView topCoordinatesView; - public MapInfoLayer(MapActivity map, RouteLayer layer){ + public MapInfoLayer(MapActivity map, RouteLayer layer) { this.map = map; settings = map.getMyApplication().getSettings(); this.routeLayer = layer; } - + public MapWidgetRegistry getMapInfoControls() { return mapInfoControls; } - + public MapActivity getMapActivity() { return map; } @@ -102,7 +102,7 @@ public class MapInfoLayer extends OsmandMapLayer { @Override public void initLayer(final OsmandMapTileView view) { this.view = view; - mapInfoControls = map.getMapLayers().getMapWidgetRegistry() ; + mapInfoControls = map.getMapLayers().getMapWidgetRegistry(); leftStack = map.findViewById(R.id.map_left_widgets_panel); rightStack = map.findViewById(R.id.map_right_widgets_panel); expand = map.findViewById(R.id.map_collapse_button); @@ -111,19 +111,19 @@ public class MapInfoLayer extends OsmandMapLayer { // update and create controls registerAllControls(); map.getMyApplication().getAidlApi().registerWidgetControls(map); - + recreateControls(); } - + public MapWidgetRegInfo registerSideWidget(TextInfoWidget widget, int drawableMenu, - int messageId, String key, boolean left, int priorityOrder) { + int messageId, String key, boolean left, int priorityOrder) { MapWidgetRegInfo reg = mapInfoControls.registerSideWidgetInternal(widget, drawableMenu, messageId, key, left, priorityOrder); updateReg(calculateTextState(), reg); return reg; } public MapWidgetRegInfo registerSideWidget(TextInfoWidget widget, int drawableMenu, - String message, String key, boolean left, int priorityOrder) { + String message, String key, boolean left, int priorityOrder) { MapWidgetRegInfo reg = mapInfoControls.registerSideWidgetInternal(widget, drawableMenu, message, key, left, priorityOrder); updateReg(calculateTextState(), reg); return reg; @@ -137,7 +137,7 @@ public class MapInfoLayer extends OsmandMapLayer { public T getSideWidget(Class cl) { return mapInfoControls.getSideWidget(cl); } - + public void removeSideWidget(TextInfoWidget widget) { mapInfoControls.removeSideWidgetInternal(widget); } @@ -167,7 +167,7 @@ public class MapInfoLayer extends OsmandMapLayer { return topToolbarView != null && topToolbarView.isTopToolbarViewVisible(); } - public void registerAllControls(){ + public void registerAllControls() { rulerWidgets = new ArrayList<>(); RouteInfoWidgetsFactory ric = new RouteInfoWidgetsFactory(); MapInfoWidgetsFactory mic = new MapInfoWidgetsFactory(); @@ -198,7 +198,7 @@ public class MapInfoLayer extends OsmandMapLayer { NextTurnWidget smallInfoControl = ric.createNextInfoControl(map, app, true); registerSideWidget(smallInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_turn_small, WIDGET_NEXT_TURN_SMALL, true, 6); NextTurnWidget nextNextInfoControl = ric.createNextNextInfoControl(map, app, true); - registerSideWidget(nextNextInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_next_turn, WIDGET_NEXT_NEXT_TURN,true, 7); + registerSideWidget(nextNextInfoControl, R.drawable.ic_action_next_turn, R.string.map_widget_next_next_turn, WIDGET_NEXT_NEXT_TURN, true, 7); // register right stack // priorityOrder: 10s navigation-related, 20s position-related, 30s recording- and other plugin-related, 40s general device information, 50s debugging-purpose @@ -222,7 +222,7 @@ public class MapInfoLayer extends OsmandMapLayer { TextInfoWidget speed = ric.createSpeedControl(map); registerSideWidget(speed, R.drawable.ic_action_speed, R.string.map_widget_speed, WIDGET_SPEED, false, 20); TextInfoWidget maxspeed = ric.createMaxSpeedControl(map); - registerSideWidget(maxspeed, R.drawable.ic_action_speed_limit, R.string.map_widget_max_speed, WIDGET_MAX_SPEED, false, 21); + registerSideWidget(maxspeed, R.drawable.ic_action_speed_limit, R.string.map_widget_max_speed, WIDGET_MAX_SPEED, false, 21); TextInfoWidget alt = mic.createAltitudeControl(map); registerSideWidget(alt, R.drawable.ic_action_altitude, R.string.map_widget_altitude, WIDGET_ALTITUDE, false, 23); TextInfoWidget gpsInfo = mic.createGPSInfoControl(map); @@ -232,8 +232,8 @@ public class MapInfoLayer extends OsmandMapLayer { registerSideWidget(plainTime, R.drawable.ic_action_time, R.string.map_widget_plain_time, WIDGET_PLAIN_TIME, false, 41); TextInfoWidget battery = ric.createBatteryControl(map); registerSideWidget(battery, R.drawable.ic_action_battery, R.string.map_widget_battery, WIDGET_BATTERY, false, 42); - TextInfoWidget ruler = mic.createRulerControl(map); - registerSideWidget(ruler, new CompassRulerWidgetState(app), WIDGET_RULER, false, 43); + TextInfoWidget radiusRuler = mic.createRadiusRulerControl(map); + registerSideWidget(radiusRuler, new CompassRulerWidgetState(app), WIDGET_RADIUS_RULER, false, 43); } public void recreateControls() { @@ -245,14 +245,14 @@ public class MapInfoLayer extends OsmandMapLayer { mapInfoControls.populateStackControl(rightStack, settings.getApplicationMode(), false, expanded); rightStack.requestLayout(); - expand.setVisibility(mapInfoControls.hasCollapsibles(settings.getApplicationMode())? + expand.setVisibility(mapInfoControls.hasCollapsibles(settings.getApplicationMode()) ? View.VISIBLE : View.GONE); Drawable expandIcon = map.getMyApplication().getUIUtilities().getMapIcon(expanded ? R.drawable.ic_action_arrow_up : R.drawable.ic_action_arrow_down, true); setMapButtonIcon(expand, expandIcon); expand.setContentDescription(map.getString(expanded ? R.string.shared_string_collapse : R.string.access_widget_expand)); expand.setOnClickListener(new OnClickListener() { - + @Override public void onClick(View v) { expanded = !expanded; @@ -298,6 +298,7 @@ public class MapInfoLayer extends OsmandMapLayer { } private int themeId = -1; + public void updateColorShadowsOfText() { boolean transparent = view.getSettings().TRANSPARENT_MAP_THEME.get(); boolean nightMode = drawSettings != null && drawSettings.isNightMode(); @@ -345,7 +346,7 @@ public class MapInfoLayer extends OsmandMapLayer { private void updateReg(TextState ts, MapWidgetRegInfo reg) { View v = reg.widget != null ? reg.widget.getView().findViewById(R.id.widget_bg) : null; - if(v != null) { + if (v != null) { v.setBackgroundResource(reg.left ? ts.leftRes : ts.rightRes); reg.widget.updateTextColor(ts.textColor, ts.textShadowColor, ts.textBold, ts.textShadowRadius); reg.widget.updateIconMode(ts.night); @@ -407,7 +408,7 @@ public class MapInfoLayer extends OsmandMapLayer { rulerWidget.updateInfo(tileBox, drawSettings); } } - + @Override public void destroyLayer() { } diff --git a/OsmAnd/src/net/osmand/plus/views/layers/RulerControlLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/RadiusRulerControlLayer.java similarity index 68% rename from OsmAnd/src/net/osmand/plus/views/layers/RulerControlLayer.java rename to OsmAnd/src/net/osmand/plus/views/layers/RadiusRulerControlLayer.java index 8ba37ca98a..7e5acb8778 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/RulerControlLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/RadiusRulerControlLayer.java @@ -8,22 +8,16 @@ import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; -import android.graphics.PathMeasure; -import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.Typeface; -import android.os.Handler; -import android.os.Message; -import android.view.MotionEvent; import android.view.View; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import net.osmand.AndroidUtils; -import net.osmand.Location; import net.osmand.data.LatLon; import net.osmand.data.QuadPoint; import net.osmand.data.RotatedTileBox; @@ -36,19 +30,14 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.layers.geometry.GeometryWay; import net.osmand.util.MapUtils; import java.util.ArrayList; import java.util.List; -public class RulerControlLayer extends OsmandMapLayer { +public class RadiusRulerControlLayer extends OsmandMapLayer { - private static final int VERTICAL_OFFSET = 15; - private static final long DRAW_TIME = 2000; - private static final long DELAY_BEFORE_DRAW = 500; private static final int TEXT_SIZE = 14; - private static final int DISTANCE_TEXT_SIZE = 16; private static final float COMPASS_CIRCLE_FITTING_RADIUS_COEF = 1.25f; private static final float CIRCLE_ANGLE_STEP = 5; private static final int SHOW_COMPASS_MIN_ZOOM = 8; @@ -63,10 +52,6 @@ public class RulerControlLayer extends OsmandMapLayer { private float maxRadius; private int radius; private double roundedDist; - private boolean showTwoFingersDistance; - private boolean showDistBetweenFingerAndLocation; - private boolean touchOutside; - private int acceptableTouchRadius; private QuadPoint cacheCenter; private float cacheMapDensity; @@ -74,18 +59,7 @@ public class RulerControlLayer extends OsmandMapLayer { private MetricsConstants cacheMetricSystem; private int cacheIntZoom; private LatLon cacheCenterLatLon; - private long cacheMultiTouchEndTime; private ArrayList cacheDistances; - private LatLon touchPointLatLon; - private PointF touchPoint; - private long touchStartTime; - private long touchEndTime; - private boolean touched; - private boolean wasZoom; - - private List tx = new ArrayList<>(); - private List ty = new ArrayList<>(); - private Path linePath = new Path(); private Bitmap centerIconDay; private Bitmap centerIconNight; @@ -95,41 +69,25 @@ public class RulerControlLayer extends OsmandMapLayer { private Paint redLinesPaint; private Paint blueLinesPaint; - private RenderingLineAttributes lineAttrs; - private RenderingLineAttributes lineFontAttrs; private RenderingLineAttributes circleAttrs; private RenderingLineAttributes circleAttrsAlt; - private Path compass = new Path(); - private Path arrow = new Path(); - private Path arrowArc = new Path(); - private Path redCompassLines = new Path(); + private final Path compass = new Path(); + private final Path arrow = new Path(); + private final Path arrowArc = new Path(); + private final Path redCompassLines = new Path(); - private double[] degrees = new double[72]; - private String[] cardinalDirections = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"}; + private final double[] degrees = new double[72]; + private final String[] cardinalDirections = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"}; - private int[] arcColors = {Color.parseColor("#00237BFF"), Color.parseColor("#237BFF"), Color.parseColor("#00237BFF")}; + private final int[] arcColors = {Color.parseColor("#00237BFF"), Color.parseColor("#237BFF"), Color.parseColor("#00237BFF")}; private float cachedHeading = 0; - private Handler handler; - - public RulerControlLayer(MapActivity mapActivity) { + public RadiusRulerControlLayer(MapActivity mapActivity) { this.mapActivity = mapActivity; } - public boolean isShowTwoFingersDistance() { - return showTwoFingersDistance; - } - - public boolean isShowDistBetweenFingerAndLocation() { - return showDistBetweenFingerAndLocation; - } - - public LatLon getTouchPointLatLon() { - return touchPointLatLon; - } - @Override public void initLayer(final OsmandMapTileView view) { app = mapActivity.getMyApplication(); @@ -141,8 +99,6 @@ public class RulerControlLayer extends OsmandMapLayer { cacheCenter = new QuadPoint(); maxRadiusInDp = mapActivity.getResources().getDimensionPixelSize(R.dimen.map_ruler_width); rightWidgetsPanel = mapActivity.findViewById(R.id.map_right_widgets_panel); - touchPoint = new PointF(); - acceptableTouchRadius = mapActivity.getResources().getDimensionPixelSize(R.dimen.acceptable_touch_radius); centerIconDay = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_day); centerIconNight = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_ruler_center_night); @@ -160,14 +116,7 @@ public class RulerControlLayer extends OsmandMapLayer { redLinesPaint = initPaintWithStyle(Style.STROKE, colorNorthArrow); blueLinesPaint = initPaintWithStyle(Style.STROKE, colorHeadingArrow); - lineAttrs = new RenderingLineAttributes("rulerLine"); - float circleTextSize = TEXT_SIZE * mapActivity.getResources().getDisplayMetrics().density; - float lineTextSize = DISTANCE_TEXT_SIZE * mapActivity.getResources().getDisplayMetrics().density; - - lineFontAttrs = new RenderingLineAttributes("rulerLineFont"); - lineFontAttrs.paint.setTextSize(lineTextSize); - lineFontAttrs.paint2.setTextSize(lineTextSize); circleAttrs = new RenderingLineAttributes("rulerCircle"); circleAttrs.paint2.setTextSize(circleTextSize); @@ -177,13 +126,6 @@ public class RulerControlLayer extends OsmandMapLayer { circleAttrsAlt.paint2.setTextSize(circleTextSize); circleAttrsAlt.paint3.setTextSize(circleTextSize); - handler = new Handler() { - @Override - public void handleMessage(Message msg) { - view.refreshMap(); - } - }; - for (int i = 0; i < 72; i++) { degrees[i] = Math.toRadians(i * 5); } @@ -197,95 +139,27 @@ public class RulerControlLayer extends OsmandMapLayer { return paint; } - @Override - public boolean isMapGestureAllowed(MapGestureType type) { - if (rulerModeOn() && type == MapGestureType.TWO_POINTERS_ZOOM_OUT) { - return false; - } else { - return true; - } - } - - @Override - public boolean onTouchEvent(MotionEvent event, RotatedTileBox tileBox) { - if (rulerModeOn() && !showTwoFingersDistance) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - touched = true; - touchOutside = false; - touchPoint.set(event.getX(), event.getY()); - touchPointLatLon = tileBox.getLatLonFromPixel(event.getX(), event.getY()); - touchStartTime = System.currentTimeMillis(); - wasZoom = false; - } else if (event.getAction() == MotionEvent.ACTION_MOVE && !touchOutside && - !(touched && showDistBetweenFingerAndLocation)) { - double d = Math.sqrt(Math.pow(event.getX() - touchPoint.x, 2) + Math.pow(event.getY() - touchPoint.y, 2)); - if (d > acceptableTouchRadius) { - touchOutside = true; - } - } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { - touched = false; - touchEndTime = System.currentTimeMillis(); - refreshMapDelayed(); - } - } - return false; - } - @Override public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings settings) { if (rulerModeOn()) { OsmandApplication app = view.getApplication(); - lineAttrs.updatePaints(app, settings, tb); - lineFontAttrs.updatePaints(app, settings, tb); - lineFontAttrs.paint.setStyle(Style.FILL); circleAttrs.updatePaints(app, settings, tb); circleAttrs.paint2.setStyle(Style.FILL); circleAttrsAlt.updatePaints(app, settings, tb); circleAttrsAlt.paint2.setStyle(Style.FILL); final QuadPoint center = tb.getCenterPixelPoint(); - final RulerMode mode = app.getSettings().RULER_MODE.get(); + final RadiusRulerMode mode = app.getSettings().RADIUS_RULER_MODE.get(); boolean showCompass = app.getSettings().SHOW_COMPASS_CONTROL_RULER.get() && tb.getZoom() >= SHOW_COMPASS_MIN_ZOOM; - final long currentTime = System.currentTimeMillis(); - - if (cacheMultiTouchEndTime != view.getMultiTouchEndTime()) { - cacheMultiTouchEndTime = view.getMultiTouchEndTime(); - refreshMapDelayed(); - } - if (touched && view.isMultiTouch()) { - touched = false; - touchEndTime = currentTime; - } - if (tb.isZoomAnimated()) { - wasZoom = true; - } - - showTwoFingersDistance = !tb.isZoomAnimated() && - !view.isWasZoomInMultiTouch() && - currentTime - view.getMultiTouchStartTime() > DELAY_BEFORE_DRAW && - (view.isMultiTouch() || currentTime - cacheMultiTouchEndTime < DRAW_TIME); - - showDistBetweenFingerAndLocation = !wasZoom && - !showTwoFingersDistance && - !view.isMultiTouch() && - !touchOutside && - touchStartTime - view.getMultiTouchStartTime() > DELAY_BEFORE_DRAW && - currentTime - touchStartTime > DELAY_BEFORE_DRAW && - (touched || currentTime - touchEndTime < DRAW_TIME); drawCenterIcon(canvas, tb, center, settings.isNightMode(), mode); - Location currentLoc = app.getLocationProvider().getLastKnownLocation(); - if (showDistBetweenFingerAndLocation && currentLoc != null) { - drawDistBetweenFingerAndLocation(canvas, tb, currentLoc, settings.isNightMode()); - } else if (showTwoFingersDistance) { - drawTwoFingersDistance(canvas, tb, view.getFirstTouchPointLatLon(), view.getSecondTouchPointLatLon(), settings.isNightMode()); - } - if (mode == RulerMode.FIRST || mode == RulerMode.SECOND) { + + if (mode == RadiusRulerMode.FIRST || mode == RadiusRulerMode.SECOND) { updateData(tb, center); if (showCompass) { updateHeading(); resetDrawingPaths(); } - RenderingLineAttributes attrs = mode == RulerMode.FIRST ? circleAttrs : circleAttrsAlt; + RenderingLineAttributes attrs = mode == RadiusRulerMode.FIRST ? circleAttrs : circleAttrsAlt; int compassCircleId = getCompassCircleId(tb, center); for (int i = 1; i <= cacheDistances.size(); i++) { if (showCompass && i == compassCircleId) { @@ -350,99 +224,19 @@ public class RulerControlLayer extends OsmandMapLayer { arrow.reset(); } - private void refreshMapDelayed() { - handler.sendEmptyMessageDelayed(0, DRAW_TIME + 50); - } - - private void drawTwoFingersDistance(Canvas canvas, RotatedTileBox tb, LatLon firstTouch, LatLon secondTouch, boolean nightMode) { - float x1 = tb.getPixXFromLatLon(firstTouch.getLatitude(), firstTouch.getLongitude()); - float y1 = tb.getPixYFromLatLon(firstTouch.getLatitude(), firstTouch.getLongitude()); - float x2 = tb.getPixXFromLatLon(secondTouch.getLatitude(), secondTouch.getLongitude()); - float y2 = tb.getPixYFromLatLon(secondTouch.getLatitude(), secondTouch.getLongitude()); - - Path path = new Path(); - path.moveTo(x1, y1); - path.lineTo(x2, y2); - - String text = OsmAndFormatter.getFormattedDistance((float) MapUtils.getDistance(firstTouch, secondTouch), app); - - canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); - canvas.drawPath(path, lineAttrs.paint); - drawFingerTouchIcon(canvas, x1, y1, nightMode); - drawFingerTouchIcon(canvas, x2, y2, nightMode); - drawTextOnCenterOfPath(canvas, x1, x2, path, text); - canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); - } - - private void drawTextOnCenterOfPath(Canvas canvas, float x1, float x2, Path path, String text) { - PathMeasure pm = new PathMeasure(path, false); - Rect bounds = new Rect(); - lineFontAttrs.paint.getTextBounds(text, 0, text.length(), bounds); - float hOffset = pm.getLength() / 2 - bounds.width() / 2; - - if (x1 >= x2) { - float[] pos = new float[2]; - pm.getPosTan(pm.getLength() / 2, pos, null); - canvas.rotate(180, pos[0], pos[1]); - canvas.drawTextOnPath(text, path, hOffset, bounds.height() + VERTICAL_OFFSET, lineFontAttrs.paint2); - canvas.drawTextOnPath(text, path, hOffset, bounds.height() + VERTICAL_OFFSET, lineFontAttrs.paint); - canvas.rotate(-180, pos[0], pos[1]); - } else { - canvas.drawTextOnPath(text, path, hOffset, -VERTICAL_OFFSET, lineFontAttrs.paint2); - canvas.drawTextOnPath(text, path, hOffset, -VERTICAL_OFFSET, lineFontAttrs.paint); - } - } - - private void drawFingerTouchIcon(Canvas canvas, float x, float y, boolean nightMode) { - if (nightMode) { - canvas.drawBitmap(centerIconNight, x - centerIconNight.getWidth() / 2, - y - centerIconNight.getHeight() / 2, bitmapPaint); - } else { - canvas.drawBitmap(centerIconDay, x - centerIconDay.getWidth() / 2, - y - centerIconDay.getHeight() / 2, bitmapPaint); - } - } - - private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, boolean nightMode, - RulerMode mode) { + private void drawCenterIcon(Canvas canvas, RotatedTileBox tb, QuadPoint center, + boolean nightMode, RadiusRulerMode mode) { canvas.rotate(-tb.getRotate(), center.x, center.y); - if (nightMode || mode == RulerMode.SECOND) { - canvas.drawBitmap(centerIconNight, center.x - centerIconNight.getWidth() / 2, - center.y - centerIconNight.getHeight() / 2, bitmapPaint); + if (nightMode || mode == RadiusRulerMode.SECOND) { + canvas.drawBitmap(centerIconNight, center.x - centerIconNight.getWidth() / 2f, + center.y - centerIconNight.getHeight() / 2f, bitmapPaint); } else { - canvas.drawBitmap(centerIconDay, center.x - centerIconDay.getWidth() / 2, - center.y - centerIconDay.getHeight() / 2, bitmapPaint); + canvas.drawBitmap(centerIconDay, center.x - centerIconDay.getWidth() / 2f, + center.y - centerIconDay.getHeight() / 2f, bitmapPaint); } canvas.rotate(tb.getRotate(), center.x, center.y); } - private void drawDistBetweenFingerAndLocation(Canvas canvas, RotatedTileBox tb, Location currLoc, boolean night) { - float x = tb.getPixXFromLatLon(touchPointLatLon.getLatitude(), touchPointLatLon.getLongitude()); - float y = tb.getPixYFromLatLon(touchPointLatLon.getLatitude(), touchPointLatLon.getLongitude()); - float currX = tb.getPixXFromLatLon(currLoc.getLatitude(), currLoc.getLongitude()); - float currY = tb.getPixYFromLatLon(currLoc.getLatitude(), currLoc.getLongitude()); - - linePath.reset(); - tx.clear(); - ty.clear(); - - tx.add(x); - ty.add(y); - tx.add(currX); - ty.add(currY); - - GeometryWay.calculatePath(tb, tx, ty, linePath); - - float dist = (float) MapUtils.getDistance(touchPointLatLon, currLoc.getLatitude(), currLoc.getLongitude()); - String text = OsmAndFormatter.getFormattedDistance(dist, app); - - canvas.rotate(-tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); - canvas.drawPath(linePath, lineAttrs.paint); - drawFingerTouchIcon(canvas, x, y, night); - drawTextOnCenterOfPath(canvas, x, currX, linePath, text); - canvas.rotate(tb.getRotate(), tb.getCenterPixelX(), tb.getCenterPixelY()); - } - private void updateData(RotatedTileBox tb, QuadPoint center) { if (tb.getPixHeight() > 0 && tb.getPixWidth() > 0 && maxRadiusInDp > 0 && !Double.isNaN(tb.getLatitude()) && !Double.isNaN(tb.getLongitude())) { @@ -472,8 +266,8 @@ public class RulerControlLayer extends OsmandMapLayer { float bottomDist = tb.getPixHeight() - center.y; float leftDist = center.x; float rightDist = tb.getPixWidth() - center.x; - float maxVertical = topDist >= bottomDist ? topDist : bottomDist; - float maxHorizontal = rightDist >= leftDist ? rightDist : leftDist; + float maxVertical = Math.max(topDist, bottomDist); + float maxHorizontal = Math.max(rightDist, leftDist); if (maxVertical >= maxHorizontal) { maxRadius = maxVertical; @@ -504,7 +298,7 @@ public class RulerControlLayer extends OsmandMapLayer { } private void drawCircle(Canvas canvas, RotatedTileBox tb, int circleNumber, QuadPoint center, - RenderingLineAttributes attrs) { + RenderingLineAttributes attrs) { if (!tb.isZoomAnimated()) { float circleRadius = radius * circleNumber; String text = cacheDistances.get(circleNumber - 1); @@ -631,8 +425,8 @@ public class RulerControlLayer extends OsmandMapLayer { return new float[]{x1, y1, x2, y2}; } - private void drawCompassCircle(Canvas canvas, RotatedTileBox tileBox,int circleNumber, QuadPoint center, - RenderingLineAttributes attrs) { + private void drawCompassCircle(Canvas canvas, RotatedTileBox tileBox, int circleNumber, + QuadPoint center, RenderingLineAttributes attrs) { if (!tileBox.isZoomAnimated()) { float radiusLength = radius * circleNumber; float innerRadiusLength = radiusLength - attrs.paint.getStrokeWidth() / 2; @@ -823,9 +617,9 @@ public class RulerControlLayer extends OsmandMapLayer { return false; } - public enum RulerMode { + public enum RadiusRulerMode { FIRST, SECOND, EMPTY } -} \ No newline at end of file +} diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java index 63c4c93ab9..6bc09a5987 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java @@ -68,9 +68,7 @@ import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.views.OsmandMapLayer.DrawSettings; -import net.osmand.plus.views.OsmandMapTileView; -import net.osmand.plus.views.layers.RulerControlLayer; -import net.osmand.plus.views.layers.RulerControlLayer.RulerMode; +import net.osmand.plus.views.layers.RadiusRulerControlLayer.RadiusRulerMode; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; @@ -162,50 +160,24 @@ public class MapInfoWidgetsFactory { return gpsInfoControl; } - public TextInfoWidget createRulerControl(final MapActivity map) { + public TextInfoWidget createRadiusRulerControl(final MapActivity map) { final String title = "—"; - final TextInfoWidget rulerControl = new TextInfoWidget(map) { - RulerControlLayer rulerLayer = map.getMapLayers().getRulerControlLayer(); - LatLon cacheFirstTouchPoint = new LatLon(0, 0); - LatLon cacheSecondTouchPoint = new LatLon(0, 0); - LatLon cacheSingleTouchPoint = new LatLon(0, 0); - boolean fingerAndLocDistWasShown; + final TextInfoWidget radiusRulerControl = new TextInfoWidget(map) { @Override public boolean updateInfo(DrawSettings drawSettings) { - OsmandMapTileView view = map.getMapView(); Location currentLoc = map.getMyApplication().getLocationProvider().getLastKnownLocation(); + LatLon centerLoc = map.getMapLocation(); - if (rulerLayer.isShowDistBetweenFingerAndLocation() && currentLoc != null) { - if (!cacheSingleTouchPoint.equals(rulerLayer.getTouchPointLatLon())) { - cacheSingleTouchPoint = rulerLayer.getTouchPointLatLon(); - setDistanceText(cacheSingleTouchPoint.getLatitude(), cacheSingleTouchPoint.getLongitude(), - currentLoc.getLatitude(), currentLoc.getLongitude()); - fingerAndLocDistWasShown = true; - } - } else if (rulerLayer.isShowTwoFingersDistance()) { - if (!cacheFirstTouchPoint.equals(view.getFirstTouchPointLatLon()) || - !cacheSecondTouchPoint.equals(view.getSecondTouchPointLatLon()) || - fingerAndLocDistWasShown) { - cacheFirstTouchPoint = view.getFirstTouchPointLatLon(); - cacheSecondTouchPoint = view.getSecondTouchPointLatLon(); - setDistanceText(cacheFirstTouchPoint.getLatitude(), cacheFirstTouchPoint.getLongitude(), - cacheSecondTouchPoint.getLatitude(), cacheSecondTouchPoint.getLongitude()); - fingerAndLocDistWasShown = false; + if (currentLoc != null && centerLoc != null) { + if (map.getMapViewTrackingUtilities().isMapLinkedToLocation()) { + setDistanceText(0); + } else { + setDistanceText(currentLoc.getLatitude(), currentLoc.getLongitude(), + centerLoc.getLatitude(), centerLoc.getLongitude()); } } else { - LatLon centerLoc = map.getMapLocation(); - - if (currentLoc != null && centerLoc != null) { - if (map.getMapViewTrackingUtilities().isMapLinkedToLocation()) { - setDistanceText(0); - } else { - setDistanceText(currentLoc.getLatitude(), currentLoc.getLongitude(), - centerLoc.getLatitude(), centerLoc.getLongitude()); - } - } else { - setText(title, null); - } + setText(title, null); } return true; } @@ -226,29 +198,29 @@ public class MapInfoWidgetsFactory { } }; - rulerControl.setText(title, null); - setRulerControlIcon(rulerControl, map.getMyApplication().getSettings().RULER_MODE.get()); - rulerControl.setOnClickListener(new OnClickListener() { + radiusRulerControl.setText(title, null); + setRulerControlIcon(radiusRulerControl, map.getMyApplication().getSettings().RADIUS_RULER_MODE.get()); + radiusRulerControl.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - final RulerMode mode = map.getMyApplication().getSettings().RULER_MODE.get(); - RulerMode newMode = RulerMode.FIRST; - if (mode == RulerMode.FIRST) { - newMode = RulerMode.SECOND; - } else if (mode == RulerMode.SECOND) { - newMode = RulerMode.EMPTY; + final RadiusRulerMode mode = map.getMyApplication().getSettings().RADIUS_RULER_MODE.get(); + RadiusRulerMode newMode = RadiusRulerMode.FIRST; + if (mode == RadiusRulerMode.FIRST) { + newMode = RadiusRulerMode.SECOND; + } else if (mode == RadiusRulerMode.SECOND) { + newMode = RadiusRulerMode.EMPTY; } - setRulerControlIcon(rulerControl, newMode); - map.getMyApplication().getSettings().RULER_MODE.set(newMode); + setRulerControlIcon(radiusRulerControl, newMode); + map.getMyApplication().getSettings().RADIUS_RULER_MODE.set(newMode); map.refreshMap(); } }); - return rulerControl; + return radiusRulerControl; } - private void setRulerControlIcon(TextInfoWidget rulerControl, RulerMode mode) { - if (mode == RulerMode.FIRST || mode == RulerMode.SECOND) { + private void setRulerControlIcon(TextInfoWidget rulerControl, RadiusRulerMode mode) { + if (mode == RadiusRulerMode.FIRST || mode == RadiusRulerMode.SECOND) { rulerControl.setIcons(R.drawable.widget_ruler_circle_day, R.drawable.widget_ruler_circle_night); } else { rulerControl.setIcons(R.drawable.widget_hidden_day, R.drawable.widget_hidden_night); @@ -933,7 +905,6 @@ public class MapInfoWidgetsFactory { } - public boolean updateInfo(DrawSettings d) { CurrentStreetName streetName = null; boolean showClosestWaypointFirstInAddress = true; @@ -998,7 +969,7 @@ public class MapInfoWidgetsFactory { AndroidUiHelper.updateVisibility(shieldIcon, false); } - if (!Algorithms.isEmpty(streetName.exitRef) ) { + if (!Algorithms.isEmpty(streetName.exitRef)) { exitRefText.setText(streetName.exitRef); AndroidUiHelper.updateVisibility(exitRefText, true); } else { @@ -1018,12 +989,12 @@ public class MapInfoWidgetsFactory { AndroidUiHelper.updateVisibility(turnIcon, false); } } - if(streetName.text == null || streetName.text.isEmpty()) { + if (streetName.text == null || streetName.text.isEmpty()) { addressTextShadow.setText(""); addressText.setText(""); } else if (!streetName.text.equals(addressText.getText().toString())) { addressTextShadow.setText(streetName.text); - addressText.setText(streetName.text ); + addressText.setText(streetName.text); return true; } } @@ -1044,14 +1015,15 @@ public class MapInfoWidgetsFactory { String val = object.names.get(object.nameIds[i]); if (key.startsWith("road_ref")) { boolean visible = setRoadShield(view, object, key, val, additional); - if(visible) { + if (visible) { return true; } } } return false; } - private boolean setRoadShield(ImageView view, RouteDataObject object, String nameTag, String name, StringBuilder additional ) { + + private boolean setRoadShield(ImageView view, RouteDataObject object, String nameTag, String name, StringBuilder additional) { Context context = topBar.getContext(); int[] tps = object.getTypes(); @@ -1088,7 +1060,7 @@ public class MapInfoWidgetsFactory { if (rreq.isSpecified(rreq.ALL.R_TEXT_SHIELD)) { text.setShieldResIcon(rreq.getStringPropertyValue(rreq.ALL.R_TEXT_SHIELD)); - shieldRes = app.getResources().getIdentifier("h_"+text.getShieldResIcon(), + shieldRes = app.getResources().getIdentifier("h_" + text.getShieldResIcon(), "drawable", app.getPackageName()); } diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java index cfb1b2af37..2c9d6af19d 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapWidgetRegistry.java @@ -66,7 +66,7 @@ public class MapWidgetRegistry { public static String WIDGET_BEARING = "bearing"; public static String WIDGET_PLAIN_TIME = "plain_time"; public static String WIDGET_BATTERY = "battery"; - public static String WIDGET_RULER = "ruler"; + public static String WIDGET_RADIUS_RULER = "ruler"; public static String WIDGET_STREET_NAME = "street_name"; @@ -369,6 +369,13 @@ public class MapWidgetRegistry { .setSelected(settings.SHOW_COORDINATES_WIDGET.get()) .setListener(new AppearanceItemClickListener(settings.SHOW_COORDINATES_WIDGET, map)) .setLayout(R.layout.list_item_icon_and_switch).createItem()); + + cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_widget_distance_by_tap, map) + .setIcon(R.drawable.ic_action_ruler_line) + .setSelected(settings.SHOW_DISTANCE_RULER.get()) + .setListener(new AppearanceItemClickListener(settings.SHOW_DISTANCE_RULER, map)) + .setLayout(R.layout.list_item_icon_and_switch).createItem()); + cm.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.map_markers, map) .setDescription(settings.MAP_MARKERS_MODE.get().toHumanString(map)) .setListener(new ContextMenuAdapter.ItemClickListener() { @@ -462,7 +469,7 @@ public class MapWidgetRegistry { .setIcon(R.drawable.ic_quick_action) .setSelected(selected) .setColor(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID) - .setSecondaryIcon( R.drawable.ic_action_additional_option) + .setSecondaryIcon(R.drawable.ic_action_additional_option) .setListener(new ContextMenuAdapter.OnRowItemClick() { @Override public boolean onContextMenuClick(ArrayAdapter adapter, int itemId, int position, boolean isChecked, int[] viewCoordinates) {