Merge pull request #10962 from osmandapp/separate_ruler_by_tap_from_radius_ruler

Separate ruler by tap from "Radius ruler"
This commit is contained in:
Vitaliy 2021-02-22 13:49:33 +02:00 committed by GitHub
commit e4098c0135
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 403 additions and 343 deletions

View file

@ -12,6 +12,7 @@
-->
<string name="map_widget_distance_by_tap">Distance by tap</string>
<string name="routing_attr_height_obstacles_description">Routing could avoid strong uphills.</string>
<string name="app_restart_required">Application restart required to apply some settings.</string>
<string name="on_pause">On pause</string>

View file

@ -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;
@ -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();
@ -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() {

View file

@ -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

View file

@ -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;
@ -700,9 +700,9 @@ public class OsmandSettings {
return false;
}
public final CommonPreference<RulerMode> RULER_MODE = new EnumStringPreference<>(this, "ruler_mode", RulerMode.FIRST, RulerMode.values()).makeGlobal().makeShared();
public final CommonPreference<RadiusRulerMode> RADIUS_RULER_MODE = new EnumStringPreference<>(this, "ruler_mode", RadiusRulerMode.FIRST, RadiusRulerMode.values()).makeGlobal().makeShared();
public final OsmandPreference<Boolean> SHOW_COMPASS_CONTROL_RULER = new BooleanPreference(this, "show_compass_ruler", true).makeGlobal().makeShared();
public final OsmandPreference<Boolean> SHOW_DISTANCE_RULER = new BooleanPreference(this, "show_distance_ruler", false).makeProfile();
public final CommonPreference<Boolean> SHOW_LINES_TO_FIRST_MARKERS = new BooleanPreference(this, "show_lines_to_first_markers", false).makeProfile();
public final CommonPreference<Boolean> 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<Boolean> 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<Boolean> 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<AutoZoomMap> AUTO_ZOOM_MAP_SCALE =
new EnumStringPreference<AutoZoomMap>(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<Boolean> SPEAK_STREET_NAMES = new BooleanPreference(this, "speak_street_names", true).makeProfile().cache();
public final CommonPreference<Boolean> 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

View file

@ -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<Float> tx = new ArrayList<>();
private final List<Float> 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;
}
}

View file

@ -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<Integer> 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) {

View file

@ -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,7 +85,7 @@ 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;
@ -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);
@ -116,14 +116,14 @@ public class MapInfoLayer extends OsmandMapLayer {
}
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;
@ -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,7 +245,7 @@ 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);
@ -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);

View file

@ -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<String> cacheDistances;
private LatLon touchPointLatLon;
private PointF touchPoint;
private long touchStartTime;
private long touchEndTime;
private boolean touched;
private boolean wasZoom;
private List<Float> tx = new ArrayList<>();
private List<Float> 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,7 +617,7 @@ public class RulerControlLayer extends OsmandMapLayer {
return false;
}
public enum RulerMode {
public enum RadiusRulerMode {
FIRST,
SECOND,
EMPTY

View file

@ -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());
}

View file

@ -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<ContextMenuItem> adapter, int itemId, int position, boolean isChecked, int[] viewCoordinates) {