diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 4595c8de30..0cf91d58db 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,5 +1,6 @@ + POI labels Enable auto follow position only in navigation mode. Auto follow navigation Auto follow settings are enabled. diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 35424229ae..b904a2515b 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -413,6 +413,9 @@ public class OsmandSettings { public final OsmandPreference SHOW_POI_OVER_MAP = new BooleanPreference("show_poi_over_map", false, true); + public final OsmandPreference SHOW_POI_LABEL = + new BooleanPreference("show_poi_label", false, true); + // this value string is synchronized with settings_pref.xml preference name public final OsmandPreference SHOW_TRANSPORT_OVER_MAP = new BooleanPreference("show_transport_over_map", false, true); diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java index 034b9fd4e7..21fba801b2 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityLayers.java @@ -1,5 +1,7 @@ package net.osmand.plus.activities; +import gnu.trove.list.array.TIntArrayList; + import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -234,59 +236,70 @@ public class MapActivityLayers { } public void openLayerSelectionDialog(final OsmandMapTileView mapView){ - List layersList = new ArrayList(); + + final TIntArrayList layers = new TIntArrayList(); + TIntArrayList selectedList = new TIntArrayList(); final OsmandSettings settings = getApplication().getSettings(); - layersList.add(getString(R.string.layer_map)); - layersList.add(getString(R.string.layer_poi)); - layersList.add(getString(R.string.layer_favorites)); - layersList.add(getString(R.string.layer_overlay)); - layersList.add(getString(R.string.layer_underlay)); - layersList.add(getString(R.string.layer_gpx_layer)); - layersList.add(getString(R.string.layer_transport)); - layersList.add(getString(R.string.layer_osm_bugs)); + layers.add(R.string.layer_map); + selectedList.add(1); + layers.add(R.string.layer_poi); + selectedList.add(settings.SHOW_POI_OVER_MAP.get() ? 1 : 0); + if(settings.SHOW_POI_OVER_MAP.get()){ + layers.add(R.string.layer_poi_label); + selectedList.add(settings.SHOW_POI_LABEL.get() ? 1 : 0); + } + layers.add(R.string.layer_favorites); + selectedList.add(settings.SHOW_FAVORITES.get() ? 1 : 0); + layers.add(R.string.layer_overlay); + selectedList.add(overlayLayer.getMap() != null ? 1 : 0); + layers.add(R.string.layer_underlay); + selectedList.add(underlayLayer.getMap() != null ? 1 : 0); - - final int routeInfoInd = routeInfoLayer.couldBeVisible() ? layersList.size() : -1; + layers.add(R.string.layer_gpx_layer); + selectedList.add(gpxLayer.isVisible() ? 1 : 0); if(routeInfoLayer.couldBeVisible()){ - layersList.add(getString(R.string.layer_route)); - } - final int transportRouteInfoInd = !TransportRouteHelper.getInstance().routeIsCalculated() ? - 1 : layersList.size(); - if(transportRouteInfoInd > -1){ - layersList.add(getString(R.string.layer_transport_route)); + layers.add(R.string.layer_route); + selectedList.add(routeInfoLayer.isUserDefinedVisible() ? 1 : 0); } - final boolean[] selected = new boolean[layersList.size()]; - Arrays.fill(selected, true); - selected[1] = settings.SHOW_POI_OVER_MAP.get(); - selected[2] = settings.SHOW_FAVORITES.get(); - selected[3] = overlayLayer.getMap() != null; - selected[4] = underlayLayer.getMap() != null; - selected[5] = gpxLayer.isVisible(); - selected[6] = settings.SHOW_TRANSPORT_OVER_MAP.get(); - selected[7] = settings.SHOW_OSM_BUGS.get(); - if(routeInfoInd != -1){ - selected[routeInfoInd] = routeInfoLayer.isUserDefinedVisible(); + layers.add(R.string.layer_transport); + selectedList.add(settings.SHOW_TRANSPORT_OVER_MAP.get() ? 1 : 0); + if(TransportRouteHelper.getInstance().routeIsCalculated()){ + layers.add(R.string.layer_transport_route); + selectedList.add(routeInfoLayer.isUserDefinedVisible() ? 1 : 0); } - if(transportRouteInfoInd != -1){ - selected[transportRouteInfoInd] = transportInfoLayer.isVisible(); + + layers.add(R.string.layer_osm_bugs); + selectedList.add(settings.SHOW_OSM_BUGS.get() ? 1 : 0); + + final boolean[] selected = new boolean[selectedList.size()]; + for (int i = 0; i < selected.length; i++) { + selected[i] = selectedList.get(i) > 0; } Builder builder = new AlertDialog.Builder(activity); - builder.setMultiChoiceItems(layersList.toArray(new String[layersList.size()]), selected, new DialogInterface.OnMultiChoiceClickListener() { + String[] layersName = new String[layers.size()]; + for (int i = 0; i < layers.size(); i++) { + layersName[i] = getString(layers.get(i)); + + } + builder.setMultiChoiceItems(layersName, selected, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int item, boolean isChecked) { - if (item == 0) { + if (layers.get(item) == R.string.layer_map) { dialog.dismiss(); selectMapLayer(mapView); - } else if(item == 1){ + } else if(layers.get(item) == R.string.layer_poi){ if(isChecked){ selectPOIFilterLayer(mapView); } settings.SHOW_POI_OVER_MAP.set(isChecked); - } else if(item == 2){ + } else if(layers.get(item) == R.string.layer_favorites){ settings.SHOW_FAVORITES.set(isChecked); - } else if(item == 3){ + } else if(layers.get(item) == R.string.layer_poi_label){ + settings.SHOW_POI_LABEL.set(isChecked); + } else if(layers.get(item) == R.string.layer_overlay){ if(overlayLayer.getMap() != null){ settings.MAP_OVERLAY.set(null); updateMapSource(mapView, null); @@ -295,7 +308,7 @@ public class MapActivityLayers { selectMapOverlayLayer(mapView, settings.MAP_OVERLAY, settings.MAP_OVERLAY_TRANSPARENCY, overlayLayer); } - } else if(item == 4){ + } else if(layers.get(item) == R.string.layer_underlay){ if(underlayLayer.getMap() != null){ settings.MAP_UNDERLAY.set(null); updateMapSource(mapView, null); @@ -304,7 +317,7 @@ public class MapActivityLayers { selectMapOverlayLayer(mapView, settings.MAP_UNDERLAY,settings.MAP_TRANSPARENCY, mapTileLayer, mapVectorLayer); } - } else if(item == 5){ + } else if(layers.get(item) == R.string.layer_gpx_layer){ if(gpxLayer.isVisible()){ getApplication().setGpxFileToDisplay(null); gpxLayer.clearCurrentGPX(); @@ -312,13 +325,13 @@ public class MapActivityLayers { dialog.dismiss(); showGPXFileLayer(mapView); } - } else if(item == 6){ + } else if(layers.get(item) == R.string.layer_transport){ settings.SHOW_TRANSPORT_OVER_MAP.set(isChecked); - } else if(item == 7){ + } else if(layers.get(item) == R.string.layer_osm_bugs){ settings.SHOW_OSM_BUGS.set(isChecked); - } else if(item == routeInfoInd){ + } else if(layers.get(item) == R.string.layer_route){ routeInfoLayer.setVisible(isChecked); - } else if(item == transportRouteInfoInd){ + } else if(layers.get(item) == R.string.layer_transport_route){ transportInfoLayer.setVisible(isChecked); } updateLayers(mapView); diff --git a/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java b/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java index 30a636f128..47500dec58 100644 --- a/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/POIMapLayer.java @@ -1,5 +1,7 @@ package net.osmand.plus.views; +import gnu.trove.set.hash.TIntHashSet; + import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -9,6 +11,7 @@ import net.osmand.LogUtil; import net.osmand.OsmAndFormatter; import net.osmand.data.Amenity; import net.osmand.osm.LatLon; +import net.osmand.osm.MapUtils; import net.osmand.plus.PoiFilter; import net.osmand.plus.R; import net.osmand.plus.ResourceManager; @@ -35,7 +38,8 @@ import android.widget.Toast; public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMenuProvider { private static final int startZoom = 10; - public static final int TEXT_WRAP = 30; + public static final int TEXT_WRAP = 15; + public static final int TEXT_LINES = 3; public static final org.apache.commons.logging.Log log = LogUtil.getLog(POIMapLayer.class); @@ -174,8 +178,8 @@ public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMen resourceManager.searchAmenitiesAsync(latLonBounds.top, latLonBounds.left, latLonBounds.bottom, latLonBounds.right, view.getZoom(), filter, objects); int r = getRadiusPoi(view.getZoom()); for (Amenity o : objects) { - int x = view.getMapXForPoint(o.getLocation().getLongitude()); - int y = view.getMapYForPoint(o.getLocation().getLatitude()); + int x = view.getRotatedMapXForPoint(o.getLocation().getLatitude(), o.getLocation().getLongitude()); + int y = view.getRotatedMapYForPoint(o.getLocation().getLatitude(), o.getLocation().getLongitude()); canvas.drawCircle(x, y, r, pointAltUI); canvas.drawCircle(x, y, r, point); String id = null; @@ -190,25 +194,52 @@ public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMen if(bmp != null){ canvas.drawBitmap(bmp, x - bmp.getWidth() / 2, y - bmp.getHeight() / 2, paintIcon); } + } + } + + if (view.getSettings().SHOW_POI_LABEL.get()) { + TIntHashSet set = new TIntHashSet(); + for (Amenity o : objects) { + int x = view.getRotatedMapXForPoint(o.getLocation().getLatitude(), o.getLocation().getLongitude()); + int y = view.getRotatedMapYForPoint(o.getLocation().getLatitude(), o.getLocation().getLongitude()); + int tx = view.getMapXForPoint(o.getLocation().getLongitude()); + int ty = view.getMapYForPoint(o.getLocation().getLatitude()); String name = o.getName(view.getSettings().USE_ENGLISH_NAMES.get()); - if(name != null && name.length() > 0){ - // TODO cache list - // 1. Draw over in 2 phases over all circles - // 2. Draw without rotation and icons (!) - // 3. Omit highdensity icons -// drawWrappedText(canvas, name, paintTextIcon.getTextSize(), -// x + bmp.getWidth() / 2, y + bmp.getHeight() / 2 + -// paintTextIcon.getTextSize() / 2); - + if (name != null && name.length() > 0) { + int lines = 0; + while (lines < TEXT_LINES) { + if (set.contains(division(tx, ty, 0, lines)) || + set.contains(division(tx, ty, -1, lines)) || set.contains(division(tx, ty, +1, lines))) { + break; + } + lines++; + } + if (lines == 0) { + // drawWrappedText(canvas, "...", paintTextIcon.getTextSize(), x, y + r + 2 + paintTextIcon.getTextSize() / 2, 1); + } else { + drawWrappedText(canvas, name, paintTextIcon.getTextSize(), x, y + r + 2 + paintTextIcon.getTextSize() / 2, + lines); + while (lines > 0) { + set.add(division(tx, ty, 1, lines - 1)); + set.add(division(tx, ty, -1, lines - 1)); + set.add(division(tx, ty, 0, lines - 1)); + lines--; + } + } + } } - } } } - private void drawWrappedText(Canvas cv, String text, float textSize, float x, float y) { + private int division(int x, int y, int sx, int sy) { + // make numbers positive + return ((((x + 10000) >> 4) + sx) << 16) | (((y + 10000) >> 4) + sy); + } + + private void drawWrappedText(Canvas cv, String text, float textSize, float x, float y, int lines) { if(text.length() > TEXT_WRAP){ int start = 0; int end = text.length(); @@ -216,7 +247,7 @@ public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMen int line = 0; int pos = 0; int limit = 0; - while(pos < end){ + while(pos < end && (line < lines)){ lastSpace = -1; limit += TEXT_WRAP; while(pos < limit && pos < end){ @@ -230,13 +261,18 @@ public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMen start = pos; } else { String subtext = text.substring(start, lastSpace); + if (line + 1 == lines) { + subtext += ".."; + } drawShadowText(cv, subtext, x, y + line * (textSize + 2)); start = lastSpace + 1; limit += (start - pos) - 1; } + line++; + } } else { drawShadowText(cv, text, x, y); @@ -263,7 +299,7 @@ public class POIMapLayer implements OsmandMapLayer, ContextMenuLayer.IContextMen @Override public boolean drawInScreenPixels() { - return false; + return true; } @Override