diff --git a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java index 5b7feed761..550b3e3b6b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java +++ b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java @@ -1,6 +1,7 @@ package net.osmand; + import net.osmand.data.QuadRect; import net.osmand.util.Algorithms; @@ -42,7 +43,9 @@ import java.util.Stack; import java.util.TimeZone; public class GPXUtilities { + public final static Log log = PlatformUtil.getLog(GPXUtilities.class); + private static final String ICON_NAME_EXTENSION = "icon"; private static final String DEFAULT_ICON_NAME = "special_star"; private static final String BACKGROUND_TYPE_EXTENSION = "background"; @@ -117,6 +120,13 @@ public class GPXUtilities { return extensions; } + public Map getExtensionsToWrite() { + if (extensions == null) { + extensions = new LinkedHashMap<>(); + } + return extensions; + } + public GPXExtensionsWriter getExtensionsWriter() { return extensionsWriter; } @@ -150,14 +160,7 @@ public class GPXUtilities { getExtensionsToWrite().remove("color"); } - public Map getExtensionsToWrite() { - if (extensions == null) { - extensions = new LinkedHashMap<>(); - } - return extensions; - } - - private int parseColor(String colorString, int defColor) { + protected int parseColor(String colorString, int defColor) { if (!Algorithms.isEmpty(colorString)) { if (colorString.charAt(0) == '#') { long color = Long.parseLong(colorString.substring(1), 16); @@ -954,7 +957,6 @@ public class GPXUtilities { sp = new SplitSegment(segment, k - 1, cf); currentMetricEnd += metricLimit; - prev = sp.get(0); } total += currentSegment; } @@ -1533,6 +1535,139 @@ public class GPXUtilities { } return new QuadRect(left, top, right, bottom); } + + public int getGradientScaleColor(GradientScaleType gradientScaleType, int defColor) { + String clrValue = null; + if (extensions != null) { + clrValue = extensions.get(gradientScaleType.getTypeName()); + } + return parseColor(clrValue, defColor); + } + + public void setGradientScaleColor(GradientScaleType gradientScaleType, int gradientScaleColor) { + getExtensionsToWrite().put(gradientScaleType.getTypeName(), Algorithms.colorToString(gradientScaleColor)); + } + + public GradientScaleType getGradientScaleType() { + if (extensions != null) { + String gradientScaleTypeName = extensions.get("gradient_scale_type"); + if (!Algorithms.isEmpty(gradientScaleTypeName)) { + try { + return GradientScaleType.valueOf(gradientScaleTypeName); + } catch (IllegalArgumentException e) { + log.error("Error reading gradientScaleType", e); + } + } + } + return null; + } + + public void setGradientScaleType(GradientScaleType gradientScaleType) { + getExtensionsToWrite().put("gradient_scale_type", gradientScaleType.name()); + } + + public GpxSplitType getSplitType() { + if (extensions != null) { + String gradientScaleTypeName = extensions.get("split_type"); + if (!Algorithms.isEmpty(gradientScaleTypeName)) { + try { + return GpxSplitType.valueOf(gradientScaleTypeName); + } catch (IllegalArgumentException e) { + log.error("Error reading GpxSplitType", e); + } + } + } + return null; + } + + public void setSplitType(GpxSplitType gpxSplitType) { + getExtensionsToWrite().put("split_type", gpxSplitType.name()); + } + + public double getSplitInterval() { + if (extensions != null) { + String splitIntervalStr = extensions.get("split_interval"); + if (!Algorithms.isEmpty(splitIntervalStr)) { + try { + return Double.parseDouble(splitIntervalStr); + } catch (NumberFormatException e) { + log.error("Error reading split_interval", e); + } + } + } + return 0; + } + + public void setSplitInterval(double splitInterval) { + getExtensionsToWrite().put("split_interval", String.valueOf(splitInterval)); + } + + public String getWidth(String defWidth) { + String widthValue = null; + if (extensions != null) { + widthValue = extensions.get("width"); + } + return widthValue != null ? widthValue : defWidth; + } + + public void setWidth(String width) { + getExtensionsToWrite().put("width", width); + } + + public boolean isShowArrows() { + String showArrows = null; + if (extensions != null) { + showArrows = extensions.get("show_arrows"); + } + return Boolean.parseBoolean(showArrows); + } + + public void setShowArrows(boolean showArrows) { + getExtensionsToWrite().put("show_arrows", String.valueOf(showArrows)); + } + + public boolean isShowStartFinish() { + if (extensions != null && extensions.containsKey("show_start_finish")) { + return Boolean.parseBoolean(extensions.get("show_start_finish")); + } + return true; + } + + public void setShowStartFinish(boolean showStartFinish) { + getExtensionsToWrite().put("show_start_finish", String.valueOf(showStartFinish)); + } + + public enum GradientScaleType { + SPEED("gradient_speed_color"), + ALTITUDE("gradient_altitude_color"), + SLOPE("gradient_slope_color"); + + private String typeName; + + GradientScaleType(String typeName) { + this.typeName = typeName; + } + + public String getTypeName() { + return typeName; + } + } + + public enum GpxSplitType { + NO_SPLIT(-1), + DISTANCE(1), + TIME(2); + + private int type; + + GpxSplitType(int type) { + this.type = type; + } + + public int getType() { + return type; + } + } } public static String asString(GPXFile file) { diff --git a/OsmAnd-java/src/main/java/net/osmand/NativeLibrary.java b/OsmAnd-java/src/main/java/net/osmand/NativeLibrary.java index 25e1a21969..0189d38378 100644 --- a/OsmAnd-java/src/main/java/net/osmand/NativeLibrary.java +++ b/OsmAnd-java/src/main/java/net/osmand/NativeLibrary.java @@ -26,10 +26,9 @@ import net.osmand.data.QuadRect; import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; import net.osmand.router.NativeTransportRoutingResult; -import net.osmand.router.PrecalculatedRouteDirection; import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RouteSegmentResult; -import net.osmand.router.RoutingConfiguration; +import net.osmand.router.RoutingContext; import net.osmand.router.TransportRoutingConfiguration; import net.osmand.util.Algorithms; @@ -135,12 +134,10 @@ public class NativeLibrary { return nativeTransportRouting(new int[] { sx31, sy31, ex31, ey31 }, cfg, progress); } - public RouteSegmentResult[] runNativeRouting(int sx31, int sy31, int ex31, int ey31, RoutingConfiguration config, - RouteRegion[] regions, RouteCalculationProgress progress, PrecalculatedRouteDirection precalculatedRouteDirection, - boolean basemap, boolean publicTransport, boolean startTransportStop, boolean targetTransportStop) { + public RouteSegmentResult[] runNativeRouting(RoutingContext c, RouteRegion[] regions, boolean basemap) { // config.router.printRules(System.out); - return nativeRouting(new int[] { sx31, sy31, ex31, ey31 }, config, config.initialDirection == null ? -360 : config.initialDirection.floatValue(), - regions, progress, precalculatedRouteDirection, basemap, publicTransport, startTransportStop, targetTransportStop); + return nativeRouting(c, c.config.initialDirection == null ? -360 : c.config.initialDirection.floatValue(), + regions, basemap); } @@ -156,16 +153,15 @@ public class NativeLibrary { protected static native NativeRouteSearchResult loadRoutingData(RouteRegion reg, String regName, int regfp, RouteSubregion subreg, boolean loadObjects); + public static native void deleteNativeRoutingContext(long handle); + protected static native void deleteRenderingContextHandle(long handle); protected static native void deleteRouteSearchResult(long searchResultHandle); protected static native RouteDataObject[] getRouteDataObjects(RouteRegion reg, long rs, int x31, int y31); - protected static native RouteSegmentResult[] nativeRouting(int[] coordinates, RoutingConfiguration r, - float initDirection, RouteRegion[] regions, RouteCalculationProgress progress, - PrecalculatedRouteDirection precalculatedRouteDirection, boolean basemap, - boolean publicTransport, boolean startTransportStop, boolean targetTransportStop); + protected static native RouteSegmentResult[] nativeRouting(RoutingContext c, float initDirection, RouteRegion[] regions, boolean basemap); protected static native NativeTransportRoutingResult[] nativeTransportRouting(int[] coordinates, TransportRoutingConfiguration cfg, RouteCalculationProgress progress); diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/GeocodingUtilities.java b/OsmAnd-java/src/main/java/net/osmand/binary/GeocodingUtilities.java index 1699d749d9..77357bac9b 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/GeocodingUtilities.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/GeocodingUtilities.java @@ -4,6 +4,7 @@ import net.osmand.PlatformUtil; import net.osmand.ResultMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; import net.osmand.binary.BinaryMapIndexReader.SearchRequest; +import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.data.Building; import net.osmand.data.City; import net.osmand.data.LatLon; @@ -23,9 +24,11 @@ import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import gnu.trove.set.hash.TLongHashSet; @@ -40,7 +43,7 @@ public class GeocodingUtilities { public static final float STOP_SEARCHING_STREET_WITH_MULTIPLIER_RADIUS = 250; public static final float STOP_SEARCHING_STREET_WITHOUT_MULTIPLIER_RADIUS = 400; - public static final int DISTANCE_STREET_NAME_PROXIMITY_BY_NAME = 15000; + public static final int DISTANCE_STREET_NAME_PROXIMITY_BY_NAME = 45000; public static final float DISTANCE_STREET_FROM_CLOSEST_WITH_SAME_NAME = 1000; public static final float THRESHOLD_MULTIPLIER_SKIP_BUILDINGS_AFTER = 1.5f; @@ -142,15 +145,12 @@ public class GeocodingUtilities { RoutePlannerFrontEnd rp = new RoutePlannerFrontEnd(); List lst = new ArrayList(); List listR = new ArrayList(); - rp.findRouteSegment(lat, lon, ctx, listR); + // we allow duplications to search in both files for boundary regions + rp.findRouteSegment(lat, lon, ctx, listR, false, true); double distSquare = 0; - TLongHashSet set = new TLongHashSet(); - Set streetNames = new HashSet(); + Map> streetNames = new HashMap<>(); for (RouteSegmentPoint p : listR) { RouteDataObject road = p.getRoad(); - if (!set.add(road.getId())) { - continue; - } // System.out.println(road.toString() + " " + Math.sqrt(p.distSquare)); String name = Algorithms.isEmpty(road.getName()) ? road.getRef("", false, true) : road.getName(); if (allowEmptyNames || !Algorithms.isEmpty(name)) { @@ -164,7 +164,13 @@ public class GeocodingUtilities { sr.connectionPoint = new LatLon(MapUtils.get31LatitudeY(p.preciseY), MapUtils.get31LongitudeX(p.preciseX)); sr.regionFP = road.region.getFilePointer(); sr.regionLen = road.region.getLength(); - if (streetNames.add(sr.streetName)) { + List plst = streetNames.get(sr.streetName); + if (plst == null) { + plst = new ArrayList(); + streetNames.put(sr.streetName, plst); + } + if (!plst.contains(road.region)) { + plst.add(road.region); lst.add(sr); } } @@ -308,6 +314,48 @@ public class GeocodingUtilities { return res; } + public void filterDuplicateRegionResults(final List res) { + Collections.sort(res, DISTANCE_COMPARATOR); + // filter duplicate city results (when building is in both regions on boundary) + for (int i = 0; i < res.size() - 1;) { + int cmp = cmpResult(res.get(i), res.get(i + 1)); + if (cmp > 0) { + res.remove(i); + } else if (cmp < 0) { + res.remove(i + 1); + } else { + // nothing to delete + i++; + } + } + } + + private int cmpResult(GeocodingResult gr1, GeocodingResult gr2) { + boolean eqStreet = Algorithms.stringsEqual(gr1.streetName, gr2.streetName); + if (eqStreet) { + boolean sameObj = false; + if (gr1.building != null && gr2.building != null) { + if (Algorithms.stringsEqual(gr1.building.getName(), gr2.building.getName())) { + // same building + sameObj = true; + } + } else if (gr1.building == null && gr2.building == null) { + // same street + sameObj = true; + } + if (sameObj) { + double cityDist1 = MapUtils.getDistance(gr1.searchPoint, gr1.city.getLocation()); + double cityDist2 = MapUtils.getDistance(gr2.searchPoint, gr2.city.getLocation()); + if (cityDist1 < cityDist2) { + return -1; + } else { + return 1; + } + } + } + return 0; + } + private List loadStreetBuildings(final GeocodingResult road, BinaryMapIndexReader reader, GeocodingResult street) throws IOException { final List streetBuildings = new ArrayList(); diff --git a/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java index c5f713cdf6..bfe638d394 100644 --- a/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java +++ b/OsmAnd-java/src/main/java/net/osmand/binary/RouteDataObject.java @@ -1,12 +1,15 @@ package net.osmand.binary; import net.osmand.Location; +import net.osmand.PlatformUtil; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion; import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteTypeRule; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import net.osmand.util.TransliterationHelper; +import org.apache.commons.logging.Log; + import java.text.MessageFormat; import java.util.Arrays; @@ -34,7 +37,7 @@ public class RouteDataObject { public int[] nameIds; // mixed array [0, height, cumulative_distance height, cumulative_distance, height, ...] - length is length(points)*2 public float[] heightDistanceArray = null; - + private static final Log LOG = PlatformUtil.getLog(RouteDataObject.class); public RouteDataObject(RouteRegion region) { this.region = region; } @@ -56,6 +59,7 @@ public class RouteDataObject { this.pointsY = copy.pointsY; this.types = copy.types; this.names = copy.names; + this.nameIds = copy.nameIds; this.restrictions = copy.restrictions; this.restrictionsVia = copy.restrictionsVia; this.pointTypes = copy.pointTypes; @@ -426,12 +430,19 @@ public class RouteDataObject { int[] opointsX = pointsX; int[] opointsY = pointsY; int[][] opointTypes = pointTypes; + String[][] opointNames = pointNames; + int[][] opointNameTypes = pointNameTypes; pointsX = new int[pointsX.length + 1]; pointsY = new int[pointsY.length + 1]; boolean insTypes = this.pointTypes != null && this.pointTypes.length > pos; + boolean insNames = this.pointNames != null && this.pointNames.length > pos; if (insTypes) { pointTypes = new int[opointTypes.length + 1][]; } + if (insNames) { + pointNames = new String[opointNames.length + 1][]; + pointNameTypes = new int[opointNameTypes.length +1][]; + } int i = 0; for (; i < pos; i++) { pointsX[i] = opointsX[i]; @@ -439,18 +450,32 @@ public class RouteDataObject { if (insTypes) { pointTypes[i] = opointTypes[i]; } + if (insNames) { + pointNames[i] = opointNames[i]; + pointNameTypes[i] = opointNameTypes[i]; + } } pointsX[i] = x31; pointsY[i] = y31; if (insTypes) { pointTypes[i] = null; } + if (insNames) { + pointNames[i] = null; + pointNameTypes[i] = null; + } for (i = i + 1; i < pointsX.length; i++) { pointsX[i] = opointsX[i - 1]; pointsY[i] = opointsY[i - 1]; if (insTypes && i < pointTypes.length) { pointTypes[i] = opointTypes[i - 1]; } + if (insNames && i < pointNames.length) { + pointNames[i] = opointNames[i - 1]; + } + if (insNames && i < pointNameTypes.length) { + pointNameTypes[i] = opointNameTypes[i - 1]; + } } } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java b/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java index cf7eacd2ee..6b8926b413 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/BinaryRoutePlanner.java @@ -68,7 +68,6 @@ public class BinaryRoutePlanner { FinalRouteSegment searchRouteInternal(final RoutingContext ctx, RouteSegmentPoint start, RouteSegmentPoint end, RouteSegment recalculationEnd ) throws InterruptedException, IOException { // measure time - ctx.timeToLoad = 0; ctx.memoryOverhead = 1000; // Initializing priority queue to visit way segments @@ -120,7 +119,9 @@ public class BinaryRoutePlanner { if (ctx.memoryOverhead > ctx.config.memoryLimitation * 0.95) { throw new IllegalStateException("There is not enough memory " + ctx.config.memoryLimitation / (1 << 20) + " Mb"); } - ctx.visitedSegments ++; + if (ctx.calculationProgress != null) { + ctx.calculationProgress.visitedSegments++; + } if (forwardSearch) { boolean doNotAddIntersections = onlyBackward; processRouteSegment(ctx, false, graphDirectSegments, visitedDirectSegments, @@ -164,12 +165,14 @@ public class BinaryRoutePlanner { throw new InterruptedException("Route calculation interrupted"); } } - ctx.visitedSegments += visitedDirectSegments.size() + visitedOppositeSegments.size(); - ctx.visitedDirectSegments += visitedDirectSegments.size(); - ctx.visitedOppositeSegments += visitedOppositeSegments.size(); - ctx.directQueueSize = graphDirectSegments.size(); // Math.max(ctx.directQueueSize, graphDirectSegments.size()); - ctx.oppositeQueueSize = graphReverseSegments.size(); - ctx.visitedOppositeSegments += visitedOppositeSegments.size(); + if (ctx.calculationProgress != null) { + ctx.calculationProgress.visitedDirectSegments += visitedDirectSegments.size(); + ctx.calculationProgress.visitedOppositeSegments += visitedOppositeSegments.size(); + ctx.calculationProgress.directQueueSize += graphDirectSegments.size(); // Math.max(ctx.directQueueSize, + // graphDirectSegments.size()); + ctx.calculationProgress.oppositeQueueSize += graphReverseSegments.size(); + ctx.calculationProgress.visitedOppositeSegments += visitedOppositeSegments.size(); + } return finalSegment; } @@ -371,18 +374,21 @@ public class BinaryRoutePlanner { } public static void printDebugMemoryInformation(RoutingContext ctx) { - printInfo(String.format("Time. Total: %.2f, to load: %.2f, to load headers: %.2f, to calc dev: %.2f ", - (System.nanoTime() - ctx.timeToCalculate) / 1e6, ctx.timeToLoad / 1e6, - ctx.timeToLoadHeaders / 1e6, ctx.timeNanoToCalcDeviation / 1e6)); -// GeneralRouter.TIMER = 0; - int maxLoadedTiles = Math.max(ctx.maxLoadedTiles, ctx.getCurrentlyLoadedTiles()); - printInfo("Current loaded tiles : " + ctx.getCurrentlyLoadedTiles() + ", maximum loaded tiles " + maxLoadedTiles); - printInfo("Loaded tiles " + ctx.loadedTiles + " (distinct " + ctx.distinctLoadedTiles + "), unloaded tiles " + ctx.unloadedTiles + - ", loaded more than once same tiles " - + ctx.loadedPrevUnloadedTiles); - printInfo("Visited segments " + ctx.visitedSegments + ", relaxed roads " + ctx.relaxedSegments); - printInfo("Priority queues sizes : " + ctx.directQueueSize + "/" + ctx.oppositeQueueSize); - printInfo("Visited interval sizes: " + ctx.visitedDirectSegments + "/" + ctx.visitedOppositeSegments); + if (ctx.calculationProgress != null) { + RouteCalculationProgress p = ctx.calculationProgress; + printInfo(String.format("Time. Total: %.2f, to load: %.2f, to load headers: %.2f, to find start/end: %.2f, extra: %.2f ", + p.timeToCalculate / 1e6, p.timeToLoad / 1e6, p.timeToLoadHeaders / 1e6, + p.timeToFindInitialSegments / 1e6, p.timeNanoToCalcDeviation / 1e6)); + // GeneralRouter.TIMER = 0; + int maxLoadedTiles = Math.max(p.maxLoadedTiles, ctx.getCurrentlyLoadedTiles()); + printInfo("Current loaded tiles : " + ctx.getCurrentlyLoadedTiles() + ", maximum loaded tiles " + + maxLoadedTiles); + printInfo("Loaded tiles " + p.loadedTiles + " (distinct " + p.distinctLoadedTiles + "), unloaded tiles " + + p.unloadedTiles + ", loaded more than once same tiles " + p.loadedPrevUnloadedTiles); + printInfo("Visited segments: " + ctx.getVisitedSegments() + ", relaxed roads " + p.relaxedSegments); + printInfo("Priority queues sizes : " + p.directQueueSize + "/" + p.oppositeQueueSize); + printInfo("Visited interval sizes: " + p.visitedDirectSegments + "/" + p.visitedOppositeSegments); + } } @@ -849,6 +855,7 @@ public class BinaryRoutePlanner { } public static class RouteSegmentPoint extends RouteSegment { + public RouteSegmentPoint(RouteDataObject road, int segmentStart, double distSquare) { super(road, segmentStart); this.distSquare = distSquare; @@ -873,6 +880,11 @@ public class BinaryRoutePlanner { } + @Override + public String toString() { + return String.format("%d (%s): %s", segStart, getPreciseLatLon(), road); + } + } public static class RouteSegment { diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteCalculationProgress.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteCalculationProgress.java index b34c2fd5bb..eb93e95699 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteCalculationProgress.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteCalculationProgress.java @@ -12,12 +12,29 @@ public class RouteCalculationProgress { public float totalEstimatedDistance = 0; public float routingCalculatedTime = 0; - public int loadedTiles = 0; + + public int relaxedSegments = 0; public int visitedSegments = 0; + public int visitedDirectSegments = 0; + public int visitedOppositeSegments = 0; + public int directQueueSize = 0; + public int oppositeQueueSize = 0; public int totalIterations = 1; public int iteration = -1; + public long timeNanoToCalcDeviation = 0; + public long timeToLoad = 0; + public long timeToLoadHeaders = 0; + public long timeToFindInitialSegments = 0; + public long timeToCalculate = 0; + + public int distinctLoadedTiles = 0; + public int maxLoadedTiles = 0; + public int loadedPrevUnloadedTiles = 0; + public int unloadedTiles = 0; + public int loadedTiles = 0; + public boolean isCancelled; public boolean requestPrivateAccessRouting; diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java index 108e00f2c9..826a40dbb8 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java @@ -117,15 +117,21 @@ public class RoutePlannerFrontEnd { } public RouteSegmentPoint findRouteSegment(double lat, double lon, RoutingContext ctx, List list, boolean transportStop) throws IOException { + return findRouteSegment(lat, lon, ctx, list, false, false); + } + + public RouteSegmentPoint findRouteSegment(double lat, double lon, RoutingContext ctx, List list, boolean transportStop, + boolean allowDuplications) throws IOException { + long now = System.nanoTime(); int px = MapUtils.get31TileNumberX(lon); int py = MapUtils.get31TileNumberY(lat); ArrayList dataObjects = new ArrayList(); - ctx.loadTileData(px, py, 17, dataObjects); + ctx.loadTileData(px, py, 17, dataObjects, allowDuplications); if (dataObjects.isEmpty()) { - ctx.loadTileData(px, py, 15, dataObjects); + ctx.loadTileData(px, py, 15, dataObjects, allowDuplications); } if (dataObjects.isEmpty()) { - ctx.loadTileData(px, py, 14, dataObjects); + ctx.loadTileData(px, py, 14, dataObjects, allowDuplications); } if (list == null) { list = new ArrayList(); @@ -167,6 +173,9 @@ public class RoutePlannerFrontEnd { return Double.compare(o1.distSquare, o2.distSquare); } }); + if (ctx.calculationProgress != null) { + ctx.calculationProgress.timeToFindInitialSegments += (System.nanoTime() - now); + } if (list.size() > 0) { RouteSegmentPoint ps = null; if (ctx.publicTransport) { @@ -203,12 +212,12 @@ public class RoutePlannerFrontEnd { useSmartRouteRecalculation = use; } - // TODO native matches less roads public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List points) throws IOException, InterruptedException { - gctx.ctx.timeToCalculate = System.nanoTime(); + long timeToCalculate = System.nanoTime(); if (gctx.ctx.calculationProgress == null) { gctx.ctx.calculationProgress = new RouteCalculationProgress(); } + gctx.ctx.keepNativeRoutingContext = true; List gpxPoints = generageGpxPoints(points, gctx); GpxPoint start = null; GpxPoint prev = null; @@ -270,6 +279,10 @@ public class RoutePlannerFrontEnd { } start = next; } + if(gctx.ctx.calculationProgress != null) { + gctx.ctx.calculationProgress.timeToCalculate = System.nanoTime() - timeToCalculate; + } + gctx.ctx.deleteNativeRoutingContext(); BinaryRoutePlanner.printDebugMemoryInformation(gctx.ctx); calculateGpxRoute(gctx, gpxPoints); if (!gctx.res.isEmpty()) { @@ -338,8 +351,8 @@ public class RoutePlannerFrontEnd { } if (gctx.distFromLastPoint(startPoint) > 1) { gctx.routeGapDistance += gctx.distFromLastPoint(startPoint); - System.out.println(String.format("????? gap of route point = %f, gap of actual gpxPoint = %f ", - gctx.distFromLastPoint(startPoint), gctx.distFromLastPoint(pnt.loc))); + System.out.println(String.format("????? gap of route point = %f, gap of actual gpxPoint = %f, %s ", + gctx.distFromLastPoint(startPoint), gctx.distFromLastPoint(pnt.loc), pnt.loc)); } gctx.res.addAll(pnt.routeToTarget); i = pnt.targetInd; @@ -524,7 +537,11 @@ public class RoutePlannerFrontEnd { // start point could shift to +-1 due to direction res.get(0).setStartPointIndex(start.pnt.getSegmentStart()); } else { - //throw new IllegalStateException("TODO"); + // for native routing this is possible when point lies on intersection of 2 lines + // solution here could be to pass to native routing id of the route + // though it should not create any issue + System.out.println("??? not found " + start.pnt.getRoad().getId() + " instead " + + res.get(0).getObject().getId()); } } start.routeToTarget = res; @@ -585,7 +602,7 @@ public class RoutePlannerFrontEnd { public List searchRoute(final RoutingContext ctx, LatLon start, LatLon end, List intermediates, PrecalculatedRouteDirection routeDirection) throws IOException, InterruptedException { - ctx.timeToCalculate = System.nanoTime(); + long timeToCalculate = System.nanoTime(); if (ctx.calculationProgress == null) { ctx.calculationProgress = new RouteCalculationProgress(); } @@ -617,6 +634,7 @@ public class RoutePlannerFrontEnd { } routeDirection = PrecalculatedRouteDirection.build(ls, ctx.config.DEVIATION_RADIUS, ctx.getRouter().getMaxSpeed()); } + List res ; if (intermediatesEmpty && ctx.nativeLib != null) { ctx.startX = MapUtils.get31TileNumberX(start.getLongitude()); ctx.startY = MapUtils.get31TileNumberY(start.getLatitude()); @@ -630,31 +648,32 @@ public class RoutePlannerFrontEnd { ctx.precalculatedRouteDirection = routeDirection.adopt(ctx); } ctx.calculationProgress.nextIteration(); - List res = runNativeRouting(ctx, recalculationEnd); - if (res != null) { - new RouteResultPreparation().printResults(ctx, start, end, res); - } + res = runNativeRouting(ctx, recalculationEnd); makeStartEndPointsPrecise(res, start, end, intermediates); - return res; - } - int indexNotFound = 0; - List points = new ArrayList(); - if (!addSegment(start, ctx, indexNotFound++, points, ctx.startTransportStop)) { - return null; - } - if (intermediates != null) { - for (LatLon l : intermediates) { - if (!addSegment(l, ctx, indexNotFound++, points, false)) { - System.out.println(points.get(points.size() - 1).getRoad().toString()); - return null; + } else { + int indexNotFound = 0; + List points = new ArrayList(); + if (!addSegment(start, ctx, indexNotFound++, points, ctx.startTransportStop)) { + return null; + } + if (intermediates != null) { + for (LatLon l : intermediates) { + if (!addSegment(l, ctx, indexNotFound++, points, false)) { + System.out.println(points.get(points.size() - 1).getRoad().toString()); + return null; + } } } + if (!addSegment(end, ctx, indexNotFound++, points, ctx.targetTransportStop)) { + return null; + } + ctx.calculationProgress.nextIteration(); + res = searchRouteImpl(ctx, points, routeDirection); } - if (!addSegment(end, ctx, indexNotFound++, points, ctx.targetTransportStop)) { - return null; + if (ctx.calculationProgress != null) { + ctx.calculationProgress.timeToCalculate += (System.nanoTime() - timeToCalculate); } - ctx.calculationProgress.nextIteration(); - List res = searchRouteImpl(ctx, points, routeDirection); + BinaryRoutePlanner.printDebugMemoryInformation(ctx); if (res != null) { new RouteResultPreparation().printResults(ctx, start, end, res); } @@ -769,8 +788,12 @@ public class RoutePlannerFrontEnd { if (ctx.nativeLib != null) { ctx.startX = start.preciseX; ctx.startY = start.preciseY; + ctx.startRoadId = start.road.id; + ctx.startSegmentInd = start.segStart; ctx.targetX = end.preciseX; ctx.targetY = end.preciseY; + ctx.targetRoadId = end.road.id; + ctx.targetSegmentInd = end.segStart; return runNativeRouting(ctx, recalculationEnd); } else { refreshProgressDistance(ctx); @@ -834,11 +857,9 @@ public class RoutePlannerFrontEnd { ctx.checkOldRoutingFiles(ctx.startX, ctx.startY); ctx.checkOldRoutingFiles(ctx.targetX, ctx.targetY); - long time = System.currentTimeMillis(); - RouteSegmentResult[] res = ctx.nativeLib.runNativeRouting(ctx.startX, ctx.startY, ctx.targetX, ctx.targetY, - ctx.config, regions, ctx.calculationProgress, ctx.precalculatedRouteDirection, ctx.calculationMode == RouteCalculationMode.BASE, - ctx.publicTransport, ctx.startTransportStop, ctx.targetTransportStop); - log.info("Native routing took " + (System.currentTimeMillis() - time) / 1000f + " seconds"); + // long time = System.currentTimeMillis(); + RouteSegmentResult[] res = ctx.nativeLib.runNativeRouting(ctx, regions, ctx.calculationMode == RouteCalculationMode.BASE); + // log.info("Native routing took " + (System.currentTimeMillis() - time) / 1000f + " seconds"); ArrayList result = new ArrayList(Arrays.asList(res)); if (recalculationEnd != null) { log.info("Native routing use precalculated route"); @@ -849,9 +870,7 @@ public class RoutePlannerFrontEnd { current = pr; } } - ctx.routingTime = ctx.calculationProgress.routingCalculatedTime; - ctx.visitedSegments = ctx.calculationProgress.visitedSegments; - ctx.loadedTiles = ctx.calculationProgress.loadedTiles; + ctx.routingTime += ctx.calculationProgress.routingCalculatedTime; return new RouteResultPreparation().prepareResult(ctx, result, recalculationEnd != null); } @@ -865,7 +884,6 @@ public class RoutePlannerFrontEnd { } pringGC(ctx, true); List res = searchRouteInternalPrepare(ctx, points.get(0), points.get(1), routeDirection); - BinaryRoutePlanner.printDebugMemoryInformation(ctx); pringGC(ctx, false); makeStartEndPointsPrecise(res, points.get(0).getPreciseLatLon(), points.get(1).getPreciseLatLon(), null); return res; @@ -912,16 +930,7 @@ public class RoutePlannerFrontEnd { List res = searchRouteInternalPrepare(local, points.get(i), points.get(i + 1), routeDirection); makeStartEndPointsPrecise(res, points.get(i).getPreciseLatLon(), points.get(i + 1).getPreciseLatLon(), null); results.addAll(res); - ctx.distinctLoadedTiles += local.distinctLoadedTiles; - ctx.loadedTiles += local.loadedTiles; - ctx.visitedSegments += local.visitedSegments; - ctx.loadedPrevUnloadedTiles += local.loadedPrevUnloadedTiles; - ctx.timeToCalculate += local.timeToCalculate; - ctx.timeToLoad += local.timeToLoad; - ctx.timeToLoadHeaders += local.timeToLoadHeaders; - ctx.relaxedSegments += local.relaxedSegments; ctx.routingTime += local.routingTime; - // local.unloadAllData(ctx); if (restPartRecalculatedRoute != null) { results.addAll(restPartRecalculatedRoute); diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java index b0c32de648..d7ebbaba8f 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteResultPreparation.java @@ -394,8 +394,8 @@ public class RouteResultPreparation { private List convertFinalSegmentToResults(RoutingContext ctx, FinalRouteSegment finalSegment) { List result = new ArrayList(); if (finalSegment != null) { - ctx.routingTime = finalSegment.distanceFromStart; - println("Routing calculated time distance " + finalSegment.distanceFromStart); + ctx.routingTime += finalSegment.distanceFromStart; + // println("Routing calculated time distance " + finalSegment.distanceFromStart); // Get results from opposite direction roads RouteSegment segment = finalSegment.reverseWaySearch ? finalSegment : finalSegment.opposite.getParentRoute(); @@ -496,8 +496,9 @@ public class RouteResultPreparation { String msg = String.format("", - ctx.config.routerName, startLat, startLon, endLat, endLon, ctx.routingTime, ctx.loadedTiles, - ctx.visitedSegments, completeDistance, completeTime); + ctx.config.routerName, startLat, startLon, endLat, endLon, ctx.routingTime, + ctx.getLoadedTiles(), + ctx.getVisitedSegments(), completeDistance, completeTime); // String msg = MessageFormat.format("", // startLat + "", startLon + "", endLat + "", endLon + "", ctx.config.routerName, diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java b/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java index e3c233b4d4..922e225855 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutingContext.java @@ -40,8 +40,6 @@ public class RoutingContext { private final static Log log = PlatformUtil.getLog(RoutingContext.class); - - // Final context variables public final RoutingConfiguration config; @@ -50,23 +48,31 @@ public class RoutingContext { public final Map> map = new LinkedHashMap>(); public final Map reverseMap = new LinkedHashMap(); + // 0. Reference to native routingcontext for multiple routes + public long nativeRoutingContext; + public boolean keepNativeRoutingContext; + // 1. Initial variables public int startX; public int startY; + public long startRoadId; + public int startSegmentInd; public boolean startTransportStop; public int targetX; public int targetY; + public long targetRoadId; + public int targetSegmentInd; public boolean targetTransportStop; + public boolean publicTransport; - // deprecated - public long firstRoadId; - public int firstRoadDirection; + public RouteCalculationProgress calculationProgress; public boolean leftSideNavigation; public List previouslyCalculatedRoute; public PrecalculatedRouteDirection precalculatedRouteDirection; + // 2. Routing memory cache (big objects) TLongObjectHashMap> indexedSubregions = new TLongObjectHashMap>(); @@ -82,26 +88,8 @@ public class RoutingContext { public TileStatistics global = new TileStatistics(); // updated by route planner in bytes public int memoryOverhead = 0; - - - long timeNanoToCalcDeviation = 0; - long timeToLoad = 0; - long timeToLoadHeaders = 0; - long timeToFindInitialSegments = 0; - public long timeToCalculate = 0; - - int distinctLoadedTiles = 0; - int maxLoadedTiles = 0; - int loadedPrevUnloadedTiles = 0; - int unloadedTiles = 0; public float routingTime = 0; - public int loadedTiles = 0; - public int visitedSegments = 0; - public int relaxedSegments = 0; - public int visitedDirectSegments = 0; - public int visitedOppositeSegments = 0; - public int directQueueSize = 0; - public int oppositeQueueSize = 0; + // callback of processing segments RouteSegmentVisitor visitor = null; @@ -207,12 +195,16 @@ public class RoutingContext { public void initStartAndTargetPoints(RouteSegment start, RouteSegment end) { initTargetPoint(end); startX = start.road.getPoint31XTile(start.getSegmentStart()); - startY = start.road.getPoint31YTile(start.getSegmentStart()); + startY = start.road.getPoint31YTile(start.getSegmentStart()); + startRoadId = start.road.getId(); + startSegmentInd = start.getSegmentStart(); } public void initTargetPoint(RouteSegment end) { targetX = end.road.getPoint31XTile(end.getSegmentStart()); targetY = end.road.getPoint31YTile(end.getSegmentStart()); + targetRoadId = end.road.getId(); + targetSegmentInd = end.getSegmentStart(); } public void unloadAllData() { @@ -224,7 +216,9 @@ public class RoutingContext { if (tl.isLoaded()) { if(except == null || except.searchSubregionTile(tl.subregion) < 0){ tl.unload(); - unloadedTiles ++; + if(calculationProgress != null) { + calculationProgress.unloadedTiles ++; + } global.size -= tl.tileStatistics.size; } } @@ -308,27 +302,37 @@ public class RoutingContext { } catch (IOException e) { throw new RuntimeException("Loading data exception", e); } - - timeToLoad += (System.nanoTime() - now); + if (calculationProgress != null) { + calculationProgress.timeToLoad += (System.nanoTime() - now); + } } else { long now = System.nanoTime(); NativeRouteSearchResult ns = nativeLib.loadRouteRegion(ts.subregion, loadObjectsInMemory); // System.out.println(ts.subregion.shiftToData + " " + Arrays.toString(ns.objects)); ts.setLoadedNative(ns, this); - timeToLoad += (System.nanoTime() - now); + if (calculationProgress != null) { + calculationProgress.timeToLoad += (System.nanoTime() - now); + } } - loadedTiles++; + if (calculationProgress != null) { + calculationProgress.loadedTiles++; + } + if (wasUnloaded) { if(ucount == 1) { - loadedPrevUnloadedTiles++; + if(calculationProgress != null) { + calculationProgress.loadedPrevUnloadedTiles++; + } } } else { if(global != null) { global.allRoutes += ts.tileStatistics.allRoutes; global.coordinates += ts.tileStatistics.coordinates; } - distinctLoadedTiles++; + if (calculationProgress != null) { + calculationProgress.distinctLoadedTiles++; + } } global.size += ts.tileStatistics.size; } @@ -402,7 +406,9 @@ public class RoutingContext { } collection.add(found); } - timeToLoadHeaders += (System.nanoTime() - now); + if (calculationProgress != null) { + calculationProgress.timeToLoadHeaders += (System.nanoTime() - now); + } } } catch (IOException e) { throw new RuntimeException("Loading data exception", e); @@ -412,6 +418,10 @@ public class RoutingContext { } public void loadTileData(int x31, int y31, int zoomAround, final List toFillIn) { + loadTileData(x31, y31, zoomAround, toFillIn, false); + } + + public void loadTileData(int x31, int y31, int zoomAround, final List toFillIn, boolean allowDuplications) { int t = config.ZOOM_TO_LOAD_TILES - zoomAround; int coordinatesShift = (1 << (31 - config.ZOOM_TO_LOAD_TILES)); if(t <= 0) { @@ -422,7 +432,6 @@ public class RoutingContext { } TLongHashSet ts = new TLongHashSet(); - long now = System.nanoTime(); for(int i = -t; i <= t; i++) { for(int j = -t; j <= t; j++) { ts.add(getRoutingTile(x31 +i*coordinatesShift, y31 + j*coordinatesShift, 0)); @@ -432,8 +441,10 @@ public class RoutingContext { TLongObjectHashMap excludeDuplications = new TLongObjectHashMap(); while (it.hasNext()) { getAllObjects(it.next(), toFillIn, excludeDuplications); + if (allowDuplications) { + excludeDuplications.clear(); + } } - timeToFindInitialSegments += (System.nanoTime() - now); } @SuppressWarnings("unused") @@ -516,7 +527,9 @@ public class RoutingContext { loaded++; } } - maxLoadedTiles = Math.max(maxLoadedTiles, getCurrentlyLoadedTiles()); + if(calculationProgress != null) { + calculationProgress.maxLoadedTiles = Math.max(calculationProgress.maxLoadedTiles, getCurrentlyLoadedTiles()); + } Collections.sort(list, new Comparator() { private int pow(int base, int pw) { int r = 1; @@ -538,7 +551,9 @@ public class RoutingContext { i++; // System.out.println("Unload " + unload); unload.unload(); - unloadedTiles ++; + if(calculationProgress != null) { + calculationProgress.unloadedTiles ++; + } global.size -= unload.tileStatistics.size; // tile could be cleaned from routing tiles and deleted from whole list @@ -789,7 +804,31 @@ public class RoutingContext { return map.keySet().toArray(new BinaryMapIndexReader[map.size()]); } - + public int getVisitedSegments() { + if(calculationProgress != null) { + return calculationProgress.visitedSegments; + } + return 0; + } + public int getLoadedTiles() { + if (calculationProgress != null) { + return calculationProgress.loadedTiles; + } + return 0; + } + + public synchronized void deleteNativeRoutingContext() { + if (nativeRoutingContext != 0) { + NativeLibrary.deleteNativeRoutingContext(nativeRoutingContext); + } + nativeRoutingContext = 0; + } + + @Override + protected void finalize() throws Throwable { + deleteNativeRoutingContext(); + super.finalize(); + } } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TestRouting.java b/OsmAnd-java/src/main/java/net/osmand/router/TestRouting.java index 78222819d9..95e2e0d15c 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TestRouting.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TestRouting.java @@ -236,13 +236,13 @@ public class TestRouting { throw new IllegalArgumentException(MessageFormat.format("Complete routing time (expected) {0} != {1} (original) : {2}", routing_time, calcRoutingTime, testDescription)); } - if (visitedSegments > 0 && !isInOrLess(visitedSegments, ctx.visitedSegments, percent)) { + if (visitedSegments > 0 && !isInOrLess(visitedSegments, ctx.getVisitedSegments(), percent)) { throw new IllegalArgumentException(MessageFormat.format("Visited segments (expected) {0} != {1} (original) : {2}", visitedSegments, - ctx.visitedSegments, testDescription)); + ctx.getVisitedSegments(), testDescription)); } - if (loadedTiles > 0 && !isInOrLess(loadedTiles, ctx.loadedTiles, percent)) { + if (loadedTiles > 0 && !isInOrLess(loadedTiles, ctx.getLoadedTiles(), percent)) { throw new IllegalArgumentException(MessageFormat.format("Loaded tiles (expected) {0} != {1} (original) : {2}", loadedTiles, - ctx.loadedTiles, testDescription)); + ctx.getLoadedTiles(), testDescription)); } if(TEST_BOTH_DIRECTION){ diff --git a/OsmAnd-telegram/res/values-be/strings.xml b/OsmAnd-telegram/res/values-be/strings.xml index eec8513da5..1051d6b1fd 100644 --- a/OsmAnd-telegram/res/values-be/strings.xml +++ b/OsmAnd-telegram/res/values-be/strings.xml @@ -85,7 +85,7 @@ Рэгістрацыя ў Telegram Для абмену вам неабходны акаўнт Тэлеграм. Калі ласка, ўсталюйце Тэлеграм і наладзьце акаўнт. - Пасля гэтага вы зможаце выкарыстоўваць дадатак. + Пасля гэтага вы зможаце выкарыстоўваць праграму. Усе Выкл Вам неабходна мець акаўнт Тэлеграм і нумар тэлефона @@ -125,7 +125,7 @@ Працягнуць Скасаваць Налады - Дадатак не мае дазволу на доступ да даных аб месцазнаходжанні. + Праграма не мае дазволу на доступ да даных аб месцазнаходжанні. Калі ласка, ўключыце \"Месцазнаходжанне\" ў сістэмных наладах Абярыце аднаго пастаўшчыка месцазнаходжання, каб падзяліцца сваім месцазнаходжаннем. Фонавы рэжым @@ -168,7 +168,7 @@ г хвіл сек - Назіральнік OsmAnd Дае магчымасць дзяліцца сваім месцазнаходжаннем і бачыць месцазнаходжанне іншых у OsmAnd.

Дадатак выкарыстоўвае Telegram API, таму вам неабходны акаўнт Тэлеграм.
+ Назіральнік OsmAnd Дае магчымасць дзяліцца сваім месцазнаходжаннем і бачыць месцазнаходжанне іншых у OsmAnd.

Праграма выкарыстоўвае Telegram API, таму вам неабходны акаўнт Тэлеграм.
Маё месцазнаходжанне Зараз дзейнічае Адправіць месцазнаходжанне як @@ -200,7 +200,7 @@ Уключыць маніторынг, каб захоўваць пункты месцазнаходжання ў гісторыі. Назіральнік OsmAnd Telegram - Telegram (дадатак для ліставання) выкарыстоўваецца для зносін паміж людзьмі. + Telegram (праграма для ліставання) выкарыстоўваецца для зносін паміж людзьмі. Назіральнік OsmAnd - адзін з кліентаў для адкрытай платформы Telegram. Вашыя кантакты могуць выкарыстоўваць іншы кліент. Націскаючы \"Працягнуць\" вы пагаджаецеся з палітыкай прыватнасці Telegram і OsmAnd. Ухваліць diff --git a/OsmAnd-telegram/res/values-fr/strings.xml b/OsmAnd-telegram/res/values-fr/strings.xml index e010baf46b..9ebff1a4d8 100644 --- a/OsmAnd-telegram/res/values-fr/strings.xml +++ b/OsmAnd-telegram/res/values-fr/strings.xml @@ -248,4 +248,20 @@ Partager la position Afficher sur la carte Vous avez besoin d\'un compte Telegram enregistré et d\'un numéro de téléphone + OsmAnd Online GPS Tracker + Sélectionnez l’un des services de localisation pour partager votre position. + OsmAnd Tracker vous permet de partager votre position et voir celle des autres dans OsmAnd.

Cette application utilise l\'API de Telegram, et donc vous avez besoin d\'un compte Telegram.
+ Vous avez besoin d\'installer la version gratuite ou payante d\'OsmAnd d\'abord + OsmAnd Tracker s\'exécute en arrière-plan, écran éteint. + Merci d\'activer la géolocalisation dans les paramètres du système + Numéro de téléphone au format international + Numéro de téléphone + Recherche : groupe ou contact + Sélectionner les contacts et les groupes avec lesquels vous souhaitez partager votre position. + Définir l\'heure + Heure visible par tous + Rendre l\'heure visible par tous + Définir l\'intervalle minimum pour partager sa position. + La dernière fois qu\'un contact s\'est déplacé. + Cacher les contacts qui ne se sont pas déplacés depuis un temps donné. \ No newline at end of file diff --git a/OsmAnd-telegram/res/values-pl/strings.xml b/OsmAnd-telegram/res/values-pl/strings.xml index 426e4ad507..22e12de229 100644 --- a/OsmAnd-telegram/res/values-pl/strings.xml +++ b/OsmAnd-telegram/res/values-pl/strings.xml @@ -142,9 +142,7 @@ h min sek - - Nadajnik OsmAnd pozwala Ci udostępniać swoją lokalizację i widzieć ją w OsmAnd.
-
Aplikacja używa API Telegram, a więc potrzebujesz konta Telegram.
+ Nadajnik OsmAnd pozwala Ci udostępniać swoją lokalizację i widzieć ją w OsmAnd.

Aplikacja używa API Telegram, a więc potrzebujesz konta Telegram.
Moja lokalizacja Na żywo Wybierz nazwę, której jeszcze nie używasz diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index 5a0082b792..e1508f6ba2 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -955,6 +955,7 @@ android:process="net.osmand.plus" android:label="@string/process_navigation_service" android:name="net.osmand.plus.NavigationService" + android:foregroundServiceType="location" android:stopWithTask="false"> diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index 79c1027c84..714b85eae8 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -22,8 +22,8 @@ task printc { } android { - compileSdkVersion 28 - buildToolsVersion "28.0.3" + compileSdkVersion 29 + buildToolsVersion "29.0.3" // compileNdkVersion "android-ndk-r17b" signingConfigs { diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index e56073c6c8..21346619a7 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -3806,4 +3806,8 @@ الحصول على معلومات حول النقاط المثيرة للاهتمام من ويكيبيديا. إنه دليلك غير المتصل بجيبك - ما عليك سوى تمكين المكون الإضافي ويكبيديا والاستمتاع بمقالات حول الكائنات من حولك. دراجة نارية سكوتر موتور + منحدرات للأمام + منحدرات + عربة التسوق + أغلق ملاحظة OSM \ No newline at end of file diff --git a/OsmAnd/res/values-be/phrases.xml b/OsmAnd/res/values-be/phrases.xml index 5a66eeae18..4e69352251 100644 --- a/OsmAnd/res/values-be/phrases.xml +++ b/OsmAnd/res/values-be/phrases.xml @@ -1049,7 +1049,7 @@ Асвятляльная вежа Выратавальная станцыя Толькі калі пераход дазволены - Не + Гук: не Так Без тактыльнага пакрыцця Так @@ -3638,4 +3638,12 @@ На адкрытым паветры Тып Статус + Даступна для механічнага транспартнага сродку: так + Даступна для механічнага транспартнага сродку: не + Даступна для механічнага транспартнага сродку: прыватны доступ + Стрэлка + Вібрацыя + Ціск + Відэа + SMS \ No newline at end of file diff --git a/OsmAnd/res/values-be/strings.xml b/OsmAnd/res/values-be/strings.xml index f02b3d7626..10ef38a0f0 100644 --- a/OsmAnd/res/values-be/strings.xml +++ b/OsmAnd/res/values-be/strings.xml @@ -7,16 +7,16 @@ Лупа мапы Асноўная мапа свету Версія: - Пра дадатак + Пра праграму Версія, ліцэнзіі, удзельнікі праекта - Спампаваныя маштабы: %1$s + Спампаваныя ўзроўні маштабавання: %1$s Тэрмін дзеяння (у хвілінах): %1$s Можна спампаваць: %1$s Максімальнае павелічэнне: %1$s Мінімальнае павелічэнне: %1$s Даныя фрагменту: %1$s Крыніца фрагментаў мапы «%1$s» захаваная - Эліптычны меркатар + Эліптычная праекцыя меркатара Максімальнае павелічэнне Тэрмін дзеяння (у хвілінах) Мінімальнае павелічэнне @@ -100,7 +100,7 @@ Наладзьце запіс вашых паездак. Паказвае налады ўключэння фонавага адсочвання і навігацыі праз перыядычнае абуджэнне GPS прылады (з выключаным экранам). Усталёўка версіі - Наладка выгляду дадатку. + Наладка выгляду праграмы. Выгляд Налады адмысловых магчымасцяў Вызначце адрас @@ -139,10 +139,10 @@ Прадвызначанае дзеянне віджэта Фармат вываду відэа: Фармат відэа - Выкарыстоўваць сістэмны дадатак для запісу відэа. - Выкарыстоўваць сістэмны дадатак для запісу - Выкарыстоўваць сістэмны дадатак для фота. - Выкарыстоўваць дадатак камеры + Выкарыстоўваць сістэмную праграму для запісу відэа. + Выкарыстоўваць сістэмную праграму для запісу + Выкарыстоўваць сістэмную праграму для фота. + Выкарыстоўваць праграму камеры Наладзіць параметры аўдыё і відэа. Налады аўдыё і відэа Запісаць не атрымалася @@ -186,10 +186,10 @@ Мапы толькі дарог Працаваць у бяспечным рэжыме (трохі павольней, але без уласных бібліятэк). Бяспечны рэжым - Дадатак працуе ў бяспечным рэжыме (адключыць ў «Наладах»). + Праграма працуе ў бяспечным рэжыме (адключыць ў «Наладах»). Фонавы рэжым OsmAnd па-ранейшаму працуе. Спыніць яго? Закрыць набор змен - Дадатак «ZXing Barcode Scanner» не ўсталяваны. Знайсці ў Google Play\? + Праграма «ZXing Barcode Scanner» не ўсталяваная. Знайсці ў Google Play\? Абярыце схему колераў дарог: Схема колераў дарог Паказваць напрамак да месца прызначэння @@ -237,19 +237,19 @@ Прывязвацца да дарог OsmAnd Мапы і навігацыя Прагляд глабальнай мабільнай мапы і навігатар для аўтаномных і сеціўных мапаў OSM - OsmAnd (OSM Automated Navigation Directions) -\n -\n -\nOsmAnd — навігацыйны дадатак з адкрытым кодам з доступам да разнастайных даных ад OpenStreetMap (OSM). Усе даныя (вектарныя і растравыя) можна захаваць на картцы памяці для аўтаномнага выкарыстання. Таксама падтрымліваецца аўтаномная і сеціўная маршрутызацыя, уключаючы пакрокавае галасавое суправаджэнне. -\n -\n + OsmAnd (OSM Automated Navigation Directions) +\n +\n +\nOsmAnd — навігацыйная праграма з адкрытым кодам з доступам да разнастайных даных ад OpenStreetMap (OSM). Усе даныя (вектарныя і растравыя) можна захаваць на картцы памяці для аўтаномнага выкарыстання. Таксама падтрымліваецца аўтаномная і сеціўная маршрутызацыя, уключаючы пакрокавае галасавое суправаджэнне. +\n +\n \nНекалькі асноўных магчымасцяў: \n \n - паўнавартасная праца без інтэрнэт-злучэння (захоўвае вектарныя або растравыя даныя ў памяці прылады); \n \n - кампактная вектарная мапа ўсяго свету; \n -\n - спампоўванне мапаў краін або рэгіёну непасрэдна ў дадатку; +\n - спампоўванне мапаў краін або рэгіёну непасрэдна ў праграме; \n \n - магчымасць адлюстравання звестак на мапе, напрыклад пласт для пракладкі маршруту або пласт з запісам GPX-следу, з POI, улюбёнымі мясцінамі, ізалініямі вышынь, грамадскім транспартам, дадатковымі мапамі з магчымасцю налады ўзроўню празрыстасці; \n @@ -257,7 +257,7 @@ \n \n - пракладка маршрутаў па-за сецівам на кароткія адлегласці (эксперыментальная функцыя); \n -\n - рэжымы для пешаходнай, аўтамабільнай і роваравай навігацыі з: +\n - рэжымы для пешаходнай, аўтамабільнай і роварнай навігацыі з: \n \n - магчымасцю аўтаматычнага пераключэння дзённага/начнога адлюстравання; \n @@ -282,7 +282,7 @@ \n \n \n -\n OsmAnd+ — навігацыйны дадатак з адкрытым кодам з доступам да разнастайных даных ад OpenStreetMap (OSM). Усе даныя (вектарныя і растравыя) можна захаваць на картцы памяці для далейшага аўтаномнага выкарыстання. Таксама падтрымліваецца аўтаномная і сеціўная маршрутызацыя, уключаючы пакрокавае галасавое суправаджэнне. +\n OsmAnd+ — навігацыйная праграма з адкрытым кодам з доступам да разнастайных даных ад OpenStreetMap (OSM). Усе даныя (вектарныя і растравыя) можна захаваць на картцы памяці для далейшага аўтаномнага выкарыстання. Таксама падтрымліваецца аўтаномная і сеціўная маршрутызацыя, уключаючы пакрокавае галасавое суправаджэнне. \n \n \n @@ -296,7 +296,7 @@ \n \n - кампактная вектарная мапа для ўсяго cвету; \n -\n - неабмежаваная колькасць спампоўванняў мапаў асобнай краіны або рэгіёну непасрэдна ў дадатку; +\n - неабмежаваная колькасць спампоўванняў мапаў асобнай краіны або рэгіёну непасрэдна ў праграме; \n \n - магчымасць аўтаномнай працы з данымі Вікіпедыі (спампоўванне POI з Вікіпедыі) з\'яўляецца цудоўным інструментам для падарожнікаў; \n @@ -370,7 +370,7 @@ Хуткасць сімуляцыі маршруту: Адведзена памяці %1$s МБ (Абмежаванне Android %2$s МБ, Dalvik %3$s МБ). Адведзеная памяць - Агулам фізічнай памяці занятай дадаткам %1$s МБ (Dalvik %2$s МБ, іншае %3$s МБ). + Агулам фізічнай памяці занятай праграмай %1$s МБ (Dalvik %2$s МБ, іншае %3$s МБ). \n Прапарцыйнай памяці %4$s МБ (Абмежаванне Android %5$s МБ, Dalvik %6$s МБ). Фізічнай памяці агулам Пункт адпраўлення знаходзіцца занадта далёка ад бліжэйшай дарогі. @@ -462,7 +462,7 @@ Калі ласка, пазначце імя і пароль карыстальніка OSM, каб адсылаць GPX-файлы. Падтрымка Падтрымка новых магчымасцяў - Ахвяраваць, каб убачыць новыя магчымасці, рэалізаваныя ў дадатку. + Ахвяраваць, каб убачыць новыя магчымасці, рэалізаваныя ў праграме. Паказваць маштаб Інфармацыя Вярнуцца да становішча @@ -518,7 +518,7 @@ Ужываць флюарэсцэнтныя колеры для слядоў і шляхоў. Пазасеціўнае рэдагаванне Заўсёды выкарыстоўваць аўтаномнае рэдагаванне. - Змены POI у дадатку не паўплываюць на cпампаваныя файлы мапаў, змены захоўваюцца як файлы на вашай прыладзе. + Змены цікавых пунктаў (POI) у праграме не паўплываюць на cпампаваныя файлы мапаў, змены захоўваюцца як файлы на вашай прыладзе. Запампоўка… {0} POI/нататкі запампаваныя Запампаваць усё @@ -560,8 +560,8 @@ Агульныя налады Кіраваць файламі мапаў Агульныя - Налады экрана і агульныя налады дадатку. - Агульныя налады дадатку + Налады экрана і агульныя налады праграмы. + Агульныя налады праграмы Вашае імя карыстальніка OSM Патрэбна для падачы ў openstreetmap.org. Ваш пароль OSM @@ -599,7 +599,7 @@ Файл POI \'%1$s\' залішні і можа быць выдалены. Лакальны файл для падтрымкі змен у POI не знойдзены і не можа быць створаны. Палепшыць да OsmAnd+ - Спампаваць новую версію дадатку, каб мець магчымасць выкарыстоўваць новыя файлы мапаў. + Спампаваць новую версію праграмы, каб мець магчымасць выкарыстоўваць новыя файлы мапаў. Сеціўны Nominatim Вызначэнне становішча… Маё становішча (знойдзена) @@ -671,7 +671,7 @@ Канал телефанавання (спыняе музыку з дынамікаў) Канал апавяшчэння Канал медыя/навігацыі - Дадатак не можа спампаваць пласт мапы %1$s. Можа дапамагчы пераўсталёўка. + Праграма не можа спампаваць пласт мапы %1$s. Можа дапамагчы пераўсталёўка. Падладзіць празрыстаць накладзенага пласта. Празрыстасць накладкі Падладзіць празрыстасць асноўнай мапы. @@ -752,14 +752,14 @@ \nНавігацыя часова пераключаецца на сэрвіс CloudMade. Не атрымалася знайсці вызначаны каталог. Каталог захоўвання даных - Усе аўтаномныя даныя ў старым усталяваным дадатку будуць падтрымлівацца новым, але ўлюбёныя мясціны патрэбна экспартаваць са старой версіі і імпартаваць у новую. + Усе аўтаномныя даныя ў старой усталяванай праграме будуць падтрымлівацца новыай, але ўлюбёныя мясціны патрэбна экспартаваць са старой версіі і імпартаваць у новую. Зборка {0} ўсталяваная ({1}). Спампоўваецца зборка… Усталяваць OsmAnd - {0} з {1} {2} МБ? Не ўдалося атрымаць спіс зборак OsmAnd Загружаюцца зборкі OsmAnd… Абярыце зборку OsmAnd для ўсталёўкі - Дадатак стану GPS не ўсталяваны. Пашукаць ў краме\? + Праграма статусу GPS не ўсталяваная. Пашукаць ў краме\? Галасавыя загады недаступныя. Калі ласка, перайдзіце ў \"Налады\" → \"Налады навігацыі\", абярыце профіль \"Галасавыя даныя\" і абярыце ці спампуйце пакунак галасавых падказак. Абярыце пакунак галасавых падказак Дзень @@ -893,7 +893,7 @@ Транспарт Паказаць прыпынкі грамадскага транспарту на мапе. Паказваць прыпынкі транспарту - Навігацыйны дадатак OsmAnd + Навігацыйная праграма OsmAnd Даныя POI былі абноўленыя ({0} аб\'ектаў загружана) Не атрымалася абнавіць лакальны спіс POI. Не атрымалася загрузіць даныя з сервера. @@ -977,7 +977,7 @@ Мэта Выбар паміж мясцовымі і англійскімі назвамі. Выкарыстоўваць англійскія назвы - Налады дадатку + Налады праграмы Пошук адраса Абраць будынак Абраць вуліцу @@ -995,7 +995,7 @@ Паказаць вашае становішча Паказаць GPS-каардынаты на мапе Спампаваць адсутныя фрагменты мапы - Навігацыйны дадатак + Навігацыйная праграма Пошук Пошук Абраць POI @@ -1147,7 +1147,7 @@ Аддаваць перавагу аўтамагістралям Імітацыя з выкарыстаннем разлічанага маршруту Імітацыя з выкарыстаннем GPX-следу - Профілі дадатку + Профілі праграмы Глабальная карэкцыя вышыні Навігацыйныя знакі ўсяго свету Плацяжы Bitcoin ўсяго свету @@ -1547,7 +1547,7 @@ \n \nГэты стыль на любым маштабе мапы паказвае максімальную колькасць падрабязнасцяў для паездкі, наяўных у даных мапы (у прыватнасці, дарогі, дарожкі, сцяжынкі, і арыенціры). \n -\nЁн таксама дакладна адлюстроўвае ўсе тыпы дарог праз колеравае кадаванне, што карысна, для, напрыклад, кіравання вялікімі транспартнымі сродкамі. +\nЁн таксама дакладна адлюстроўвае ўсе тыпы дарог праз каляровае кадаванне, што карысна, для, напрыклад, кіравання вялікімі транспартнымі сродкамі. \n \nІ ён дадае адмысловыя турыстычныя налады, такія як роварныя маршруты або альпійскія горныя маршруты. \n @@ -1574,7 +1574,7 @@ Высокая кантрастнасць дарог Немагчыма стварыць мапы ў вызначаным каталозе Перамясціць файлы не атрымалася - Унутраная памяць дадатку + Унутраная памяць праграмы Вызначана ўласнаручна Унутраная памяць Капіяваць @@ -1600,7 +1600,7 @@ Сапраўды хочаце выдаліць %1$d нататак\? Імпартаваць у OsmAnd Прадухіліць аўтаномны запіс - Запіс GPX прыпыніцца, калі дадатак будзе забіты (праз надаўнія дадаткі). (Апавяшчэнне ў вобласці падказак Android пра фонавы рэжым OsmAnd знікне.) + Запіс GPX прыпыніцца, калі праграма будзе забітая (праз надаўнія праграмы). (Апавяшчэнне ў вобласці падказак Android пра фонавы рэжым OsmAnd знікне.) Служба вызначэння месцазнаходжання выключаная. Уключыць яе\? Даныя Вікіпедыі састарэлі і больш непрыдатныя. Заархіваваць іх\? Спампаваць дадатковыя даныя Вікіпедыі (%1$s МБ)\? @@ -1636,7 +1636,7 @@ Бішнупрыя Наваха Неварская / Непал-бхаса - Каб усе змены ўжыліся, патрэбна перезапусціць дадатак. + Каб усе змены ўжыліся, патрэбна перезапусціць праграму. Колер GPX Шырыня GPX Чырвоны @@ -1657,7 +1657,7 @@ Прадвызначана (13) Прадвызначана (празрысты сіні) Вам падабаецца OsmAnd? - Ацаніце гэты дадатак + Ацаніце праграму Калі ласка, дайце ацэнку OsmAnd на Google Play Скажыце нам чаму. Калі ласка, пішыце прапановы. @@ -1760,7 +1760,7 @@ Падзяліцца месцазнаходжаннем геа: \"Выключана\" наўпрост запускае мапу. - Імітаваць першы запуск дадатку + Імітаваць першы запуск праграмы QR-код Мапа спампаваная Зваротная сувязь @@ -1778,7 +1778,7 @@ Абнавіць Базавая мапа свету (якая пакрывае ўвесь свет пры малым маштабе) адсутнічае або састарэла. Калі ласка, спампуйце яе каб мець магчымасць базавага агляду ўсяго свету. Мапа «%1$s» гатовая для выкарыстання. - Усталёўвае прыкмету першага запуску дадатку, не змяняе іншых налад. + Вызначае адзнаку першага запуску праграмы, не змяняе іншых налад. Увядзіце назву краіны Першыя крокі з OsmAnd Дапамажыце палепшыць OsmAnd @@ -1944,7 +1944,7 @@ Актыўны Не актыўны Паказаць празрыстую пошукавую панэль - Дадатак мае дазвол на запіс на рухомы носьбіт, але патрабуецца перазагрузка. + Праграма мае дазвол на запіс на рухомы носьбіт, але патрабуецца перазагрузка. Поўная справаздача Імя карыстальніка і пароль OpenStreetMap Дзякуй вам за падтрымку OsmAnd! @@ -2071,7 +2071,7 @@ Атрымайце неабмежаваную колькасць спампоўванняў мапаў у дадатак да штотыднёвых, штодзённых і нават штогадзінных абнаўленняў. Неабмежаваная колькасць спамоўванняў мапаў, абнаўленняў і ўбудова Wikipedia. Мілі/метры - Плата за падпіску спаганяецца штомесяц. Скасаваць яе на Google Play можна у любы момант. + Плата за падпіску спаганяецца за абраны перыяд. Скасаваць яе на Google Play можна у любы момант. Ахвяраванне супольнасці OpenStreetMap Частка вашага ахвяравання накіроўваецца ўдзельнікам праекта OpenStreetMap. Кошт падпіскі застаецца тым жа самым. Падпіска дазваляе атрымліваць штогадзіныя, штодзённыя, штотыднёвыя абнаўленні і неабмежаваную колькасць спампоўванняў для ўсіх мапаў па ўсім свеце. @@ -2265,7 +2265,7 @@ Збалансаваны Аддаваць перавагу завулкам На адсылаць ананімную статыстыку выкарыстання - OsmAnd збірае інфармацыю аб тым, якія часткі дадатку выкарыстоўваюцца вамі. Вашае месцазнаходжанне ніколі не адпраўляецца, як і ўсё, што вы ўводзіце, якія вобласці праглядаеце, што шукаеце ці спампоўваеце. + OsmAnd збірае інфармацыю аб тым, якія часткі праграмы выкарыстоўваюцца вамі. Ваша месцазнаходжанне ніколі не адпраўляецца, як і ўсё, што вы ўводзіце, якія вобласці праглядаеце, што шукаеце ці спампоўваеце. Не паказваць паведамленні падчас запуску Не паказваць зніжкі і адмысловыя паведамленні аб мясцовых падзеях. Параметры паркоўкі @@ -2307,9 +2307,9 @@ Аналізуй на мапе Бачны Прыпынена - OsmAnd (OSM Automated Navigation Directions) мапа і навігацыйны дадатак з доступам да бясплатных якасных мапаў усяго свету OpenStreetMap (OSM). + OsmAnd (OSM Automated Navigation Directions) мапа і навігацыйная праграма з доступам да бясплатных якасных мапаў усяго свету OpenStreetMap (OSM). \n -\nАтрымлівайце асалоду ад голасавога і візуальнага навігатара, прагляду карысных месцаў (анг. POI, points of interest), стварэння і кіравання GPX-слядоў, выкарыстання контурных ліній і інфармацыі аб вышыні (праз убудову), выбару паміж кіраваннем аўтамабілем, яздой на ровары і шпацырам, рэдагавання OSM і шмат іншым. +\nАтрымлівайце асалоду ад галасавога і візуальнага навігатара, прагляду цікавых пунктаў (анг. POI, points of interest), стварэння і кіравання GPX-слядоў, выкарыстання контурных ліній і інфармацыі аб вышыні (праз убудову), выбару паміж кіраваннем аўтамабілем, яздой на ровары і шпацырам, рэдагавання OSM і шмат іншым. Агляд Прыблізнае пакрыццё і якасць мапы: \n • Заходняя Еўропа: **** @@ -2354,10 +2354,10 @@ Узровень маштабавання паказу: %1$s Для вялікіх адлегласцяў: калі ласка, дадайце прамежкавыя пункты, калі разлік не завяршыўся цягам 10 хвілін. Лыжня -\nУбудова лыжных мап для OsmAnd дазваляе бачыць лыжныя трасы з узроўнем складанасці і некаторай дадатковай інфармацыяй: размяшчэнне пад\'ёмнікаў і іншых аб\'ектаў. +\nУбудова лыжных мапаў для OsmAnd дазваляе бачыць лыжныя трасы з узроўнем складанасці і некаторай дадатковай інфармацыяй: размяшчэнне пад\'ёмнікаў і іншых аб\'ектаў. Назва змяшчае занадта шмат вялікіх літар. Працягнуць\? Мапа -\n• Адлюстроўвае POI (пункт цікавасці) побач вас +\n• Адлюстроўвае POI (цікавы пункт) побач вас \n• Адаптуе мапу ў напрамку вашага руху (ці компаса) \n• Паказвае, дзе вы знаходзіцеся і куды вы глядзіце \n• Дзяліцеся сваім месцазнаходжаннем, каб сябры змаглі знайсці вас @@ -2386,7 +2386,7 @@ \n Удзел у OSM \n • Паведамленне аб памылках -\n • Спампоўванне GPX-слядоў у OSM проста з дадатку +\n • Спампоўванне GPX-слядоў у OSM проста з праграмы \n • Даданне цікавых пунктаў (POI) і запампоўка іх у OSM (ці пазней, па-за сецівам) \n Навігацыя @@ -2426,38 +2426,38 @@ \n • Антарктыда: \n Большасць краін свету даступная да спампоўвання! \n Атрымайце надзейны навігатар у вашай краіне — будзь то Беларусь, Францыя, Германія, Мексіка, Вялікабрытанія, Іспанія, Нідэрланды, ЗША, Расія, Бразілія ці якая іншая. - OsmAnd+ (OSM Automated Navigation Directions) — мапа і навігацыйны дадатак з доступам да бясплатных, сусветных і высокаякасных даных OpenStreetMap (OSM). -\n Атрымлівайце асалоду ад галасавой і візуальная навігацыі, праглядайце пукты цікавасцяў (POI), запісвайце GPX-сляды, выкарыстоўвайце візуалізацыю контурных ліній ды даных вышыні, пераключайцеся паміж рэжымамі кіравання, яздой на ровары ды шпацырамі, рэдагуйце OSM-даныя і шмат іншага. -\n + OsmAnd+ (OSM Automated Navigation Directions) — мапа і навігацыйная праграма з доступам да бясплатных, сусветных і высокаякасных даных OpenStreetMap (OSM). +\n Атрымлівайце асалоду ад галасавой і візуальная навігацыі, праглядайце цікавыя пукты (POI), запісвайце GPX-сляды, выкарыстоўвайце візуалізацыю контурных ліній ды даных вышыні, пераключайцеся паміж рэжымамі кіравання, яздой на ровары ды шпацырамі, рэдагуйце OSM-даныя і шмат іншага. +\n \n OsmAnd+ — платная версія. Пры набыцці вы падтрымліваеце праект, фінансуеце распрацоўку новых магчымасцяў ды атрымліваеце апошнія абнаўленні. -\n +\n \nНекаторыя з галоўных магчымасцяў: Прагляд мапы -\n +\n \n • Паказвае дзе вы знаходзіцеся і куды глядзіце -\n +\n \n • Пры патрэбе выраўняе мапу па компасе ці па напрамку вашага руху -\n +\n \n • Захавае вашыя найважнейшыя месцы ва ўлюблёных -\n -\n • Адлюстроўвае пункты цікавасцяў вакол вас -\n +\n +\n • Адлюстроўвае цікавыя пункты вакол вас +\n \n • Паказвае адмысловыя сеціўныя мапы, спадарожнікавыя здымкі (Bing), розныя накладкі накшталт турыстычных/навігацыйных GPX-слядоў і дадатковыя пласты з наладжвальнай празрыстасцю -\n +\n \n • Можа адлюстроўваць на мапе беларускія, англійскія, мясцовыя назвы ці фанетычным напісаннем \n - Выкарыстоўваюцца даныя OSM ды Вікіпедыі -\n -\n • Высокаякасная інфармацыя ад найлепшых праектаў свету -\n -\n • OSM-даныя даступныя па краіне ці рэгіёну -\n -\n • Пункты цікавасцяў з Вікіпедыі, выдатна падыходзіць для агляду выбітнасцяў -\n -\n • Неабмежаваная колькасць бясплатных спампоўванняў непасрэдна з дадатку -\n -\n • Кампактныя пазасеціўныя вектарныя мапы абнаўляюцца не радзей за раз на месяц -\n + Выкарыстоўваюцца даныя OSM ды Вікіпедыі +\n +\n • Высокаякасная інфармацыя ад найлепшых праектаў свету +\n +\n • OSM-даныя даступныя па краіне ці рэгіёну +\n +\n • Цікавыя пункты з Вікіпедыі, выдатна падыходзіць для агляду выбітнасцяў +\n +\n • Неабмежаваная колькасць бясплатных спампоўванняў непасрэдна з праграмы +\n +\n • Кампактныя пазасеціўныя вектарныя мапы абнаўляюцца не радзей за раз на месяц +\n \n • Выбар паміж поўнымі данымі рэгіёна ці толькі дарожнай сеткай (напрыклад, уся Японія займае 700 МБ, а дарожная сетка — 200 МБ) Асаблівасці бяспекі \n • Магчамасць аўтаматычнага пераключэння рэжыма дзень/ноч @@ -2471,17 +2471,17 @@ \n • Прыпынкі грамадскага транспарту (аўтобус, трамвай, цягнік), уключаючы назвы маршрутаў \n • Магчымасць запісу падарожжа ў лакальны GPX-файл ці інтэрнэт-сэрвіс \n • Магчымасць адлюстравання хуткасці ды вышыні -\n • Адлюстраванне контурных ліній ды зацянення вышынь (праз дадатак) +\n • Адлюстраванне контурных ліній ды зацянення вышынь (праз праграму) Непасрэдны ўнёсак у OSM \n • Заявы аб памылках у даных -\n • Запампоўванне GPX-слядоў у OSM проста з дадатку -\n • Даданне пунктаў цікавасцяў (POI) і непасрэдная запампоўка іх у OSM (ці пазней, па-за сецівам) +\n • Запампоўванне GPX-слядоў у OSM проста з праграмы +\n • Даданне цікавых пунктаў (POI) і непасрэдная запампоўка іх у OSM (ці пазней, па-за сецівам) \n • Магчымасць запісу падарожжа ў фонавым рэжыме (у той час, як прылада знаходзіцца ў рэжыме сну) \n OsmAnd — адкрытае праграмнае забяспячэнне ў актыўнай распрацоўцы. Кожны можа ўнесці ўклад паведамляючы аб памылках, паляпшаючы пераклад ці распрацоўваючы новыя магчымасці. Ход праекта залежыць таксама ад фінансавых унёскаў для забяспячэння кадавання і тэставання новай функцыянальнасці. \n Усталяваць Палепшыць фотапакрыццё Mapillary - Усталяваць Mapillary, каб дадаць адзін альбо некалькі фотаздымкаў да гэтага месца на мапе. + Усталюйце Mapillary, каб дадаць фотаздымкі гэтага месца. Адкрыць Mapillary Выява Mapillary Дыстанцыя выпраўленая @@ -2590,7 +2590,7 @@ Экспартаваць вашыя адзнакі ў наступны GPX-файл: Захаваць як GPX-файл Перамясціць у гісторыю - Групы ўжо не будзе пасля наступнага перазапуску дадатку. + Групы ўжо не будзе пасля наступнага перазапуску праграмы. Адзнакі Фармат каардынат Выкарыстоўваць сістэмную клавіятуру @@ -2642,7 +2642,7 @@ Паказвае лініі накірунку ад вашага становішча да актыўнай адзнакі. Паказвае адну ці дзьве стрэлкі, якія паказваюць накірунак да актыўных адзнак. Абярыце, як адлюстроўваць адлегласць да актыўных адзнак. - Вызначце колькасць указальнікаў кірунку: + Вызначце колькасць указальнікаў кірунку. Выгляд на мапе Абраць след, каб дадаць яго пункты ў адзнакі. Направа @@ -2754,7 +2754,7 @@ Выдаліць гісторыю пошукаў Паказаць выявы Папулярныя напрамкі - Платны дадатак + Платная праграма Платная ўбудова Дастуны новыя даныя Wikivoyage, абнавіце іх. Спампуйце даведнікі Wikivoyage для прагляду артыкулаў аб мясцінах па ўсім свеце без Інтэрнэту. @@ -2771,7 +2771,7 @@ Дапаможнік па самым цікавым месцам на планеце ўнутры OsmAnd без злучэння з Інтэрнэтам. Штомесячныя абнаўленні мапаў Штогадзінныя абнаўленні мапаў - Пакупка ў дадатку + Пакупка ў праграме Разавы плацёж Аднойчы набыты, будзе заўсёды даступны для вас. Купіць - %1$s @@ -2800,7 +2800,7 @@ Пошук адпаведнага артыкула вікіпедыі Артыкул не знойдзены Як адкрыць артыкулы Вікіпедыі? - Перазапуск дадатку + Перазапуск праграмы Вы анулявалі падпіску OsmAnd Live Прадоўжыць падпіску, каб і далей карыстацца ўсімі функцыямі: На падставе закладзеных вамі артыкулаў рэкамендуецца спампаваць наступныя мапы: @@ -2877,7 +2877,7 @@ \n Выдаліць адзнаку мапы «%s»\? Рэдагаваць адзнаку мапы - Асобны дадатак + Асобная праграма Пошук вуліцы Спачатку вызначце горад/мясцовасць Аднавіць @@ -2934,7 +2934,7 @@ трансферы пешшу Шлях - Пункты цікавасцяў (POI) + Цікавыя пункты (POI) Падлік маршруту… Грамадскі транспарт Абярыце дарогу, якой хочаце пазбягаць падчас навігацыі, або на мапе, або са спіса ніжэй: @@ -3093,7 +3093,7 @@ У кожнага профілю свае налады Вызначце час, цягам якога экран не будзе выключацца. Выкарыстоўваць датчык адлегласці - Правядзіце рукой па верхняй частцы экрана, каб уключыць яго падчас навігацыі. + Уключаць экран правёўшы па яму рукой. Зімовая дарога Ледзяная дарога Зімовыя і ледзяныя дарогі @@ -3133,11 +3133,11 @@ Вызначыць мінімальную / максімальную хуткасць Новы профіль Крушэнне - Апошні запуск OsmAnd завяршыўся хібай. Калі ласка, адпраўце паведамленне памылкі, каб палепшыць дадатак. + Апошні запуск OsmAnd завяршыўся хібай. Калі ласка, адпраўце паведамленне памылкі, каб палепшыць праграму. Асабісты транспарт Монакола Скутар - Дазвольце OsmAnd збіраць і апрацоўваць ананімныя даныя пра выкарыстанне дадатку. Мы не збіраем і не захоўваем даныя вашай пазіцыі ці месцаў, якія вы бачыце на мапе. + Дазвольце OsmAnd збіраць і апрацоўваць ананімныя даныя пра выкарыстанне праграмы. Мы не збіраем і не захоўваем даныя вашай пазіцыі ці месцаў, якія вы бачыце на мапе. \n \nВы можаце змяніць свой выбар у любы час у \"Налады\" > \"Прыватнасць і бяспека\". Дапамагае нам даведацца пра папулярнасць мапаў рэгіёнаў і краін. @@ -3166,7 +3166,7 @@ Тып: %s Базавы профіль Абярыце тып навігацыі - Калі ласка, абярыце тып навігацыі для новага профілю дадатку + Калі ласка, абярыце тып навігацыі для новага профілю праграмы Увядзіце назву профілю Спачатку неабходна даць профілю назву. Дублікат назвы @@ -3186,8 +3186,8 @@ BRouter (па-за сецівам) Адвольны профіль маршрутызацыі Адмысловая маршрутызацыя - Абярыце профілі, што будуць бачныя ў дадатку. - Профілі дадатку + Абярыце профілі, што будуць бачныя ў праграме. + Профілі праграмы Лыжныя туры Трасы для гарналыжных тураў. Санкі @@ -3206,7 +3206,7 @@ Клавіятура WunderLINQ Parrot - Калі ласка, ўключыце па меншай меры адзін профіль дадатку, каб выкарыстоўваць гэты параметр. + Калі ласка, ўключыце па меншай меры адзін профіль праграмы, каб выкарыстоўваць гэты параметр. Абраць gaps Прычэп Паказваць на мапе зоны з нізкім узроўнем выкідаў. Не ўплывае на маршрутызацыю. @@ -3242,7 +3242,7 @@ Буфер logcat UTM Standard Адкрыты код месцазнаходжання (OLC) - Абраны фармат будзе ужыты да ўсяго дадатку. + Абраны фармат будзе ужыты да ўсёй праграмы. Параметр прадвызначана абраны для профіляў: %s Змяніць налады Адкінуць змены @@ -3250,7 +3250,7 @@ Ужыць да ўсіх профіляў Паведамленне падчас запуску Аналітыка - Профіль дадатку зменены на \"%s\" + Профіль праграмы зменены на \"%s\" Налады ўбудоў Шпацыры, паходы, бег Карабель, веславанне, парусны спорт @@ -3272,30 +3272,30 @@ Аддаваць перавагу трасам гэтай складанаці, але не выключаць прастейшыя, калі шлях будзе карацейшым. Па-за трасай Freerides і offpiste - неафіцыйныя маршруты і праходы. Як правіла, недагледжаныя, неразмечаныя, не асвятляюцца ўвечары. Будзьце вельмі ўважлівымі. - • Профілі дадатку: стварыце ўласны профіль адпаведна вашых патрэб, выкарыстаўшы адмысловыя значок і колер. -\n + • Профілі праграмы: стварыце ўласны профіль адпаведна вашых патрэб, выкарыстаўшы адмысловыя значок і колер. +\n \n \n • Для профіляў дададзеныя прадвызначаныя налады і мінімальная / максімальная хуткасць \n -\n +\n \n • Дададзены віджэт з бягучымі каардынатамі \n -\n +\n \n • Дададзены параметры для адлюстравання на мапе компаса і радыуснай лінейкі \n -\n +\n \n • Палепшана загрузка мапаў у фонавым рэжыме \n -\n +\n \n • Вернуты параметр \"Уключыць экран\" \n -\n +\n \n • Выпраўлены выбар мовы Вікіпедыі \n -\n +\n \n • Выпраўлены паводзіны кнопкі компаса падчас навігацыі \n -\n +\n \n • Выпраўленні памылак \n \n @@ -3307,27 +3307,27 @@ Пікап Паказваць мапу падчас навігацыі на заблакаваным экране. Налады пабудовы маршруту абранага профілю \"%1$s\". - Час абуджэння + Час працы пасля абуджэння Адзінкі вымярэння і фарматы Выгляд Выгляд мапы Выгляд мапы Усталяваныя убудовы Наладзіць навігацыю - Тэма дадатку, адзінкі вымярэння, рэгіён + Тэма праграмы, адзінкі вымярэння, рэгіён Апавяшчэнні будуць паказвацца падчас навігацыі ў левым ніжнім куце экрана. Мова і вывад Скінуць да прадвызначаных Стварэнне, імпарт, рэдагаванне профіляў - Кіраванне профілямі дадатку… - Уплывае на ўвесь дадатак + Кіраванне профілямі праграмы… + Уплывае на ўсю праграму Налады OsmAnd Скапіяваць з іншага профілю Уключыць экран Мапа падчас навігацыі Мапа падчас навігацыі Іншае - Вага, вышыня, хуткасць + Вага, вышыня, даўжыня, хуткасць Параметры аўтамабіля Галасавыя апавяшчэнні прайграюцца толькі падчас навігацыі. Навігацыйныя інструкцыі і апавяшчэнні @@ -3439,10 +3439,10 @@ Перамясціць у новы пункт прызначэння Запісваць сляды кожны дзень у новы падкаталог (напрыклад, 2018-01-01). Сапраўды хочаце абнавіць усе мапы (%1$d)\? - Стварыце свой профіль на аснове аднаго з базавых профіляў - гэта будзе вызначаць асноўныя параметры, такія як віджэты, адзінкі вымярэння хуткасці і адлегласці. Гэта тыповыя профілі дадатку, якія разам з прыкладамі профіляў карыстальніка можна пашырыць да: + Стварыце свой профіль на аснове аднаго з базавых профіляў - гэта будзе вызначаць асноўныя параметры, такія як віджэты, адзінкі вымярэння хуткасці і адлегласці. Гэта тыповыя профілі праграмы, якія разам з прыкладамі профіляў карыстальніка можна пашырыць да: Маршруты, падрыхтаваныя толькі для класічнага стылю без канькабежных трас. Сюды ўваходзяць маршруты, падрыхтаваныя невялікім снегаходам з больш свабоднай лыжнёй і трасамі, падрыхтаваныя непасрэдна лыжнікамі. Спампаваць падрабязную мапу %s, каб праглядзець гэтую вобласць. - Унутранае сховішча OsmAnd, схаванае ад карыстальніка і іншых дадаткаў. + Унутранае сховішча OsmAnd, схаванае ад карыстальніка і іншых праграм. Змена каталога сховішча Ландшафтны парк Самаходныя і несамаходныя сані (запрэжкі) @@ -3464,7 +3464,7 @@ Складанасць гарналыжнай трасы Абмежаванне па шырыні Увядзіце шырыню транспартнага сродку для ўліку пры разліку маршруту. - • Абноўлены налады дадатку і профілю. Цяпер налады размешчаныя па тыпу. Кожны профіль можна наладзіць асобна. + • Абноўлены налады праграмы і профілю. Цяпер налады размешчаныя па тыпу. Кожны профіль можна наладзіць асобна. \n  \n  • Новы дыялог загрузкі мапы, які прапануе загрузіць мапу падчас прагляду \n  @@ -3502,7 +3502,7 @@ Рэдагаванне OSM OSM Значок будзе паказвацца падчас навігацыі або руху. - Прадвызначаны дадатак (%s) + Прадвызначаная праграма (%s) Адвольны профіль Вугал: %s° Вугал @@ -3527,7 +3527,7 @@ Улюбёнае Падпіска - OsmAnd Live Пакупкі OsmAnd - Даведка па знаках мапы + Даведка па знаках мапы. Профілі навігацыі Стварыць/Рэдагаваць POI Месца паркоўкі @@ -3535,7 +3535,7 @@ Аднавіць прадвызначаны парадак элементаў Вярнуцца да рэдагавання Паказаць грамадскі транспарт - Кнопка, каб паказаць ці схаваць грамадскі транспарт на мапе. + Кнопка для паказу ці хавання грамадскага транспарту на мапе. Дадаць профіль %1$s з %2$s Схілы @@ -3564,10 +3564,10 @@ Падзяляльнік Схавана Калі схаваць налады, то яны скінуцца да зыходнага стану. - \"Асноўныя дзеянні\" змяшчаюць толькі 4 кнопкі. + Толькі 4 кнопкі. Асноўныя дзеянні Убудова для распрацоўшчыкаў - Замяніць іншы пункт на гэты + Замяніць іншы пункт на гэты. Лыжныя туры Снегаход Адвольная ўбудова OsmAnd @@ -3596,8 +3596,8 @@ Арагонская Адвольны колер Пошук тыпаў POI - Абраныя профілі пераключаюцца націскам на кнопку \"Дзеянне\". - Профіляў, абраных для гэтага дзеяння, не знойдзена. + Пры націсканні на кнопку \"Дзеянні\" пераключаюцца абраныя профілі. + Адпаведных профіляў не знойдзена. Кантонская Ёруба Узбекская @@ -3614,9 +3614,34 @@ Ламбардская %1$s / %2$s Можна спалучаць тыпы POI з розных катэгорый. Націсніце \"Пераключыць\", каб абраць усе ці націсніце злева, каб абраць катэгорыю. - Змяніць профіль дадатку + Змяніць профіль праграмы Аглядная мапа свету (падрабязная) Схаваць грамадскі транспарт Паказаць/схаваць грамадскі транспарт Пералічыць маршрут у выпадку адхілення + Выдаліць + Вызначце шырыню судна, каб пазбягаць вузкіх мастоў + Паказаць/схаваць Mapillary + Схаваць Mapillary + Паказаць Mapillary + Пераключальнік для паказу альбо хавання пласта Mapillary. + Пазначце даўжыню транспартнага сродку, дазволеную для руху па маршрутах. + Ліміт даўжыні + Арыентацыя + Выдалена: %1$s + Перазапуск патрабуецца для поўнага выдалення даных камер кантролю хуткасці. + Кіраванне ўзроўнем маштабавання мапы пры дапамозе кнопак рэгулявання гучнасці. + Інфармацыя пра славутасці з Вікіпедыі. Гэта ваш кішэнны даведнік - уключыце ўбудову вікіпедыі і чытайце артыкулы пра аб’екты вакол вас. + Матацыкл Эндура + Мотаролер + Выдаліць і перазапусціць + На гэтай прыладзе няма камер кантролю хуткасці. + Ролікі + Выдаліць наступны пункт прызначэння + Маштабаванне кнопкамі гучнасці + Калі ласка, дайце пункту назву + Бягучы пункт прызначэння маршруту будзе выдалены. Калі гэта канцавы пункт прызначэння, то навігацыя спыніцца. + Спампаваць мапы Вікіпедыі + Інвалідны вазок + Закрытая нататка OSM \ No newline at end of file diff --git a/OsmAnd/res/values-da/strings.xml b/OsmAnd/res/values-da/strings.xml index 0e4bf01dbe..addb268595 100644 --- a/OsmAnd/res/values-da/strings.xml +++ b/OsmAnd/res/values-da/strings.xml @@ -3709,4 +3709,13 @@ Repræsenterer område: %1$s x %2$s Vis/skjul Mapillary Skjul Mapillary Vis Mapillary + Slet næste destinationspunkt + Lydstyrkeknapper som zoom + Angiv et navn til punktet + Hent Wikipedia-kort + Enduro motorcykel + Scooter + Kørestol + Go cart + Lukket OSM-note \ No newline at end of file diff --git a/OsmAnd/res/values-de/phrases.xml b/OsmAnd/res/values-de/phrases.xml index 65018d07c7..e2ca883769 100644 --- a/OsmAnd/res/values-de/phrases.xml +++ b/OsmAnd/res/values-de/phrases.xml @@ -3603,7 +3603,7 @@ Anzahl der Wickeltische Wickeltischgebühr: ja Wickeltischgebühr: nein - Holzkohlestoß + Kohlenmeiler Historischer Panzer Wasserpfeifen-Lounge Energiequelle: Biomasse diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index c177aba730..80666c5ffd 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3823,4 +3823,8 @@ Informationen über Sehenswürdigkeiten erhalten Sie bei Wikipedia. Es ist Ihr Offline-Wegweiser für die Hosentasche - aktivieren Sie einfach das Wikipedia-Modul und genießen Sie Artikel über Objekte in Ihrer Umgebung. Enduro Motorroller + Rollstuhl + Go-Kart + Geschlossene OSM-Notiz + Rollstuhl vorwärts \ No newline at end of file diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index 0933178823..4d47baaff2 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -3611,7 +3611,7 @@ Anstataŭigi alian punkton per tiu ĉi. Aplikis ŝanĝojn al la profilo “%1$s”. Ne povas legi el “%1$s”. - Ne povas skribi al “%1%s”. + Ne povas skribi al “%1$s”. Ne povas enporti el “%1$s”. Elekti dosieron de spuro Lingvoj @@ -3814,4 +3814,10 @@ La markita celo de la kurso estos forigita. Se tio ĉi estos la fina celo, la navigado ĉesos. Elŝuti vikipediajn mapojn Akiru informojn pri interesaj punktoj el Vikipedio. Gvidilo en via poŝo – aktivigu la kromprogramon Vikipedio por ricevi artikolojn pri proksimaj objektoj. + Motorciklo (enduro) + Motorciklo (skotero) + Rulseĝo + Rulseĝo (klinita) + Gokarto + Fermita OSM‑rimarko \ No newline at end of file diff --git a/OsmAnd/res/values-es-rAR/phrases.xml b/OsmAnd/res/values-es-rAR/phrases.xml index 9e596b6667..5e9d8b5c82 100644 --- a/OsmAnd/res/values-es-rAR/phrases.xml +++ b/OsmAnd/res/values-es-rAR/phrases.xml @@ -1852,7 +1852,7 @@ Monumento técnico Templo piramidal Oficina del campamento - Aeródromo a escala + Pista de aeromodelismo Oficina del guía ONG casi autónoma Oficina de consultoría diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index 6e06602862..c4e1c15d19 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -3819,4 +3819,10 @@ El punto de destino actual de la ruta será borrado. Si será el destino, la navegación se detendrá. Descargar datos de Wikipedia Obtén información sobre los puntos de interés de Wikipedia. Es tu guía de bolsillo sin conexión - sólo activa el complemento de Wikipedia y disfruta los artículos sobre los objetos de alrededor. + Motocicleta de enduro + Motoneta (motor) + Silla de ruedas + Go-kart + Nota de OSM cerrada + Silla de ruedas (hacia adelante) \ No newline at end of file diff --git a/OsmAnd/res/values-es-rUS/phrases.xml b/OsmAnd/res/values-es-rUS/phrases.xml index ceb20a440f..7f0a081326 100644 --- a/OsmAnd/res/values-es-rUS/phrases.xml +++ b/OsmAnd/res/values-es-rUS/phrases.xml @@ -1852,7 +1852,7 @@ Monumento técnico Templo piramidal Oficina del campamento - Aeródromo a escala + Pista de aeromodelismo Oficina del guía ONG casi autónoma Oficina de consultoría @@ -3837,4 +3837,6 @@ Flecha Vibración Caja de regalo + Manzana (cuadra) + Municipio \ No newline at end of file diff --git a/OsmAnd/res/values-es-rUS/strings.xml b/OsmAnd/res/values-es-rUS/strings.xml index 6230a0046d..0f3ef1ff1b 100644 --- a/OsmAnd/res/values-es-rUS/strings.xml +++ b/OsmAnd/res/values-es-rUS/strings.xml @@ -3802,7 +3802,7 @@ Un botón que alterna la capa de Mapillary en el mapa. Rumbo %1$s borrado - Debes reiniciar para borrar completamente los datos de los radares de velocidad. + Se debe reiniciar para borrar completamente los datos de los radares de velocidad. Desinstalar y reiniciar Indica la longitud permitida del vehículo en rutas. Límite de longitud @@ -3810,4 +3810,12 @@ Patines en línea Permite controlar el nivel de zoom del mapa con los botones de volumen del dispositivo. Botones de volumen como zoom + Descargar datos de Wikipedia + El punto de destino actual de la ruta será borrado. Si será el destino, la navegación se detendrá. + Borrar el siguiente punto de destino + Obtén información sobre los puntos de interés de Wikipedia. Es tu guía de bolsillo sin conexión - sólo activa el complemento de Wikipedia y disfruta los artículos sobre los objetos de alrededor. + Proporciona un nombre para el punto + Proporciona la longitud del vehículo, se pueden aplicar algunas restricciones de rutas para vehículos largos. + Motoneta (motor) + Motocicleta de enduro \ No newline at end of file diff --git a/OsmAnd/res/values-fr/phrases.xml b/OsmAnd/res/values-fr/phrases.xml index b220d4eaf1..f26c9279aa 100644 --- a/OsmAnd/res/values-fr/phrases.xml +++ b/OsmAnd/res/values-fr/phrases.xml @@ -3600,7 +3600,7 @@ Nombre de tables à langer Table à langer payante Table à langer gratuite - Pile de charbon + Meule Bar à chicha Balkanique Point de vente diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index 4261dd28db..805fa38ba4 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -3798,4 +3798,8 @@ Télécharger les cartes Wikipédia Scooter Moto enduro + Kart + Note OSM fermée + Fauteuil roulant + Fauteuil roulant vers l\'avant \ No newline at end of file diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index 9e146396df..43bb801860 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -3841,4 +3841,10 @@ Lon %2$s O punto de destino actual na ruta será eliminado. Se fora o destino, a navegación sería interrompida. Baixar mapas da Wikipedia Obter información sobre os puntos de interesse da Wikipédia. É o teu guía de peto sen conexión - só activar o complemento da Wikipédia e desfrutar dos artigos sobre os elementos ó teu redor. + Enduro + Scooter + Cadeira de rodas + Cadeira de rodas só cara adiante + Kart + Nota do OSM pechada \ No newline at end of file diff --git a/OsmAnd/res/values-hu/phrases.xml b/OsmAnd/res/values-hu/phrases.xml index 07a5eabded..056b60bcf5 100644 --- a/OsmAnd/res/values-hu/phrases.xml +++ b/OsmAnd/res/values-hu/phrases.xml @@ -1116,7 +1116,7 @@ van Vakvezető burkolat nincs van - nincs + Hang nincs Csak amikor zöld Pihenőhely Mini körforgalom @@ -1198,13 +1198,13 @@ Elektromosautó-szerelés Motorkerékpár-szerelés igen - Nem önkiszolgáló + Nem igen Nem automatizált Teljes kiszolgálás igen Kefés - Autómosó nincs + Nincs Repülőgépüzemanyag-töltő állomás Közfürdő Férfi @@ -3792,4 +3792,15 @@ Nyíl Rezgés Nyomás + Akadály + Pálya azonosítószám + Bowling központ + Biztonsági szaküzlet + Hegyimentő + Igen + Igen + Rezgés nincs + Adomány doboz + Kerület + Háztömb \ No newline at end of file diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml index ce0242574b..70cf693f39 100644 --- a/OsmAnd/res/values-hu/strings.xml +++ b/OsmAnd/res/values-hu/strings.xml @@ -3767,4 +3767,10 @@ \nAz előfizetéseit a Google Play beállításainál tudja kezelni és lemondani. Törli az útvonal soron következő célpontját. Amennyiben ez a végző célpont, a navigáció megáll. Szerezzen információt az érdekes helyekkel kapcsolatban a Wikipédiáról. Ez az ön offline zseb útikönyve - egyszerűen engedélyezze a Wikipédia bővítményt és élvezze az ön körül lévő objektumokról szóló cikkeket. + Salakmotor + Robogó + Kerekesszék + Gokart + Lezárt OSM-jegyzet + Előre döntött kerekesszék \ No newline at end of file diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index e96e07e7b5..1eb7abb563 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -3787,4 +3787,39 @@ Nascondi Mapilly Mostra Mapillary Un pulsante per visualizzare nella mappa o nascondere il livello Mapillary . + Fornisci la lunghezza del tuo veicolo, alcune restrizioni di percorso potrebbero essere applicate per veicoli. + Disinstalla autovelox + Legale + PDI autovelox + In alcuni paesi o regioni, gli avvisi di presenza di autovelox sono proibiti dalla legge. +\n +\nDevi scegliere in base alle leggi del tuo paese. +\n +\nScegliendo %1$s e riceverai gli avvisi della presenza di autovelox. +\n +\nScegliendo %2$s. Tutti i dati relativi agli autovelox: avvisi, notifiche, PDI saranno cancellati fino a che OsmAnd non sarà completamente reinstallato. + Mantieni attivo + Disinstalla + Gli avvisi sulla presenza di autovelox in alcuni paesi è proibita dalla legge. + Specifica la lunghezza del veicolo permessa nei percorsi. + Lunghezza massima + Bussola + %1$s cancellato + Il riavvio è necessario per cancellare completamente i dati degli autovelox. + Disinstalla e Riavvia + Questo dispositivo non ha autovelox. + Pattini in linea + Cancella il prossimo punto di destinazione + Abilita per controllare il livello di zoom della mappa con i pulsanti del volume del dispositivo. + Pulsanti volume come zoom + Per favore indica un nome per il punto + Il punto di destinazione corrente sul percorso verrà eliminato. Se sarà la Destinazione, la navigazione verrà interrotta. + Scarica mappe Wikipedia + Ottieni informazioni sui punti di interesse da Wikipedia. È la tua guida tascabile offline - basta abilitare il plugin Wikipedia e goderti gli articoli sugli oggetti intorno a te. + Moto da enduro + Moto scooter + Sedia a rotelle + Go-kart + Chiudi la nota OSM + Sedia a rotelle \ No newline at end of file diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml index fed119f881..ba88963918 100644 --- a/OsmAnd/res/values-iw/strings.xml +++ b/OsmAnd/res/values-iw/strings.xml @@ -3824,4 +3824,8 @@ קבלת מידע על נקודות עניין מוויקיפדיה. מדריך הכיס הפרטי שלך - עליך פשוט להפעיל את התוסף של ויקיפדיה וליהנות מערכים על מה שסביבך. אופנוע שטח טוסטוס + כסא גלגלים + כסא גלגלים ספורטיבי + קארטינג + הערת OSM סגורה \ No newline at end of file diff --git a/OsmAnd/res/values-nl/phrases.xml b/OsmAnd/res/values-nl/phrases.xml index fb9b279343..65a281ce68 100644 --- a/OsmAnd/res/values-nl/phrases.xml +++ b/OsmAnd/res/values-nl/phrases.xml @@ -3612,4 +3612,141 @@ Kinderopvang Tolportaal Atol + Aangegeven + Aangegeven + Bestemmingsverkeer + Aangegeven + Toegestaan + Bestemmingsverkeer + Aangegeven + Aangegeven + Aangegeven + Bestemmingsverkeer + Toegestaan + Aangegeven + Aangegeven + Aangegeven + Aangegeven + Toegestaan + Aangegeven + Toegang voor gehandicapten: nee + Toegang voor taxi’s: nee + Toegang voor taxi’s: aangegeven + Toegang voor taxi’s: ja + Toegang voor landbouwvoertuigen: nee + Toegang voor landbouwvoertuigen: ja + Toegang voor sneeuwscooters: nee + Toegang voor sneeuwscooters: privé + Toegang voor skiërs: nee + Toegang voor skiërs: ja + Toegang voor touringcars: nee + Toegang voor touringcars: aangegeven + Toegang voor lijnbussen: nee + Toegang voor touringcars: ja + Toegang voor touringcars: ja + Toegang voor touringcars: nee + Toegang voor publiek transport of taxi’s: nee + Toegang voor publiek transport of taxi’s: aangegeven + Toegang voor publiek transport of taxi’s: ja + Toegang voor aanhangers: nee + Toegang voor campers: nee + Toegang voor caravans: nee + Toegang voor fietsers: klanten + Toegang voor fietsers: toegestaan + Toegang voor fietsers: bestemmingsverkeer + Toegang voor fietsers: afstappen + Toegang voor fietsers: privé + Toegang voor snorfietsers: nee + Toegang voor bromfietsers: nee + Toegang voor motorbestuurders: nee + Toegang voor motorbestuurders: privé + Toegang voor voetgangers: klanten + Toegang voor voetgangers: toegestaan + Toegang voor voetgangers: bestemmingsverkeer + Toegang voor voetgangers: nee + Toegang voor voetgangers: privé + Toegang voor voetgangers: ja + Toegang voor ruiters: boswachterij + Toegang voor ruiters: toegestaan + Toegang voor ruiters: bestemmingsverkeer + Toegang voor ruiters: privé + Toegang voor bestelwagens: nee + Toegang voor vrachtwagens: ongeschikt + Toegang voor vrachtwagens: ontraden + Toegang voor vrachtwagens: landbouw + Toegang voor vrachtwagens: nee + Toegang voor vrachtwagens: privé + Toegang voor motorvoertuigen: landbouw + Toegang voor motorvoertuigen: boswachterij + Toegang voor motorvoertuigen: bezorging + Toegang voor motorvoertuigen: militair + Toegang voor motorvoertuigen: klanten + Toegang voor motorvoertuigen: toegestaan + Toegang voor motorvoertuigen: bestemmingsverkeer + Toegang voor motorvoertuigen: nee + Toegang voor motorvoertuigen: privé + Toegang voor auto’s: toegestaan + Toegang voor auto’s: bestemmingsverkeer + Toegang voor auto’s: nee + Toegang voor auto’s: privé + Toegang voor auto’s: ja + Toegang voor auto’s: klanten + Toegang voor auto’s: boswachterij + Toegang voor motorvoertuigen: ja + Toegang voor voertuigen: boswachterij + Toegang voor voertuigen: bezorging + Toegang voor voertuigen: militair + Toegang voor voertuigen: klanten + Toegang voor voertuigen: toegestaan + Toegang voor voertuigen: bestemmingsverkeer + Toegang voor voertuigen: nee + Toegang voor voertuigen: privé + Toegang voor voertuigen: ja + Hookah lounge + Meiler + Noodhulpkist + Faciliteiten voor pijpleidingen + Parkeerplaats + Graf + Soort klooster: reguliere orde + Soort klooster: kluizenaars + Soort klooster: kanunniken + Soort klooster: convent + Soort klooster: monniken + Nee + Ja + Voetenbad + Meer + Rivier + Thermisch + Hamam + Onsen + Warmwaterbron + Postbank + Girokaart + Migros bank + Postfinance card + Geldopname: internationaal + Geldopname: minimum aankoopbedrag + Kostenloze geldopname: ja + Kostenloze geldopname: nee + Geldopname: zonder aankoop + Geldopname: bij aankoop + Munteenheid + Opnamelimiet + Geldopname via: zelfbedieningskassa + Geldopname via: kassa + Uitbatende organisatie van geldopname + Geldopname + Geldopname: ja + Huisdierverzorging + Tarief + Meubelmaker + Bakkerij + Vloerenlegger + Schrijnwerker + Destilleerderij + Aannemer + Health food + Kelderingang \ No newline at end of file diff --git a/OsmAnd/res/values-nl/strings.xml b/OsmAnd/res/values-nl/strings.xml index 0702198718..8823108ba9 100644 --- a/OsmAnd/res/values-nl/strings.xml +++ b/OsmAnd/res/values-nl/strings.xml @@ -3431,7 +3431,7 @@ Recht-naar-punt Kies een naam voor het profiel Open instellingen - Plugin uitgeschakeld + Plug-in uit Deze plug-in is een afzonderlijke app, die afzonderlijk verwijderd moet worden als je deze niet meer nodig denkt te hebben. \n \nDe plug-in blijft op het apparaat aanwezig na het verwijderen van OsmAnd. @@ -3442,7 +3442,7 @@ Het geïmporteerde profiel bevat bijkomende gegevens. Klik \'importeer\' om enkel de profielgegevens te importeren of kies bijkomende gegevens om te importeren. Je kan bijkomende gegevens om mee met het profiel te exporteren. App Standaardwaarde (%s) - Herberekening uitschakelen + Niet herberekenen Minimale afstand om route te herbereken De route wordt herberekend wanneer de afstand tot die route groter is dan de opgegeven parameter Eigen profiel @@ -3471,17 +3471,17 @@ Alle profielinstellingen herstellen\? Slaat nieuw profiel op Kan profiel niet back-uppen. - %1$s of %2$s + %1$s van %2$s Hellingen Terrein tonen / verbergen Terrein verbergen Terrein tonen Een knop om de terreinlaag al dan niet te tonen op de kaart. - Verwijder een beschrijving - Voeg een beschrijving toe - Selecteer groep - Selecteer vorm - cirkel + Beschrijving verwijderen + Beschrijving toevoegen + Groep kiezen + Vorm kiezen + Cirkel Ruit Min Combineer POI-types uit verschillende categorieën. Tik op \"Schakelen\" om alles te selecteren, tik op de linkerkant voor de categoriekeuze. @@ -3707,4 +3707,10 @@ Verwijder het volgende routepunt Kies een naam voor het punt Wikipedia-kaarten downloaden + Motorscooter + Enduromotor + Rolstoel + Rolstoel vooraanzicht + Opgeloste OSM-notitie + Kart \ No newline at end of file diff --git a/OsmAnd/res/values-pl/phrases.xml b/OsmAnd/res/values-pl/phrases.xml index 263a687f98..f0ae512c20 100644 --- a/OsmAnd/res/values-pl/phrases.xml +++ b/OsmAnd/res/values-pl/phrases.xml @@ -3825,4 +3825,7 @@ Ciśnienie Strzałka Wibracja + Tak + Tak + Wibracja: nie \ No newline at end of file diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index eea73e1812..c7ab2ef74d 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -61,7 +61,7 @@ Pobierz dane (\"offline\") by używać map offline. " \n -\nPrzytrzymaj dłużej, aby uzyskać opcje" +\nPrzytrzymaj dłużej, aby wyświetlić opcje" Wersja lokalna Zarchiwizowano %1$d z %2$d. Usunięto %1$d z %2$d. @@ -97,7 +97,9 @@ Odwróć kierunek GPX Użyj bieżącego celu Pobierz mapę wektorową offline tego położenia w „Ustawieniach” (\"Zarządzaj mapami\") lub przełącz na wtyczkę \"Mapy online\". - Dla bieżącego położenia dostępna jest wektorowa mapa offline. Aby jej użyć, proszę wybrać „Menu” → „Skonfiguruj mapę” → „Zasób mapy…” → „Wektorowe mapy offline”. + Dla bieżącego położenia dostępna jest wektorowa mapa offline. +\n +\nAby jej użyć wybierz „Menu” → „Skonfiguruj mapę” → „Źródło mapy…” → „Wektorowe mapy offline”. Wyjście dźwięku nawigacji głosowej Wybiera kanał do odtwarzania komunikatów głosowych. Kanał telefoniczny (przerywa odtwarzanie muzyki z głośników) @@ -1053,7 +1055,7 @@ Kanada Diagnozowanie błędów FPS Pobrane stopnie przybliżenia: %1$s - Wygaśnięcie (minuty): %1$s + Czas wygaśnięcia (minuty): %1$s Do pobrania: %1$s Maksymalne przybliżenie: %1$s Minimalne przybliżenie: %1$s @@ -1228,7 +1230,7 @@ %1$s \nTrasa %2$s " \n -\nPrzytrzymaj nacisk, aby zobaczyć na mapie" +\nPrzytrzymaj dłużej, aby wyświetlić na mapie" Rozpocznij nawigację automatycznie wybrano Interwał podziału @@ -2033,7 +2035,7 @@ Pomijanie aktualizacji Uaktualnić wszystkie mapy? Wyczyść wszystkie kafelki - Opłata za subskrypcję na miesiąc. Anuluj ją w Google Play w dowolnym momencie. + Subskrypcja naliczona za wybrany okres. Anuluj go w Google Play w dowolnym momencie. Darowizna na rzecz społeczności OSM Część z dotacji jest przekazywana darczyńcom OSM. Koszt subskrypcji pozostaje taki sam. Subskrypcje pozwalają na cogodzinne, codzienne i cotygodniowe uaktualnienia i nieograniczone liczbą pobieranie map całego świata. @@ -2307,18 +2309,18 @@ Pokaż lub ukryj notatki OSM Pokaż uwagi OSM Ukryj uwagi OSM - Przybliżony zasięg i jakość mapy: -\n • Europa Zachodnia: **** -\n • Europa Wschodnia: *** -\n • Rosja: *** -\n • Ameryka Północna: *** -\n • Ameryka Południowa: ** -\n • Azja: ** -\n • Japonia i Korea: *** -\n • Bliski Wschód: ** -\n • Afryka: ** + Przybliżony zasięg i jakość mapy: +\n • Europa Zachodnia: **** +\n • Europa Wschodnia: *** +\n • Rosja: *** +\n • Ameryka Północna: *** +\n • Ameryka Południowa: ** +\n • Azja: ** +\n • Japonia i Korea: *** +\n • Bliski Wschód: ** +\n • Afryka: ** \n • Antarktyda: * -\n Jest możliwe pobranie map większości krajów na świecie! +\n Jest możliwe pobranie map większości krajów na świecie! \n Od Afganistanu po Zimbabwe, przez Australię po USA. Argentyna, Brazylia, Kanada, Francja, Niemcy, Polska, Meksyk, Wielka Brytania, Hiszpania, … \n Posortowane wg odległości @@ -2340,7 +2342,7 @@ Udostępnia zdjęcia w widoku ulicznym. Pozwala na odkrywanie miejsc, współpracę nad uchwyceniem świata. Zainstaluj Zwiększ pokrycie zdjęć Mapillary - Proszę zainstalować Mapillary, aby dodać zdjęcia tego położenia na mapie. + Zainstaluj Mapillary, aby dodać zdjęcia do tej lokalizacji na mapie. Otwórz Mapillary Obraz Mapillary Poprawiona odległość @@ -2409,7 +2411,7 @@ Dodaj pliki GPX Importowanie plików GPX lub nagranych tras. Dodaj do ulubionych - Importuje ulubione lub dodaje poprzez zaznaczenie punktów na mapie. + Zaimportuj Ulubione lub dodaj je poprzez zaznaczenie punktów na mapie. Importuj plik GPX Plik %1$s nie zawiera punktów trasy, czy zaimportować go jako ślad? Przesuń punkt @@ -2522,7 +2524,7 @@ Czytaj cały artykuł Czytaj artykuł Notuj! - Dodaj notatkę audio, video lub zdjęciową do każdego punktu na mapie, za pomocą widgetu lub menu kontekstowego. + Dodaj notatki audio, wideo lub zdjęcia do dowolnego punktu na mapie za pomocą widżetów lub menu kontekstowego. Notatki A/V według daty Importuj grupy Wybierz kategorię Ulubione, aby dodać znaczniki. @@ -3152,7 +3154,7 @@ Przebudzaj przed zakrętem Ustaw jak długo ekran będzie włączony. Używanie czujnika zbliżeniowego - Włącza ekran podczas nawigacji machaniem ręką nad ekranem. + Włącza ekran machaniem ręką nad ekranem. Zewnętrzne urządzenia wejściowe Wybierz urządzenie takie jak zwykła klawiatura lub WundeRLINQ do sterowania zewnętrznego. Brak @@ -3418,12 +3420,12 @@ Wybór koloru Nie można usunąć domyślnych profili OsmAnd, ale można je wyłączyć (na poprzednim ekranie) lub przenieść na dół. Edytuj profile - Określa w jaki sposób wyznaczane są trasy. + „Typ nawigacji” określa sposób obliczania tras. Wygląd profilu Ikona, kolor i nazwa Edytuj listę profili Wybrany profil - Stuknięcie %1$s spowoduje utratę wszystkich zmian. + Naciśnięcie przycisku %1$s powoduje odrzucenie wszystkich zmian. Wszystkie ustawienia profilu zostaną przywrócone do stanu po instalacji. Zresetować wszystkie ustawienia profilu\? %1$s: %2$s @@ -3461,7 +3463,7 @@ Uwierzytelniono Efekt uboczny: trasa nie będzie zawierała sekcji, w których nie zostało spełnione kryterium minimalnej prędkości (np. podczas pchania roweru pod strome wzgórze). Nie będzie również zawierała informacji o czasach odpoczynku, np. przerwach. Ma to wpływ na analizę i przetwarzanie końcowe, np. przy próbie określenia całkowitej długości trasy, czasu w ruchu lub średniej prędkości. Zmień układ kategorii - Zmień kolejność sortowania listy, ukryj niepotrzebne kategorie. Wszystkie zmiany można importować lub eksportować za pomocą profili. + Zmień kolejność sortowania listy, ukryj kategorie. Wszystkie zmiany można importować lub eksportować za pomocą profili. Można dodać nową, niestandardową kategorię wybierając jedną lub kilka kategorii. Dostępne Dodaj niestandardową kategorię @@ -3478,7 +3480,7 @@ Przywrócenie ustawień wtyczki do wartości domyślnych Użyj aplikacji systemowej Dźwięk migawki aparatu - Przywrócenie domyślnej kolejności sortowania spowoduje przywrócenie porządku sortowania do stanu domyślnego po instalacji. + Opcja \'Przywróć ustawienia domyślne\' spowoduje przywrócenie porządku sortowania do stanu domyślnego po instalacji. Tryb ułatwień jest dostępu wyłączony w twoim systemie. Wygaś ekran zgodnie z ustawieniami systemu Wyczyść zarejestrowane dane @@ -3678,7 +3680,7 @@ \nMożesz wyłączyć nieużywane wtyczki, aby ukryć ich elementy w aplikacji. %1$s. %1$s / %2$s Szukaj typów użytecznych miejsc - Łącz typy użytecznych zmian z różnych kategorii. Stuknij \"Zmień\", aby zaznaczyć wszystko, stuknij lewą stronę, aby wybrać kategorię. + Łącz typy użytecznych zmian z różnych kategorii. Stuknij przełącznik, aby zaznaczyć wszystko, stuknij lewą stronę, aby wybrać kategorię. Przewodnik po symbolach mapy. Profile nawigacji OsmAnd + Mapillary @@ -3695,22 +3697,22 @@ \nSubskrypcja automatycznie odnawia się, chyba że anulujesz ją przed dniem odnowienia. Twoje konto zostanie obciążone za okres odnowienia (miesiąc/trzy miesiące/rok) dopiero w dniu odnowienia. \n \nMożesz zarządzać subskrypcjami i anulować je w ustawieniach Google Play. - • Nowe mapy stoków offline -\n + • Nowe mapy stoków offline +\n \n • Pełna personalizacja Ulubionych i Punktów GPX - niestandardowe kolory, ikony, kształty -\n -\n • Dostosowywanie kolejności elementów w menu kontekstowym, konfiguracji mapy, menu podręcznym -\n +\n +\n • Dostosowywanie kolejności elementów w menu kontekstowym, konfiguracji mapy i menu podręcznym +\n \n • Wikipedia jako osobna warstwa w konfiguracji mapy, wybierz tylko potrzebne języki -\n -\n • Tworzenie własnego filtru użytecznych miejsc/mapy z pełną elastycznością -\n +\n +\n • Tworzenie własnego filtru użytecznych miejsc/map z pełną elastycznością +\n \n • Dodano opcje przywracania ustawień profili niestandardowych -\n +\n \n • Pełne trasy GPX z nawigacji obsługują pasy ruchu i pełne instrukcje skrętu -\n +\n \n • Naprawiono rozmiary interfejsu użytkownika na tabletach -\n +\n \n • Naprawiono błędy z RTL \n \n @@ -3720,7 +3722,7 @@ Pokaż/ukryj transport publiczny Utwórz / Edytuj użyteczne miejsce Dodaj / Edytuj Ulubione - Naciśnięcie przycisku akcji powoduje przełączanie między wybranymi profilami. + Przycisk akcji przełącza między wybranymi profilami. Dodaj profil Zmiana profilu aplikacji Możesz uzyskać dostęp do tych czynności, naciskając przycisk „%1$s”. @@ -3802,4 +3804,15 @@ Usunięto %1$s Ponowne uruchomienie jest wymagane, żeby całkowicie usunąć dane fotoradarów. Odinstaluj i zrestartuj + Tracker OsmAnd + Podaj długość pojazdu, niektóre ograniczenia tras mogą być stosowane dla długich pojazdów. + To urządzenie nie ma fotoradarów. + Usuń następny punkt docelowy + Włącz sterowanie poziomem powiększenia mapy za pomocą przycisków głośności urządzenia. + Podaj nazwę punktu + Bieżący punkt docelowy na trasie zostanie usunięty. Jeśli będzie to miejsce docelowe, nawigacja zostanie zatrzymana. + Pobierz mapy Wikipedii + Uzyskaj informacje o interesujących miejscach z Wikipedii. Jest to kieszonkowy przewodnik offline - wystarczy włączyć wtyczkę Wikipedii i cieszyć się artykułami o obiektach wokół ciebie. + Motocykl Enduro + Skuter \ No newline at end of file diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml index 4ad3f4b969..3b0b437c87 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -3801,4 +3801,10 @@ Pôr do Sol: %2$s O ponto de destino atual na rota será excluído. Se for o destino, a navegação será interrompida. Baixar mapas da Wikipédia Obter informações sobre pontos de interesse da Wikipédia. É o seu guia de bolso off-line - só ativar o complemento Wikipédia e desfrutar de artigos sobre os elementos ao seu redor. + Motocicleta enduro + Motoneta + Cadeira de rodas + Cadeira de rodas para a frente + Carrinho de compras + Nota OSM fechada \ No newline at end of file diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index ef9375b604..659e2b28c2 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -3813,4 +3813,8 @@ Текущий пункт назначения на маршруте будет удалён. Если это пункт назначения, навигация остановится. Информация о достопримечательностях из Википедии. Это ваш карманный автономный гид — просто включите плагин Википедии и наслаждайтесь статьями об объектах вокруг вас. Скачать карты Википедии + Эндуро мотоцикл + Мотороллер + Закрытая заметка OSM + Инвалидная коляска \ No newline at end of file diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml index 7af00c0cae..f8c3f277fc 100644 --- a/OsmAnd/res/values-sc/strings.xml +++ b/OsmAnd/res/values-sc/strings.xml @@ -3816,4 +3816,10 @@ Su puntu de destinatzione atuale in s\'àndala at a èssere iscantzelladu. Si at a èssere sa destinatzione, sa navigatzione s\'at a firmare. Iscàrriga sas mapas de Wikipedia Otene informatziones a pitzu de puntos de interesse dae Wikipedia. Est sa ghia non in lìnia tua de mantènnere in butzaca - abìlita s\'estensione Wikipedia e ispassia·ti cun sos artìculos a pitzu de sos ogetos a fùrriu de tie. + Moto enduro + Motorinu + Cadira a rodas cara a in antis + Cadira a rodas + Go-kart + Nota de OSM serrada \ No newline at end of file diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml index f5e8919fc8..b41cf8721c 100644 --- a/OsmAnd/res/values-sk/strings.xml +++ b/OsmAnd/res/values-sk/strings.xml @@ -3812,4 +3812,10 @@ Aktuálny cieľový bod na trase bude vymazaný. Ak je to posledný cieľ, navigácia sa zastaví. Stiahnuť mapy Wikipédia Získajte informácie o bodoch záujmu z Wikipédie. Je to váš vreckový sprievodca - zapnite modul Wikipédia a užívajte si články o objektoch okolo vás. + Enduro motorka + Skúter + Invalidný vozík + Invalidný vozík dopredu + Motokára + Zatvorená OSM poznámka \ No newline at end of file diff --git a/OsmAnd/res/values-sr/phrases.xml b/OsmAnd/res/values-sr/phrases.xml index b220869840..2908da2fc3 100644 --- a/OsmAnd/res/values-sr/phrases.xml +++ b/OsmAnd/res/values-sr/phrases.xml @@ -2933,4 +2933,702 @@ Плотун експлозија: прва детонација плотун теста Куглање Мрежа + Продаја: половна + Продаја: да, половна + Продаја: не + Продаја + Штандови + Рептили + Соколарник + Птичник + Птице + Сафари парк + Кућиште + Парк дивљих животиња + Зоолошки врт са мажењем животиња + Животни прстен + Школа страних језика + Музичка школа + Дечији камп + Поправка електронике: ТВ + Поправка електронике: телефон + Поправка електронике: апарати + Поправка електронике: рачунари + Канцеларија снабдевача енергије + Вино: сервирано + Вино: малопродаја + Вино: да + Да + Заједнички радни простор + Теретна станица + Конструкција: скривена + Конструкција: купола + Конструкција: тањир + Конструкција: самостојећа + Конструкција: решетка + Тип: отворена штала + Бушеншанк + Затворено + Отворено + Видљивост: подручје + Видљивост: улица + Видљивост: кућа + Локација: улаз + Локација: зид + Локација: мост + Локација: платформа + Локација: унутар + Локација: напољу + Локација: врх крова + Локација: кров + Локација: изнад главе + Локација: надземље + Локација: подводна + Локација: подземна + Метална мрежа + Декотрава + Вештачка трава + Тартан + Глина + Планинско подручје + Кулуар + Клисура + ВХФ канал + Законодавна институција + Транспортна институција + Благајна + Социјалне услуге + Социјално осигурање + Јавни сервис + Министарство + Архива + Мрежа + Кану: не + Кану: да + Кајаци: не + Кајаци: да + Гумењак: не + Гумењак: да + Једрењаци: не + Једрењаци: да + Џетски: не + Џетски: да + Бродови на веслање: не + Бродови на веслање: да + Кућни бродови: не + Кућни бродови: да + Моторни бродови: не + Моторни бродови: да + Тип: ограђен део + Чување животиња: овца + Чување животиња: коњ + Чување животиња + Литица + Фото студио + Додаци исхрани + Локомотива + Продавница електронских цигарета + Бинго + Клађење + Слот машине + Пацинко + Лутрија + Врста + Место коцкања + Лото срећке + Опрема за расвету + Браварска продавница + Електро продавница + Намирнице за забаву + Место за исхрану животиња + Кантонска + Пастел + Суб + Сагардотегиа + Чај са мехурићима + Брасери + Емпанада + Предјело + Пиадина + Кантина + Слане палачинке + Замрзнути јогурт + Деликатеси + Фина јела + Соба + Багел + Хеуригер + Гастропуб + Гиудон + Риба и помфрит + Тип: метални орман + Тип: дрвени ормар + Тип: кутија за читање + Тип: телефонска кутија + Јавна полица за књиге + Божић: вебсајт + Божић: локација + Божић: радно време + Божић: белешка + Божић: период догађаја + Јелка + Продавница дрвећа + Божићна радња + Божићна пирамида + Божићно тржиште + Божићни догађај + Божић + Википедија + Дужина + Одлагање тоалета: кантом + Одлагање тоалета: хемијско + Одлагање тоалета: питлатрине + Одлагање тоалета: испирање + Резервоар за воду + Противпожарни оператор + Висока комисија + Резиденција амбасадора + Делегација + Стална мисија + Почасни конзулат + Генерални конзулат + Конзулат + Саобраћајно огледало + Једино + Не + Да + Минимална старост + Главни дистрибуциони оквир + Аквакултура: дагње + Аквакултура: риба + Аквакултура: шкампи + Аквакултура + Приказ информација путницима: не + Приказ информација путницима: да + Подршка: кула + Подршка: кров + Подршка: носеће + Подршка: плафон + Подршка: билбord + Подршка: земља + Подршка: постоље + Подршка: дрво + Подршка: зид + Подршка: стуб + Приказ датума: не + Приказ датума + Хигрометар: не + Капацитет (кревета) + ХигрометарHygrometer + Термометар: не + Термометар + Сунчани сат + Дигитални екран + Аналогни екран + Пумпна станица + Екран: не + Екран: да + Излаз: биогас + Излазна снага биогаса + Излаз: вакуум + Излаз: компримовани ваздух + Излаз: хладна вода + Излаз: врућ ваздух + Излаз: пара + Излаз: топла вода + Излаз (струја): не + Излаз: струја + Напон + Стакленичка хортикултура + Гравитациона + Метеоролошка + Употреба: шпијунажа + Употреба: истраживање + Употреба: шпијунажа + Употреба: образовање + Спектар + Пречник + Гама + Радио + Оптички + Телескоп + Картица \"Тројка\" се не прихвата + Тројка + Статус пумпе: закључана + Статус пумпе: поломљена + Статус пумпе: у реду + Стил пумпе: историјски + Стил пумпе: модеран + Тип пумпе: гравитациона + Тип пумпе: Индија Мк II или III> + Тип пумпе: пумпа снопа + Вентилациони отвор + Балка + Приватни + Јавни + Регионални + Међународни + Испорука: не + Да + Надзор прелаза: камера + Надзор прелаза: полазник + Надзор прелаза: не + Надзор прелаза + Прелазни салтир: не + Прелазни салтир + Прелаз на захтев: не + Прелаз на захтев + Прелазно светло: не + Прелазно светло + Прелазно звоно: не + Прелазно звоно + Прелазна баријера: дупло половична + Прелазна баријера: половична + Прелазна баријера: пуна + Прелазна баријера + Прелазна баријера: не + Активирање прелаза: даљинско + Активирање прелаза: локално + Активирање прелаза: аутоматско + Рекреациони центар + Летњи камп + Покварена гомила + Одређено + Со: не + Со + Дубина + Улично постоље + Бицикл дрво + Ормарићи + Војни контролни пункт + Тип кабинета: улична расвета + Тип кабинета: водоводни + Тип кабинета: отпади + Тип кабинета: поштански + Тип кабинета: гасни + Тип кабинета: кабловска телевизија + Тип кабинета: телекомски + Тип кабинета: енергетски + У употреби: да + Цистерна + Ток + Понд + Главни + Стил хидранта: wsh + Подземни + Улица + Паркинг + Трака + Зелена + Тротоар + Капацитет протока хидранта + Број хидранта + Притисак хидранта + Пречник хидранта + Канцеларија бабице + Услуга неге + Канцеларија психолога + Канцеларија исцелитеља + Канцеларија подолога + Канцеларија терапеута + Лекарска ординација + СИДА: не + СИДА: да + Аутизам: не + Аутизам: да + Ебола: не + Ебола: да + Маларија: не + Маларија: да + Кућна посета: не + Да + Хитна: не + Хитна: да + Саветовање: не + Саветовање: да + Болничке услуге: само + Болничке услуге: не + Болничке услуге: да + Предвиђено за дечаке: не + Предвиђено за дечаке: да + Предвиђено за мушкарце: не + Предвиђено за мушкарце: да + Предвиђено за девојке: не + Предвиђено за девојке: да + Предвиђено за старије особе: не + Предвиђено за старије особе: да + Предвиђено за жене: не + Предвиђено за жене: да + Предвиђено за одрасле: не + Предвиђено за одрасле: да + Предвиђено за децу: не + Предвиђено за децу: да + Предвиђено за малишане: не + Предвиђено за малишане: да + Предвиђено за новорођенчад: не + Предвиђено за новорођенчад: да + Саветовање (насиље): не + Саветовање (насиље): да + Саветовање (жртве): не + Саветовање (жртве): да + Саветовање (сексуално злостављање): не + Саветовање (сексуално злостављање): да + Саветовање (сексуално): не + Саветовање (сексуално): да + Саветовање (рехабилитација): не + Саветовање (рехабилитација): да + Саветовање (исхрана): не + Саветовање (исхрана): да + Атол + Донација крви + Медицинска лабораторија + Велепродаја + Производња кондиторских производа + Теренско прикупљање + Уређај инспекције + Вентилски групна + Вентилска + Мерна + Компресиона + Компензациона + Претварачка + Вучна + Прелазна + Индустријска + Мања дистрибуциона + Дистрибуциона + Преносна + Цевоводна подстаница + Једино + Да + Поправка обуће + Брдо + Лиценцни часови + Рушевине + Минско поље + Опасност од поплаве + Клизав пут + Опасност од лавине + Опасност од ерозије + Нуклеарна опасност + Опасност + Бесконтактно не прихвата се + Бесконтактно + Нагла појава + Продавница апарата + Крајњи датум + Стена + Курс + Електронски + Инјектор + Код + Тачка уреза + Пешачка контролна тачка + Просечан нагиб + Најнижа тачка + Највиша тачка + Ледени језик + Остатак + Полица + Стена + Ледопад + Висећи + Планински + Плимски + Излазни + Долина + Плато + Ледено поље + Ледена капа + Тежина + Број кабла + Виа ферата + Авантура пењања + Зип линија + Гуме + Осигурање + Мотор + Поправка трансмисије + Реглажа + Пригушивач + Поправка камиона + Стакло + Точкови + Електрика + Поправка каросерије + Клима уређај + Батерије + Ауто делови + Дијагностика + Продаја нових аутомобила + Кочнице + Продаја половних аутомобила + Промена уља + Ауто сервис + Играчки центар за одрасле + Забавна аркадна игра + Канцеларија за водоснабдевање + Место испоруке продавнице + Име речних брзака + Керамика + Продавница подова + Низак + Средњи + Висок + Низак + Средњи + Висок + Низак + Средњи + Висок + Низак + Средњи + Висок + Низак + Средњи + Висок + Низак + Средњи + Висок + АС / НЗС 3112 + БС 1363 + Шуко + НЕМА 14-30 + НЕМА 14-30 + НЕМА 5-20 + НЕМА 5-15Р + Тесла Роудстер + Тесла Суперпуњач + Тесла стандард + CHAdeMO + Тип 3 + Тип 2 комбо + Тип 2 + Тип 1 комбо + Тип 1 + ЦЕЕ црвена 125А + ЦЕЕ црвена 64А + ЦЕЕ црвена 32А + ЦЕЕ црвена 16А + ЦЕЕ плава + Продавница канабиса + Продавница чамаца + Продавница камина + Замрзнута храна + Тип: пашњак + Тип: трајна + Тип: прелазна + Пречник круне + Обим + Пењачке руте + Дневник врха пењања: не + Дневник врха пењања: да + Оријентација зида: СЗ + Оријентација зида: З + Оријентација зида: ЈЗ + Оријентација зида: Ј + Оријентација зида: ЈИ + Оријентација зида: И + Оријентација зида: СИ + Оријентација зида: С + Фиксна сидра: не + Фиксна сидра: да + Квалитет пењања: крх + Квалитет пењања: чврст + Стена за пењање: порфир + Стена за пењање: гнеисс + Стена за пењање: кварцит + Стена за пењање: пешчењак + Пењање на камен: гранит + Стена за пењање: кречњак + Максимална дужина пењања + Минимална дужина пењања + Дужина пењања + Соло у дубљим водама: не + Соло у дубљим водама: да + Мешовито: не + Мешовито: да + Лед: не + Лед: да + Руте на више тачака: не + Руте са више тачака: да + Традиционално: не + Традиционално: да + Горње уже: не + Горње уже: да + Балванирање: не + Балванирање: да + Спорт: не + Спорт: да + Поштански број + Трансфер новца + Центар плаћања + Стан + Кућни број + Улица + Кутија писма + Депо + Станица пуњење + Величина мапе: регија + Величина мапе: град + Величина мапе: сајт + Тип мапе: топоскопска + Тип мапе: шема + Врста мапе: улична + Врста мапе: топо + Излаз станице пуњења + Ампеража + Цена паркирања + Цена паркирања: не + Цена паркирања: да + Камион: не + Камион: да + Скутер: не + Скутер: да + Бицикл: не + Бицикл: да + Аутомобил: не + Аутомобил: да + Утичница: АС / НЗС 3112: излаз + Утичница: АС / НЗС 3112: струја + Утичница: АС / НЗС 3112 + Утичница: БС 1363: излаз + Утичница: БС 1363: струја + Утичница: БС 1363 + Утичница: Шуко: излаз + Утичница: Шуко: струја + Утичница: Шуко + Утичница: НЕМА 14-50: излаз + Утичница: НЕМА 14-50: струја + Утичница: НЕМА 14-50 + Утичница: НЕМА 14-30: излаз + Утичница: НЕМА 14-30: струја + Утичница: НЕМА 14-30 + Утичница: НЕМА 5-20: излаз + Утичница: НЕМА 5-20: струја + Утичница: НЕМА 5-20 + Утичница: НЕМА 5-15Р: излаз + Утичница: НЕМА 5-15Р: струја + Утичница: НЕМА 5-15Р + Утичница: Тесла Роудстер: излаз + Утичница: Тесла Роудстер: струја + Утичница: Тесла Роудстер + Утичница: Тесла суперпуњач: излаз + Утичница: Тесла суперпуњач: струја + Утичница: Тесла суперпуњач + Утичница: Тесла стандард: излаз + Утичница: Тесла стандард: струја + Утичница: Тесла стандард + Утичница: CHAdeMO: излаз + Утичница: CHAdeMO: струја + Утичница: CHAdeMO + Утичница: Тип 3: излаз + Утичница: Тип 3: струја + Утичница: Тип 3 + Утичница: Тип 2 комбо: излаз + Утичница: Тип 2 комбо: струја + Утичница: Тип 2 комбо + Утичница: Тип 2: излаз + Утичница: Тип 2: струја + Утичница: Тип 2 + Утичница: Тип 1 комбо: излаз + Утичница: Тип 1 комбо: струја + Утичница: Тип 1 комбо + Соцкет: Тип 1: излаз + Утичница: Тип 1: струја + Утичница: Тип 1 + Утичница: ЦЕЕ црвена 125А: излаз + Утичница: ЦЕЕ црвена 125А: струја + Утичница: ЦЕЕ црвена 125А + Утичница: ЦЕЕ црвена 64А: излаз + Утичница: ЦЕЕ црвена 64А: струја + Утичница: ЦЕЕ црвена 64А + Утичница: ЦЕЕ црвена 32А: излаз + Утичница: ЦЕЕ црвена 32А: струја + Утичница: ЦЕЕ црвена 32А + Утичница: ЦЕЕ црвена 16А: излаз + Утичница: ЦЕЕ црвена 16А: струја + Утичница: ЦЕЕ црвена 16А + Утичница: ЦЕЕ плава: излаз + Утичница: ЦЕЕ плава: струја + Утичница: ЦЕЕ плава + Флаширана вода + Резервоар за воду + Превоз воде + Бушотина + Пумпа + Текућа вода + Цевовод + Бунар + Акватаблете + Обрнута осмоза + Хлор + Нема + Трајност воденог места: хитно + Трајност воденог места: издржљива + Потребно одржавање + Прекинуто + Ограничен + Локација: киоск + Изнајмљивање чамаца + Кревети + Резервација: само чланови + Резервација: не + Резервација: да + Резервације: препоручује се + Резервација: обавезна + Зимска соба: не + Зимска соба: да + Правац: сви + Правац: излаз + Правац: улаз + Правац: надоле + Правац: нагоре + Правац: супротно од казаљке на сату + Правац: у смеру казаљке на сату + Правац: уназад + Правац: напред + Правац: север-северозапад + Правац: северозапад + Правац: запад-северозапад + Правац: запад + Правац: запад-југозапад + Правац: југозапад + Правац: југ-југозапад + Правац: југ + Правац: југ-југоисток + Правац: југоисток + Правац: исток-југоисток + Правац: исток + Правац: исток-североисток + Правац: североисток + Правац: север-североисток + Правац: север + Свемирска лука + Пуштање: не + Пуштање: да + Усвајање: не + Усвајање: да + Власник + Стандардни + Дуалспорт + Ван пута + Чопер + Спортски моторцикл + Скутер + Мото одећа: не + Мото одећа + Гуме: не + Гуме + Делови: не + Делови + Поправака: не + Поправка + Изнајмљивање: не + Изнајмљивање + Да + Ознака земље + Природни споменик + Брига о деци + Путарина \ No newline at end of file diff --git a/OsmAnd/res/values-sr/strings.xml b/OsmAnd/res/values-sr/strings.xml index 0d73885ba5..7a19f27534 100644 --- a/OsmAnd/res/values-sr/strings.xml +++ b/OsmAnd/res/values-sr/strings.xml @@ -3813,4 +3813,8 @@ Информације о тачкама од интереса потражите од Википедије. То је ваш џепни ванмрежни водич - само омогућите додатак Википедиа и уживајте у чланцима о објектима око вас. Ендуро скутер Скутер + Инвалидска колица + Инвалидска колица напред + Корпа + Затворена ОСМ белешка \ No newline at end of file diff --git a/OsmAnd/res/values-sv/phrases.xml b/OsmAnd/res/values-sv/phrases.xml index 4306fea7c0..60e90c4246 100644 --- a/OsmAnd/res/values-sv/phrases.xml +++ b/OsmAnd/res/values-sv/phrases.xml @@ -1640,7 +1640,7 @@ Ja Drive-in: nej Ja - Drive-through: ja + Drive-through: nej Bryggerinamn Ja Inget mikrobryggeri diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml index 612339d2a6..268467dae2 100644 --- a/OsmAnd/res/values-tr/strings.xml +++ b/OsmAnd/res/values-tr/strings.xml @@ -2500,7 +2500,7 @@ Nokta ekle Açıklamayı gizle Açıklamayı göster - Haritaları taşı + Haritaları hareket ettir Yürüme navigasyonunu dene. Ayarları değiştirmeyi deneyin. Restore et @@ -3771,4 +3771,8 @@ Wikipedia\'dan ilgi çekici yerler hakkında bilgi alın. Bu sizin çevrim dışı cep rehberinizdir - sadece Wikipedia eklentisini etkinleştirin ve etrafınızdaki nesneler hakkında makalelerin tadını çıkarın. Enduro motosiklet Küçük motosiklet + Tekerlekli sandalye + İleri tekerlekli sandalye + Go-kart + Kapatılmış OSM Notu \ No newline at end of file diff --git a/OsmAnd/res/values-uk/phrases.xml b/OsmAnd/res/values-uk/phrases.xml index 530cedf2c2..3c309cdf27 100644 --- a/OsmAnd/res/values-uk/phrases.xml +++ b/OsmAnd/res/values-uk/phrases.xml @@ -3817,4 +3817,7 @@ Вібрація: вимкнено Стрілка Вібрація + Міський квартал + Район + Подарункова коробка \ No newline at end of file diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index 3d8ce5177f..41f145794f 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -1127,7 +1127,7 @@ Маршрутна точка " \n -\nДовго утримуйте, щоб побачити на мапі" +\nУтримуйте, щоб побачити на мапі" Запускати навігацію автоматично виділені Під-треки: %1$s @@ -3124,7 +3124,7 @@ Прогулянки, походи, біг Види громадського транспорту Корабель, веслування, вітрильний спорт - Літак, аероглайдинг + Літак, планер Геокодування Пряма лінія BRouter (автономний) @@ -3407,10 +3407,10 @@ Позиція значка в спокої Натиснення \"Застосувати\" видалить профілі назавжди. Основний профіль - Оберіть колір + Виберіть колір Усталені профілі OsmAnd не видалено, проте вимкнуто (на попередньому екрані) чи відпорядковано донизу. Редагувати профілі - \"Вид навігації\" визначає спосіб обчислення маршрутів. + \'Тип навігації\' визначає спосіб обчислення маршрутів. Зовнішній вигляд профілю Значок, колір та назва Редагувати список профілів @@ -3805,8 +3805,14 @@ Масштабування кнопками гучності Вкажіть довжину вашого автомобіля, для довгих транспортних засобів можуть застосовуватися деякі обмеження на маршрутах. Видалити наступну точку призначення - Укажіть назву пункту + Вкажіть назву пункту Поточну точку призначення на маршруті буде видалено. Якщо це буде місце призначення, навігація припиниться. Завантажити мапи Вікіпедії Отримайте відомості про визначні місця у Вікіпедії. Це ваш кишеньковий посібник без мережі - просто ввімкніть втулок \"Вікіпедія\" і насолоджуйтесь статтями про об\'єкти навколо вас. + Моторолер + легкий мотоцикл + Інвалідне крісло + Інвалідне крісло попереду + у мапу + Закрита нотатка OSM \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index 9dc5ab36ad..88c644aee8 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -3811,4 +3811,8 @@ 從維基百科取得關於興趣點的資訊。這是您的離線口袋指南 ── 只要啟用維基百科外掛程式並享受有關於您周圍景點的文章。 耐力賽摩托車 小型摩托車 + 輪椅 + 輪椅向前 + 卡丁車 + 已關閉的 OSM 註記 \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java index 582d6972ee..96686c9956 100644 --- a/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java +++ b/OsmAnd/src/net/osmand/aidl/OsmandAidlApi.java @@ -43,6 +43,7 @@ import net.osmand.data.PointDescription; import net.osmand.plus.AppInitializer; import net.osmand.plus.AppInitializer.AppInitializeListener; import net.osmand.plus.AppInitializer.InitEvents; +import net.osmand.plus.dialogs.GpxAppearanceAdapter; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuItem; @@ -60,7 +61,6 @@ import net.osmand.plus.SQLiteTileSource; import net.osmand.plus.settings.backend.SettingsHelper; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.audionotes.AudioVideoNotesPlugin; -import net.osmand.plus.dialogs.ConfigureMapMenu; import net.osmand.plus.helpers.ColorDialogs; import net.osmand.plus.helpers.ExternalApiHelper; import net.osmand.plus.mapcontextmenu.MapContextMenu; @@ -1146,7 +1146,7 @@ public class OsmandAidlApi { @SuppressLint("StaticFieldLeak") private void finishGpxImport(boolean destinationExists, File destination, String color, boolean show) { - final int col = ConfigureMapMenu.GpxAppearanceAdapter.parseTrackColor( + final int col = GpxAppearanceAdapter.parseTrackColor( app.getRendererRegistry().getCurrentSelectedRenderer(), color); if (!destinationExists) { GpxDataItem gpxDataItem = new GpxDataItem(destination, col); @@ -1390,7 +1390,7 @@ public class OsmandAidlApi { int color = dataItem.getColor(); String colorName = ""; if (color != 0) { - colorName = ConfigureMapMenu.GpxAppearanceAdapter.parseTrackColorName(app.getRendererRegistry().getCurrentSelectedRenderer(), color); + colorName = GpxAppearanceAdapter.parseTrackColorName(app.getRendererRegistry().getCurrentSelectedRenderer(), color); } net.osmand.aidlapi.gpx.AGpxFileDetails details = null; GPXTrackAnalysis analysis = dataItem.getAnalysis(); @@ -1431,7 +1431,7 @@ public class OsmandAidlApi { if (file.getName().equals(gpxFileName)) { int color = dataItem.getColor(); if (color != 0) { - return ConfigureMapMenu.GpxAppearanceAdapter.parseTrackColorName(app.getRendererRegistry().getCurrentSelectedRenderer(), color); + return GpxAppearanceAdapter.parseTrackColorName(app.getRendererRegistry().getCurrentSelectedRenderer(), color); } } } diff --git a/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java b/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java index 5fce920b91..a50a345aa3 100644 --- a/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java +++ b/OsmAnd/src/net/osmand/plus/CurrentPositionHelper.java @@ -237,6 +237,7 @@ public class CurrentPositionHelper { List complete = new ArrayList<>(); double minBuildingDistance = 0; if (res != null) { + GeocodingUtilities gu = new GeocodingUtilities(); for (GeocodingResult r : res) { BinaryMapIndexReader foundRepo = null; List rts = usedReaders; @@ -259,7 +260,7 @@ public class CurrentPositionHelper { } else if (foundRepo != null) { List justified = null; try { - justified = new GeocodingUtilities().justifyReverseGeocodingSearch(r, foundRepo, + justified = gu.justifyReverseGeocodingSearch(r, foundRepo, minBuildingDistance, result); } catch (IOException e) { log.error("Exception happened during reverse geocoding", e); @@ -277,6 +278,7 @@ public class CurrentPositionHelper { complete.add(r); } } + gu.filterDuplicateRegionResults(complete); } if (result.isCancelled()) { @@ -287,7 +289,7 @@ public class CurrentPositionHelper { }); return; } - Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); +// Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); // for(GeocodingResult rt : complete) { // System.out.println(rt.toString()); // } diff --git a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java index 2c232ea8e8..e0cb743a64 100644 --- a/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/CustomOsmandPlugin.java @@ -22,7 +22,7 @@ import net.osmand.plus.settings.backend.SettingsHelper; import net.osmand.plus.settings.backend.SettingsHelper.AvoidRoadsSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.MapSourcesSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.PluginSettingsItem; -import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFilterSettingsItem; +import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFiltersSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.QuickActionsSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.SettingsCollectListener; @@ -305,9 +305,9 @@ public class CustomOsmandPlugin extends OsmandPlugin { Algorithms.removeAllFiles(dir); } } - } else if (item instanceof PoiUiFilterSettingsItem) { - PoiUiFilterSettingsItem poiUiFilterSettingsItem = (PoiUiFilterSettingsItem) item; - List poiUIFilters = poiUiFilterSettingsItem.getItems(); + } else if (item instanceof PoiUiFiltersSettingsItem) { + PoiUiFiltersSettingsItem poiUiFiltersSettingsItem = (PoiUiFiltersSettingsItem) item; + List poiUIFilters = poiUiFiltersSettingsItem.getItems(); for (PoiUIFilter filter : poiUIFilters) { app.getPoiFilters().removePoiFilter(filter); } diff --git a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java index f6bb1866e7..4b9dc43eb3 100644 --- a/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/FavouritesDbHelper.java @@ -679,6 +679,16 @@ public class FavouritesDbHelper { return favoriteGroups; } + public boolean isGroupVisible(String name) { + String nameLowercase = name.toLowerCase(); + for (String groupName : flatGroups.keySet()) { + if (groupName.toLowerCase().equals(nameLowercase) || FavoriteGroup.getDisplayName(context, groupName).equals(name)) { + return flatGroups.get(groupName).isVisible(); + } + } + return false; + } + public boolean groupExists(String name) { String nameLowercase = name.toLowerCase(); for (String groupName : flatGroups.keySet()) { @@ -800,10 +810,12 @@ public class FavouritesDbHelper { public void editFavouriteGroup(FavoriteGroup group, String newName, int color, boolean visible) { if (color != 0 && group.color != color) { FavoriteGroup gr = flatGroups.get(group.name); - group.color = color; for (FavouritePoint p : gr.points) { - p.setColor(color); + if (p.getColor() == group.color) { + p.setColor(color); + } } + group.color = color; runSyncWithMarkers(gr); } if (group.visible != visible) { diff --git a/OsmAnd/src/net/osmand/plus/GPXDatabase.java b/OsmAnd/src/net/osmand/plus/GPXDatabase.java index 94b1a993b6..d0a19e80b9 100644 --- a/OsmAnd/src/net/osmand/plus/GPXDatabase.java +++ b/OsmAnd/src/net/osmand/plus/GPXDatabase.java @@ -3,6 +3,8 @@ package net.osmand.plus; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.GPXFile.GradientScaleType; import net.osmand.GPXUtilities.GPXTrackAnalysis; import net.osmand.IndexConstants; import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; @@ -15,8 +17,9 @@ import java.util.List; public class GPXDatabase { + private static final int DB_VERSION = 11; private static final String DB_NAME = "gpx_database"; - private static final int DB_VERSION = 10; + private static final String GPX_TABLE_NAME = "gpxTable"; private static final String GPX_COL_NAME = "fileName"; private static final String GPX_COL_DIR = "fileDir"; @@ -56,9 +59,19 @@ public class GPXDatabase { private static final String GPX_COL_JOIN_SEGMENTS = "joinSegments"; - public static final int GPX_SPLIT_TYPE_NO_SPLIT = -1; - public static final int GPX_SPLIT_TYPE_DISTANCE = 1; - public static final int GPX_SPLIT_TYPE_TIME = 2; + private static final String GPX_COL_SHOW_ARROWS = "showArrows"; + + private static final String GPX_COL_SHOW_START_FINISH = "showStartFinish"; + + private static final String GPX_COL_WIDTH = "width"; + + private static final String GPX_COL_GRADIENT_SPEED_COLOR = "gradientSpeedColor"; + + private static final String GPX_COL_GRADIENT_ALTITUDE_COLOR = "gradientAltitudeColor"; + + private static final String GPX_COL_GRADIENT_SLOPE_COLOR = "gradientSlopeColor"; + + private static final String GPX_COL_GRADIENT_SCALE_TYPE = "gradientScaleType"; private static final String GPX_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS " + GPX_TABLE_NAME + " (" + GPX_COL_NAME + " TEXT, " + @@ -89,7 +102,14 @@ public class GPXDatabase { GPX_COL_API_IMPORTED + " int, " + // 1 = true, 0 = false GPX_COL_WPT_CATEGORY_NAMES + " TEXT, " + GPX_COL_SHOW_AS_MARKERS + " int, " + // 1 = true, 0 = false - GPX_COL_JOIN_SEGMENTS + " int);"; // 1 = true, 0 = false + GPX_COL_JOIN_SEGMENTS + " int, " + // 1 = true, 0 = false + GPX_COL_SHOW_ARROWS + " int, " + // 1 = true, 0 = false + GPX_COL_SHOW_START_FINISH + " int, " + // 1 = true, 0 = false + GPX_COL_WIDTH + " TEXT, " + + GPX_COL_GRADIENT_SPEED_COLOR + " TEXT, " + + GPX_COL_GRADIENT_ALTITUDE_COLOR + " TEXT, " + + GPX_COL_GRADIENT_SLOPE_COLOR + " TEXT, " + + GPX_COL_GRADIENT_SCALE_TYPE+ " TEXT);"; private static final String GPX_TABLE_SELECT = "SELECT " + GPX_COL_NAME + ", " + @@ -117,8 +137,15 @@ public class GPXDatabase { GPX_COL_API_IMPORTED + ", " + GPX_COL_WPT_CATEGORY_NAMES + ", " + GPX_COL_SHOW_AS_MARKERS + ", " + - GPX_COL_JOIN_SEGMENTS + - " FROM " + GPX_TABLE_NAME; + GPX_COL_JOIN_SEGMENTS + ", " + + GPX_COL_SHOW_ARROWS + ", " + + GPX_COL_SHOW_START_FINISH + ", " + + GPX_COL_WIDTH + ", " + + GPX_COL_GRADIENT_SPEED_COLOR + ", " + + GPX_COL_GRADIENT_ALTITUDE_COLOR + ", " + + GPX_COL_GRADIENT_SLOPE_COLOR + ", " + + GPX_COL_GRADIENT_SCALE_TYPE + + " FROM " + GPX_TABLE_NAME; private static final String GPX_TABLE_UPDATE_ANALYSIS = "UPDATE " + GPX_TABLE_NAME + " SET " + @@ -144,15 +171,23 @@ public class GPXDatabase { private OsmandApplication context; public static class GpxDataItem { + private File file; private GPXTrackAnalysis analysis; + private String width; + private GradientScaleType gradientScaleType; private int color; - private long fileLastModifiedTime; + private int gradientSpeedColor; + private int gradientAltitudeColor; + private int gradientSlopeColor; private int splitType; private double splitInterval; + private long fileLastModifiedTime; private boolean apiImported; private boolean showAsMarkers; private boolean joinSegments; + private boolean showArrows; + private boolean showStartFinish; public GpxDataItem(File file, GPXTrackAnalysis analysis) { this.file = file; @@ -164,6 +199,22 @@ public class GPXDatabase { this.color = color; } + public GpxDataItem(File file, @NonNull GPXFile gpxFile) { + this.file = file; + color = gpxFile.getColor(0); + width = gpxFile.getWidth(null); + showArrows = gpxFile.isShowArrows(); + showStartFinish = gpxFile.isShowStartFinish(); + gradientScaleType = gpxFile.getGradientScaleType(); + gradientSpeedColor = gpxFile.getGradientScaleColor(GradientScaleType.SPEED, 0); + gradientSlopeColor = gpxFile.getGradientScaleColor(GradientScaleType.SLOPE, 0); + gradientAltitudeColor = gpxFile.getGradientScaleColor(GradientScaleType.ALTITUDE, 0); + if (gpxFile.getSplitType() != null && gpxFile.getSplitInterval() != 0) { + splitType = gpxFile.getSplitType().getType(); + splitInterval = gpxFile.getSplitInterval(); + } + } + public File getFile() { return file; } @@ -177,6 +228,27 @@ public class GPXDatabase { return color; } + public GradientScaleType getGradientScaleType() { + return gradientScaleType; + } + + public int getGradientSpeedColor() { + return gradientSpeedColor; + } + + public int getGradientAltitudeColor() { + return gradientAltitudeColor; + } + + public int getGradientSlopeColor() { + return gradientSlopeColor; + } + + public String getWidth() { + return width; + } + + public long getFileLastModifiedTime() { return fileLastModifiedTime; } @@ -209,8 +281,12 @@ public class GPXDatabase { return joinSegments; } - public void setJoinSegments(boolean joinSegments) { - this.joinSegments = joinSegments; + public boolean isShowArrows() { + return showArrows; + } + + public boolean isShowStartFinish() { + return showStartFinish; } @Override @@ -273,7 +349,7 @@ public class GPXDatabase { if (oldVersion < 3) { db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_FILE_LAST_MODIFIED_TIME + " long"); } - + if (oldVersion < 4) { db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_SPLIT_TYPE + " int"); db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_SPLIT_INTERVAL + " double"); @@ -341,6 +417,20 @@ public class GPXDatabase { " SET " + GPX_COL_JOIN_SEGMENTS + " = ? " + "WHERE " + GPX_COL_JOIN_SEGMENTS + " IS NULL", new Object[]{0}); } + if (oldVersion < 11) { + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_SHOW_ARROWS + " int"); + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_SHOW_START_FINISH + " int"); + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_WIDTH + " TEXT"); + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_GRADIENT_SPEED_COLOR + " TEXT"); + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_GRADIENT_ALTITUDE_COLOR + " TEXT"); + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_GRADIENT_SLOPE_COLOR + " TEXT"); + db.execSQL("ALTER TABLE " + GPX_TABLE_NAME + " ADD " + GPX_COL_GRADIENT_SCALE_TYPE + " TEXT"); + + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_SHOW_ARROWS + " = ? " + + "WHERE " + GPX_COL_SHOW_ARROWS + " IS NULL", new Object[]{0}); + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_SHOW_START_FINISH + " = ? " + + "WHERE " + GPX_COL_SHOW_START_FINISH + " IS NULL", new Object[]{1}); + } db.execSQL("CREATE INDEX IF NOT EXISTS " + GPX_INDEX_NAME_DIR + " ON " + GPX_TABLE_NAME + " (" + GPX_COL_NAME + ", " + GPX_COL_DIR + ");"); } @@ -391,8 +481,7 @@ public class GPXDatabase { try { String fileName = getFileName(item.file); String fileDir = getFileDir(item.file); - db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + - GPX_COL_COLOR + " = ? " + + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_COLOR + " = ? " + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", new Object[] { (color == 0 ? "" : Algorithms.colorToString(color)), fileName, fileDir }); item.color = color; @@ -404,6 +493,106 @@ public class GPXDatabase { return false; } + public boolean updateGradientScaleColor(@NonNull GpxDataItem item, @NonNull GradientScaleType gradientScaleType, int gradientScaleColor) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String fileName = getFileName(item.file); + String fileDir = getFileDir(item.file); + String columnName = null; + if (GradientScaleType.SPEED == gradientScaleType) { + columnName = GPX_COL_GRADIENT_SPEED_COLOR; + item.gradientSpeedColor = gradientScaleColor; + } else if (GradientScaleType.ALTITUDE == gradientScaleType) { + columnName = GPX_COL_GRADIENT_ALTITUDE_COLOR; + item.gradientAltitudeColor = gradientScaleColor; + } else if (GradientScaleType.SLOPE == gradientScaleType) { + columnName = GPX_COL_GRADIENT_SLOPE_COLOR; + item.gradientSlopeColor = gradientScaleColor; + } + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + columnName + " = ? " + + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] {(gradientScaleColor == 0 ? "" : Algorithms.colorToString(gradientScaleColor)), fileName, fileDir}); + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean updateGradientScaleType(@NonNull GpxDataItem item, GradientScaleType gradientScaleType) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String fileName = getFileName(item.file); + String fileDir = getFileDir(item.file); + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_GRADIENT_SCALE_TYPE + " = ? " + + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] {(gradientScaleType == null ? "" : gradientScaleType.name()), fileName, fileDir}); + item.gradientScaleType = gradientScaleType; + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean updateShowArrows(GpxDataItem item, boolean showArrows) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String fileName = getFileName(item.file); + String fileDir = getFileDir(item.file); + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_SHOW_ARROWS + " = ? " + + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] {showArrows ? 1 : 0, fileName, fileDir}); + item.showArrows = showArrows; + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean updateShowStartFinish(GpxDataItem item, boolean showStartFinish) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String fileName = getFileName(item.file); + String fileDir = getFileDir(item.file); + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_SHOW_START_FINISH + " = ? " + + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] {showStartFinish ? 1 : 0, fileName, fileDir}); + item.showStartFinish = showStartFinish; + } finally { + db.close(); + } + return true; + } + return false; + } + + public boolean updateWidth(GpxDataItem item, String width) { + SQLiteConnection db = openConnection(false); + if (db != null) { + try { + String fileName = getFileName(item.file); + String fileDir = getFileDir(item.file); + db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + GPX_COL_WIDTH + " = ? " + + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", + new Object[] {width, fileName, fileDir}); + item.width = width; + } finally { + db.close(); + } + return true; + } + return false; + } + public boolean updateShowAsMarkers(GpxDataItem item, boolean showAsMarkers) { SQLiteConnection db = openConnection(false); if (db != null) { @@ -433,7 +622,7 @@ public class GPXDatabase { GPX_COL_JOIN_SEGMENTS + " = ? " + " WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?", new Object[]{joinSegments ? 1 : 0, fileName, fileDir}); - item.setJoinSegments(joinSegments); + item.joinSegments = joinSegments; } finally { db.close(); } @@ -516,14 +705,17 @@ public class GPXDatabase { } else { color = Algorithms.colorToString(item.color); } + String gradientScaleType = item.gradientScaleType != null ? item.gradientScaleType.name() : null; if (a != null) { db.execSQL( - "INSERT INTO " + GPX_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO " + GPX_TABLE_NAME + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[] {fileName, fileDir, a.totalDistance, a.totalTracks, a.startTime, a.endTime, a.timeSpan, a.timeMoving, a.totalDistanceMoving, a.diffElevationUp, a.diffElevationDown, a.avgElevation, a.minElevation, a.maxElevation, a.maxSpeed, a.avgSpeed, a.points, a.wptPoints, color, item.file.lastModified(), item.splitType, item.splitInterval, item.apiImported ? 1 : 0, - Algorithms.encodeStringSet(item.analysis.wptCategoryNames), item.showAsMarkers ? 1 : 0, item.joinSegments ? 1 : 0}); + Algorithms.encodeStringSet(item.analysis.wptCategoryNames), item.showAsMarkers ? 1 : 0, + item.joinSegments ? 1 : 0, item.showArrows ? 1 : 0, item.showStartFinish ? 1 : 0, item.width, + item.gradientSpeedColor, item.gradientAltitudeColor, item.gradientSlopeColor, gradientScaleType}); } else { db.execSQL("INSERT INTO " + GPX_TABLE_NAME + "(" + GPX_COL_NAME + ", " + @@ -534,9 +726,19 @@ public class GPXDatabase { GPX_COL_SPLIT_INTERVAL + ", " + GPX_COL_API_IMPORTED + ", " + GPX_COL_SHOW_AS_MARKERS + ", " + - GPX_COL_JOIN_SEGMENTS + - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", - new Object[] {fileName, fileDir, color, 0, item.splitType, item.splitInterval, item.apiImported ? 1 : 0, item.showAsMarkers ? 1 : 0, item.joinSegments ? 1 : 0}); + GPX_COL_JOIN_SEGMENTS + ", " + + GPX_COL_SHOW_ARROWS + ", " + + GPX_COL_SHOW_START_FINISH + ", " + + GPX_COL_WIDTH + ", " + + GPX_COL_GRADIENT_SPEED_COLOR + ", " + + GPX_COL_GRADIENT_ALTITUDE_COLOR + ", " + + GPX_COL_GRADIENT_SLOPE_COLOR + ", " + + GPX_COL_GRADIENT_SCALE_TYPE + + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + new Object[] {fileName, fileDir, color, 0, item.splitType, item.splitInterval, + item.apiImported ? 1 : 0, item.showAsMarkers ? 1 : 0, item.joinSegments ? 1 : 0, + item.showArrows ? 1 : 0, item.showStartFinish ? 1 : 0, item.width, + item.gradientSpeedColor, item.gradientAltitudeColor, item.gradientSlopeColor, gradientScaleType}); } } @@ -617,6 +819,13 @@ public class GPXDatabase { String wptCategoryNames = query.getString(23); boolean showAsMarkers = query.getInt(24) == 1; boolean joinSegments = query.getInt(25) == 1; + boolean showArrows = query.getInt(26) == 1; + boolean showStartFinish = query.getInt(27) == 1; + String width = query.getString(28); + String gradientSpeedColor = query.getString(29); + String gradientAltitudeColor = query.getString(30); + String gradientSlopeColor = query.getString(31); + String gradientScaleType = query.getString(32); GPXTrackAnalysis a = new GPXTrackAnalysis(); a.totalDistance = totalDistance; @@ -647,20 +856,37 @@ public class GPXDatabase { dir = context.getAppPath(IndexConstants.GPX_INDEX_DIR); } GpxDataItem item = new GpxDataItem(new File(dir, fileName), a); - try { - item.color = Algorithms.isEmpty(color) ? 0 : Algorithms.parseColor(color); - } catch (IllegalArgumentException e) { - item.color = 0; - } + item.color = parseColor(color); item.fileLastModifiedTime = fileLastModifiedTime; item.splitType = splitType; item.splitInterval = splitInterval; item.apiImported = apiImported; item.showAsMarkers = showAsMarkers; item.joinSegments = joinSegments; + item.showArrows = showArrows; + item.showStartFinish = showStartFinish; + item.width = width; + item.gradientSpeedColor = parseColor(gradientSpeedColor); + item.gradientAltitudeColor = parseColor(gradientAltitudeColor); + item.gradientSlopeColor = parseColor(gradientSlopeColor); + + try { + item.gradientScaleType = Algorithms.isEmpty(gradientScaleType) ? null : GradientScaleType.valueOf(gradientScaleType); + } catch (IllegalArgumentException e) { + item.gradientScaleType = null; + } + return item; } + private int parseColor(String color) { + try { + return Algorithms.isEmpty(color) ? 0 : Algorithms.parseColor(color); + } catch (IllegalArgumentException e) { + return 0; + } + } + @NonNull public List getItems() { List items = new ArrayList<>(); diff --git a/OsmAnd/src/net/osmand/plus/GpxDbHelper.java b/OsmAnd/src/net/osmand/plus/GpxDbHelper.java index 41f19a020b..fc0ffb636e 100644 --- a/OsmAnd/src/net/osmand/plus/GpxDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxDbHelper.java @@ -8,6 +8,8 @@ import androidx.annotation.Nullable; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.GPXFile.GpxSplitType; +import net.osmand.GPXUtilities.GPXFile.GradientScaleType; import net.osmand.GPXUtilities.GPXTrackAnalysis; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.api.SQLiteAPI.SQLiteConnection; @@ -77,19 +79,49 @@ public class GpxDbHelper { return res; } + public boolean updateGradientScaleColor(@NonNull GpxDataItem item, @NonNull GradientScaleType gradientScaleType, int color) { + boolean res = db.updateGradientScaleColor(item, gradientScaleType, color); + putToCache(item); + return res; + } + + public boolean updateGradientScaleType(@NonNull GpxDataItem item, @Nullable GradientScaleType gradientScaleType) { + boolean res = db.updateGradientScaleType(item, gradientScaleType); + putToCache(item); + return res; + } + public boolean updateShowAsMarkers(GpxDataItem item, boolean showAsMarkers) { boolean res = db.updateShowAsMarkers(item, showAsMarkers); putToCache(item); return res; } - public boolean updateSplit(@NonNull GpxDataItem item, int splitType, double splitInterval) { - boolean res = db.updateSplit(item, splitType, splitInterval); + public boolean updateShowArrows(GpxDataItem item, boolean showArrows) { + boolean res = db.updateShowArrows(item, showArrows); putToCache(item); return res; } - public boolean updateJoinSegments(@NonNull GpxDataItem item, boolean joinSegments) { + public boolean updateShowStartFinish(GpxDataItem item, boolean showStartFinish) { + boolean res = db.updateShowStartFinish(item, showStartFinish); + putToCache(item); + return res; + } + + public boolean updateWidth(GpxDataItem item, String width) { + boolean res = db.updateWidth(item, width); + putToCache(item); + return res; + } + + public boolean updateSplit(@NonNull GpxDataItem item, @NonNull GpxSplitType splitType, double splitInterval) { + boolean res = db.updateSplit(item, splitType.getType(), splitInterval); + putToCache(item); + return res; + } + + public boolean updateJoinSegments(@NonNull GpxDataItem item, boolean joinSegments) { boolean res = db.updateJoinSegments(item, joinSegments); putToCache(item); return res; @@ -157,7 +189,7 @@ public class GpxDbHelper { } private void readGpxItem(@NonNull File gpxFile, @Nullable GpxDataItem item, @Nullable GpxDataItemCallback callback) { - readingItemsMap.put(gpxFile, item != null ? item : new GpxDataItem(null, null)); + readingItemsMap.put(gpxFile, item != null ? item : new GpxDataItem(null, (GPXTrackAnalysis) null)); if (callback != null) { readingItemsCallbacks.put(gpxFile, callback); } diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index f750056bd3..6f239e2286 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -11,6 +11,8 @@ import androidx.core.content.ContextCompat; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.GPXFile.GpxSplitType; +import net.osmand.GPXUtilities.GPXFile.GradientScaleType; import net.osmand.GPXUtilities.GPXTrackAnalysis; import net.osmand.GPXUtilities.Route; import net.osmand.GPXUtilities.Track; @@ -51,7 +53,11 @@ public class GpxSelectionHelper { private static final String BACKUP = "backup"; private static final String BACKUPMODIFIEDTIME = "backupTime"; private static final String COLOR = "color"; + private static final String WIDTH = "width"; private static final String SELECTED_BY_USER = "selected_by_user"; + private static final String SHOW_ARROWS = "show_arrows"; + private static final String GRADIENT_SCALE_TYPE = "gradient_scale_type"; + private static final String SHOW_START_FINISH = "show_start_finish"; private OsmandApplication app; @NonNull @@ -167,17 +173,17 @@ public class GpxSelectionHelper { if (selectedGpxFile != null && selectedGpxFile.getGpxFile() != null) { GPXFile gpxFile = selectedGpxFile.getGpxFile(); List groups = app.getSelectedGpxHelper().collectDisplayGroups(gpxFile); - if (dataItem.getSplitType() == GPXDatabase.GPX_SPLIT_TYPE_NO_SPLIT) { + if (dataItem.getSplitType() == GpxSplitType.NO_SPLIT.getType()) { for (GpxDisplayGroup model : groups) { model.noSplit(app); } selectedGpxFile.setDisplayGroups(groups, app); - } else if (dataItem.getSplitType() == GPXDatabase.GPX_SPLIT_TYPE_DISTANCE) { + } else if (dataItem.getSplitType() == GpxSplitType.DISTANCE.getType()) { for (GpxDisplayGroup model : groups) { model.splitByDistance(app, dataItem.getSplitInterval(), dataItem.isJoinSegments()); } selectedGpxFile.setDisplayGroups(groups, app); - } else if (dataItem.getSplitType() == GPXDatabase.GPX_SPLIT_TYPE_TIME) { + } else if (dataItem.getSplitType() == GpxSplitType.TIME.getType()) { for (GpxDisplayGroup model : groups) { model.splitByTime(app, (int) dataItem.getSplitInterval(), dataItem.isJoinSegments()); } @@ -515,6 +521,29 @@ public class GpxSelectionHelper { int clr = Algorithms.parseColor(obj.getString(COLOR)); gpx.setColor(clr); } + for (GradientScaleType scaleType : GradientScaleType.values()) { + if (obj.has(scaleType.getTypeName())) { + int clr = Algorithms.parseColor(obj.getString(scaleType.getTypeName())); + gpx.setGradientScaleColor(scaleType, clr); + } + } + if (obj.has(SHOW_ARROWS)) { + boolean showArrows = obj.optBoolean(SHOW_ARROWS, false); + gpx.setShowArrows(showArrows); + } + if (obj.has(GRADIENT_SCALE_TYPE)) { + String gradientScaleTypeName = obj.optString(GRADIENT_SCALE_TYPE); + if (!Algorithms.isEmpty(gradientScaleTypeName)) { + gpx.setGradientScaleType(GradientScaleType.valueOf(gradientScaleTypeName)); + } + } + if (obj.has(SHOW_START_FINISH)) { + boolean showStartFinish = obj.optBoolean(SHOW_START_FINISH, false); + gpx.setShowStartFinish(showStartFinish); + } + if (obj.has(WIDTH)) { + gpx.setWidth(obj.getString(WIDTH)); + } if (gpx.error != null) { save = true; } else if (obj.has(BACKUP)) { @@ -554,6 +583,20 @@ public class GpxSelectionHelper { if (s.gpxFile.getColor(0) != 0) { obj.put(COLOR, Algorithms.colorToString(s.gpxFile.getColor(0))); } + if (s.gpxFile.getWidth(null) != null) { + obj.put(WIDTH, s.gpxFile.getWidth(null)); + } + if (s.gpxFile.getGradientScaleType() != null) { + obj.put(GRADIENT_SCALE_TYPE, s.gpxFile.getGradientScaleType()); + } + obj.put(SHOW_ARROWS, s.gpxFile.isShowArrows()); + obj.put(SHOW_START_FINISH, s.gpxFile.isShowStartFinish()); + for (GradientScaleType scaleType : GradientScaleType.values()) { + int gradientScaleColor = s.gpxFile.getGradientScaleColor(scaleType, 0); + if (gradientScaleColor != 0) { + obj.put(scaleType.getTypeName(), Algorithms.colorToString(gradientScaleColor)); + } + } } obj.put(SELECTED_BY_USER, s.selectedByUser); } catch (JSONException e) { @@ -606,6 +649,23 @@ public class GpxSelectionHelper { if (dataItem.getColor() != 0) { gpx.setColor(dataItem.getColor()); } + if (dataItem.getGradientSpeedColor() != 0) { + gpx.setGradientScaleColor(GradientScaleType.SPEED, dataItem.getGradientSpeedColor()); + } + if (dataItem.getGradientAltitudeColor() != 0) { + gpx.setGradientScaleColor(GradientScaleType.ALTITUDE, dataItem.getGradientAltitudeColor()); + } + if (dataItem.getGradientSlopeColor() != 0) { + gpx.setGradientScaleColor(GradientScaleType.SLOPE, dataItem.getGradientSlopeColor()); + } + if (dataItem.getGradientScaleType() != null) { + gpx.setGradientScaleType(dataItem.getGradientScaleType()); + } + if (dataItem.getWidth() != null) { + gpx.setWidth(dataItem.getWidth()); + } + gpx.setShowArrows(dataItem.isShowArrows()); + gpx.setShowStartFinish(dataItem.isShowStartFinish()); sf.setJoinSegments(dataItem.isJoinSegments()); } sf.setGpxFile(gpx, app); @@ -1024,13 +1084,13 @@ public class GpxSelectionHelper { @Override protected void onProgressUpdate(Void... values) { - gpxTaskListener.gpxSelectionInProgress(); + gpxTaskListener.gpxSelectionInProgress(); } @Override protected void onPreExecute() { collectSelectedItems(); - gpxTaskListener.gpxSelectionStarted(); + gpxTaskListener.gpxSelectionStarted(); } private void collectSelectedItems() { diff --git a/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java b/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java index f6399cfa7d..726475cdc7 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/ConfigureMapMenu.java @@ -2,9 +2,7 @@ package net.osmand.plus.dialogs; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.os.Build; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -25,8 +23,6 @@ import androidx.appcompat.widget.SwitchCompat; import androidx.core.content.ContextCompat; import net.osmand.AndroidUtils; -import net.osmand.CallbackWithObject; -import net.osmand.GPXUtilities; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.core.android.MapRendererContext; @@ -35,20 +31,14 @@ import net.osmand.plus.ContextMenuAdapter.ItemClickListener; import net.osmand.plus.ContextMenuAdapter.OnRowItemClick; import net.osmand.plus.ContextMenuItem; import net.osmand.plus.DialogListItemAdapter; -import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.MapActivityLayers; -import net.osmand.plus.activities.PluginActivity; import net.osmand.plus.activities.SettingsActivity; -import net.osmand.plus.dashboard.DashboardOnMap; import net.osmand.plus.inapp.InAppPurchaseHelper; -import net.osmand.plus.poi.PoiFiltersHelper; import net.osmand.plus.poi.PoiUIFilter; -import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.render.RendererRegistry; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; @@ -57,8 +47,6 @@ import net.osmand.plus.srtmplugin.SRTMPlugin; import net.osmand.plus.transport.TransportLinesMenu; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.corenative.NativeCoreContext; -import net.osmand.plus.wikipedia.WikipediaPoiMenu; -import net.osmand.render.RenderingRule; import net.osmand.render.RenderingRuleProperty; import net.osmand.render.RenderingRuleStorageProperties; import net.osmand.render.RenderingRulesStorage; @@ -67,7 +55,6 @@ import net.osmand.util.SunriseSunset; import org.apache.commons.logging.Log; -import java.io.File; import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; @@ -101,7 +88,6 @@ import static net.osmand.aidlapi.OsmAndCustomizationConstants.ROUTES_ID; import static net.osmand.aidlapi.OsmAndCustomizationConstants.SHOW_CATEGORY_ID; import static net.osmand.aidlapi.OsmAndCustomizationConstants.TEXT_SIZE_ID; import static net.osmand.aidlapi.OsmAndCustomizationConstants.TRANSPORT_ID; -import static net.osmand.aidlapi.OsmAndCustomizationConstants.WIKIPEDIA_ID; import static net.osmand.plus.ContextMenuAdapter.makeDeleteAction; import static net.osmand.plus.srtmplugin.SRTMPlugin.CONTOUR_DENSITY_ATTR; import static net.osmand.plus.srtmplugin.SRTMPlugin.CONTOUR_LINES_ATTR; @@ -181,188 +167,12 @@ public class ConfigureMapMenu { return customRules; } - private final class LayerMenuListener extends OnRowItemClick { - private MapActivity ma; - private ContextMenuAdapter cm; - - private LayerMenuListener(MapActivity ma, ContextMenuAdapter cm) { - this.ma = ma; - this.cm = cm; - } - - private List getAlreadySelectedGpx() { - GpxSelectionHelper selectedGpxHelper = ma.getMyApplication().getSelectedGpxHelper(); - List selectedGpxFiles = selectedGpxHelper.getSelectedGPXFiles(); - - List files = new ArrayList<>(); - for (GpxSelectionHelper.SelectedGpxFile file : selectedGpxFiles) { - files.add(file.getGpxFile().path); - } - if (selectedGpxFiles.isEmpty()) { - Map fls = selectedGpxHelper.getSelectedGpxFilesBackUp(); - for(Map.Entry f : fls.entrySet()) { - if(!Algorithms.isEmpty(f.getKey().path)) { - File file = new File(f.getKey().path); - if(file.exists() && !file.isDirectory()) { - files.add(f.getKey().path); - } - } - } - } - - return files; - } - - @Override - public boolean onRowItemClick(final ArrayAdapter adapter, View view, int itemId, int pos) { - if (itemId == R.string.layer_poi) { - showPoiFilterDialog(adapter, adapter.getItem(pos)); - return false; - } else if (itemId == R.string.layer_gpx_layer && cm.getItem(pos).getSelected()) { - showGpxSelectionDialog(adapter, adapter.getItem(pos)); - return false; - } else if (itemId == R.string.rendering_category_transport) { - final ContextMenuItem item = adapter.getItem(pos); - TransportLinesMenu.showTransportsDialog(ma, new CallbackWithObject() { - @Override - public boolean processResult(Boolean result) { - if (item != null) { - item.setSelected(result); - item.setColorRes(result ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); - adapter.notifyDataSetChanged(); - } - return true; - } - }); - boolean selected = TransportLinesMenu.isShowLines(ma.getMyApplication()); - if (!selected && item != null) { - item.setSelected(true); - item.setColorRes(R.color.osmand_orange); - adapter.notifyDataSetChanged(); - } - return false; - } else { - CompoundButton btn = (CompoundButton) view.findViewById(R.id.toggle_item); - if (btn != null && btn.getVisibility() == View.VISIBLE) { - btn.setChecked(!btn.isChecked()); - cm.getItem(pos).setColorRes(btn.isChecked() ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); - adapter.notifyDataSetChanged(); - return false; - } else { - return onContextMenuClick(adapter, itemId, pos, false, null); - } - } - } - - @Override - public boolean onContextMenuClick(final ArrayAdapter adapter, int itemId, - final int pos, boolean isChecked, int[] viewCoordinates) { - final OsmandSettings settings = ma.getMyApplication().getSettings(); - final PoiFiltersHelper poiFiltersHelper = ma.getMyApplication().getPoiFilters(); - final ContextMenuItem item = cm.getItem(pos); - if (item.getSelected() != null) { - item.setColorRes(isChecked ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); - } - if (itemId == R.string.layer_poi) { - PoiUIFilter wiki = poiFiltersHelper.getTopWikiPoiFilter(); - poiFiltersHelper.clearSelectedPoiFilters(wiki); - if (isChecked) { - showPoiFilterDialog(adapter, adapter.getItem(pos)); - } else { - adapter.getItem(pos).setDescription( - poiFiltersHelper.getSelectedPoiFiltersName(wiki)); - } - } else if (itemId == R.string.layer_amenity_label) { - settings.SHOW_POI_LABEL.set(isChecked); - } else if (itemId == R.string.shared_string_favorites) { - settings.SHOW_FAVORITES.set(isChecked); - } else if (itemId == R.string.layer_gpx_layer) { - final GpxSelectionHelper selectedGpxHelper = ma.getMyApplication().getSelectedGpxHelper(); - if (selectedGpxHelper.isShowingAnyGpxFiles()) { - selectedGpxHelper.clearAllGpxFilesToShow(true); - adapter.getItem(pos).setDescription(selectedGpxHelper.getGpxDescription()); - } else { - showGpxSelectionDialog(adapter, adapter.getItem(pos)); - } - } else if (itemId == R.string.rendering_category_transport) { - boolean selected = TransportLinesMenu.isShowLines(ma.getMyApplication()); - TransportLinesMenu.toggleTransportLines(ma, !selected, new CallbackWithObject() { - @Override - public boolean processResult(Boolean result) { - item.setSelected(result); - item.setColorRes(result ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); - adapter.notifyDataSetChanged(); - return true; - } - }); - } else if (itemId == R.string.map_markers) { - settings.SHOW_MAP_MARKERS.set(isChecked); - } else if (itemId == R.string.layer_map) { - if (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) == null) { - Intent intent = new Intent(ma, PluginActivity.class); - intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, OsmandRasterMapsPlugin.ID); - ma.startActivity(intent); - } else { - ContextMenuItem it = adapter.getItem(pos); - ma.getMapLayers().selectMapLayer(ma.getMapView(), it, adapter); - } - } - adapter.notifyDataSetChanged(); - ma.getMapLayers().updateLayers(ma.getMapView()); - ma.getMapView().refreshMap(); - return false; - } - - private void showGpxSelectionDialog(final ArrayAdapter adapter, - final ContextMenuItem item) { - AlertDialog dialog = ma.getMapLayers().showGPXFileLayer(getAlreadySelectedGpx(), - ma.getMapView()); - dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - OsmandApplication app = ma.getMyApplication(); - boolean selected = app.getSelectedGpxHelper().isShowingAnyGpxFiles(); - item.setSelected(selected); - item.setDescription(app.getSelectedGpxHelper().getGpxDescription()); - item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); - adapter.notifyDataSetChanged(); - } - }); - } - - protected void showPoiFilterDialog(final ArrayAdapter adapter, - final ContextMenuItem item) { - final PoiFiltersHelper poiFiltersHelper = ma.getMyApplication().getPoiFilters(); - final PoiUIFilter wiki = poiFiltersHelper.getTopWikiPoiFilter(); - MapActivityLayers.DismissListener dismissListener = - new MapActivityLayers.DismissListener() { - @Override - public void dismiss() { - PoiFiltersHelper pf = ma.getMyApplication().getPoiFilters(); - boolean selected = pf.isShowingAnyPoi(wiki); - item.setSelected(selected); - item.setDescription(pf.getSelectedPoiFiltersName(wiki)); - item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); - adapter.notifyDataSetChanged(); - } - }; - if (poiFiltersHelper.isShowingAnyPoi(wiki)) { - ma.getMapLayers().showMultichoicePoiFilterDialog(ma.getMapView(), - dismissListener); - } else { - ma.getMapLayers().showSingleChoicePoiFilterDialog(ma.getMapView(), - dismissListener); - } - } - } - private void createLayersItems(List customRules, ContextMenuAdapter adapter, final MapActivity activity, final int themeRes, final boolean nightMode) { final OsmandApplication app = activity.getMyApplication(); final OsmandSettings settings = app.getSettings(); final int selectedProfileColorRes = settings.getApplicationMode().getIconColorInfo().getColor(nightMode); - final int selectedProfileColor = ContextCompat.getColor(app, selectedProfileColorRes); - LayerMenuListener l = new LayerMenuListener(activity, adapter); + MapLayerMenuListener l = new MapLayerMenuListener(activity, adapter); adapter.addItem(new ContextMenuItem.ItemBuilder() .setId(SHOW_CATEGORY_ID) .setTitleId(R.string.shared_string_show, activity) @@ -1299,230 +1109,35 @@ public class ConfigureMapMenu { } } - private class StringSpinnerArrayAdapter extends ArrayAdapter { + private static class StringSpinnerArrayAdapter extends ArrayAdapter { private boolean nightMode; public StringSpinnerArrayAdapter(Context context, boolean nightMode) { super(context, android.R.layout.simple_spinner_item); setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - OsmandApplication app = (OsmandApplication )getContext().getApplicationContext(); this.nightMode = nightMode; } - @Override - public View getView(int position, View convertView, ViewGroup parent) { - TextView label = (TextView) super.getView(position, convertView, parent); - - String text = getItem(position); - label.setText(text); - label.setTextColor(nightMode ? - ContextCompat.getColorStateList(getContext(), R.color.text_color_primary_dark) : ContextCompat.getColorStateList(getContext(), R.color.text_color_primary_light)); - return label; - } - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - TextView label = (TextView) super.getDropDownView(position, convertView, parent); - - String text = getItem(position); - label.setText(text); - label.setTextColor(nightMode ? - ContextCompat.getColorStateList(getContext(), R.color.text_color_primary_dark) : ContextCompat.getColorStateList(getContext(), R.color.text_color_primary_light)); - - return label; - } - } - - public static class GpxAppearanceAdapter extends ArrayAdapter { - - private OsmandApplication app; - private int currentColor; - private GpxAppearanceAdapterType adapterType = GpxAppearanceAdapterType.TRACK_WIDTH_COLOR; - - public enum GpxAppearanceAdapterType { - TRACK_WIDTH, - TRACK_COLOR, - TRACK_WIDTH_COLOR - } - - public GpxAppearanceAdapter(Context context, String currentColorValue, GpxAppearanceAdapterType adapterType) { - super(context, R.layout.rendering_prop_menu_item); - this.app = (OsmandApplication) getContext().getApplicationContext(); - this.adapterType = adapterType; - RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - this.currentColor = parseTrackColor(renderer, currentColorValue); - init(); - } - - public GpxAppearanceAdapter(Context context, int currentColor, GpxAppearanceAdapterType adapterType) { - super(context, R.layout.rendering_prop_menu_item); - this.app = (OsmandApplication) getContext().getApplicationContext(); - this.adapterType = adapterType; - this.currentColor = currentColor; - init(); - } - - public void init() { - RenderingRuleProperty trackWidthProp = null; - RenderingRuleProperty trackColorProp = null; - RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - if (renderer != null) { - if (adapterType == GpxAppearanceAdapterType.TRACK_WIDTH || adapterType == GpxAppearanceAdapterType.TRACK_WIDTH_COLOR) { - trackWidthProp = renderer.PROPS.getCustomRule(CURRENT_TRACK_WIDTH_ATTR); - } - if (adapterType == GpxAppearanceAdapterType.TRACK_COLOR || adapterType == GpxAppearanceAdapterType.TRACK_WIDTH_COLOR) { - trackColorProp = renderer.PROPS.getCustomRule(CURRENT_TRACK_COLOR_ATTR); - } - } - - if (trackWidthProp != null) { - AppearanceListItem item = new AppearanceListItem(CURRENT_TRACK_WIDTH_ATTR, "", - SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getDefaultValueDescription())); - add(item); - for (int j = 0; j < trackWidthProp.getPossibleValues().length; j++) { - item = new AppearanceListItem(CURRENT_TRACK_WIDTH_ATTR, - trackWidthProp.getPossibleValues()[j], - SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getPossibleValues()[j])); - add(item); - } - item.setLastItem(true); - } - if (trackColorProp != null) { - AppearanceListItem item = new AppearanceListItem(CURRENT_TRACK_COLOR_ATTR, "", - SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getDefaultValueDescription()), - parseTrackColor(renderer, "")); - add(item); - for (int j = 0; j < trackColorProp.getPossibleValues().length; j++) { - item = new AppearanceListItem(CURRENT_TRACK_COLOR_ATTR, - trackColorProp.getPossibleValues()[j], - SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getPossibleValues()[j]), - parseTrackColor(renderer, trackColorProp.getPossibleValues()[j])); - add(item); - } - item.setLastItem(true); - } - } - - public static int parseTrackColor(RenderingRulesStorage renderer, String colorName) { - int defaultColor = -1; - RenderingRule gpxRule = null; - if (renderer != null) { - gpxRule = renderer.getRenderingAttributeRule("gpx"); - } - if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) { - List rules = gpxRule.getIfElseChildren().get(0).getIfElseChildren(); - for (RenderingRule r : rules) { - String cName = r.getStringPropertyValue(CURRENT_TRACK_COLOR_ATTR); - if (!Algorithms.isEmpty(cName) && cName.equals(colorName)) { - return r.getIntPropertyValue(COLOR_ATTR); - } - if (cName == null && defaultColor == -1) { - defaultColor = r.getIntPropertyValue(COLOR_ATTR); - } - } - } - return defaultColor; - } - - public static String parseTrackColorName(RenderingRulesStorage renderer, int color) { - RenderingRule gpxRule = null; - if (renderer != null) { - gpxRule = renderer.getRenderingAttributeRule("gpx"); - } - if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) { - List rules = gpxRule.getIfElseChildren().get(0).getIfElseChildren(); - for (RenderingRule r : rules) { - String cName = r.getStringPropertyValue(CURRENT_TRACK_COLOR_ATTR); - if (!Algorithms.isEmpty(cName) && color == r.getIntPropertyValue(COLOR_ATTR)) { - return cName; - } - } - } - return Algorithms.colorToString(color); - } - @NonNull @Override public View getView(int position, View convertView, @NonNull ViewGroup parent) { - AppearanceListItem item = getItem(position); - View v = convertView; - if (v == null) { - v = LayoutInflater.from(getContext()).inflate(R.layout.rendering_prop_menu_item, null); - } - if (item != null) { - TextView textView = (TextView) v.findViewById(R.id.text1); - textView.setText(item.localizedValue); - if (item.attrName == CURRENT_TRACK_WIDTH_ATTR) { - int iconId; - if (item.value.equals("bold")) { - iconId = R.drawable.ic_action_gpx_width_bold; - } else if (item.value.equals("medium")) { - iconId = R.drawable.ic_action_gpx_width_medium; - } else { - iconId = R.drawable.ic_action_gpx_width_thin; - } - textView.setCompoundDrawablesWithIntrinsicBounds(null, null, - app.getUIUtilities().getPaintedIcon(iconId, currentColor), null); - } else { - if (item.color == -1) { - textView.setCompoundDrawablesWithIntrinsicBounds(null, null, - app.getUIUtilities().getThemedIcon(R.drawable.ic_action_circle), null); - } else { - textView.setCompoundDrawablesWithIntrinsicBounds(null, null, - app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, item.color), null); - } - } - textView.setCompoundDrawablePadding(AndroidUtils.dpToPx(getContext(), 10f)); - v.findViewById(R.id.divider).setVisibility(item.lastItem - && position < getCount() - 1 ? View.VISIBLE : View.GONE); - } - return v; - } - } - - public static class AppearanceListItem { - private String attrName; - private String value; - private String localizedValue; - private int color; - private boolean lastItem; - - public AppearanceListItem(String attrName, String value, String localizedValue) { - this.attrName = attrName; - this.value = value; - this.localizedValue = localizedValue; + TextView label = (TextView) super.getView(position, convertView, parent); + setupLabel(label, getItem(position)); + return label; } - public AppearanceListItem(String attrName, String value, String localizedValue, int color) { - this.attrName = attrName; - this.value = value; - this.localizedValue = localizedValue; - this.color = color; + @Override + public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) { + TextView label = (TextView) super.getDropDownView(position, convertView, parent); + setupLabel(label, getItem(position)); + return label; } - public String getAttrName() { - return attrName; - } - - public String getValue() { - return value; - } - - public String getLocalizedValue() { - return localizedValue; - } - - public int getColor() { - return color; - } - - public boolean isLastItem() { - return lastItem; - } - - public void setLastItem(boolean lastItem) { - this.lastItem = lastItem; + private void setupLabel(TextView label, String text) { + int colorId = nightMode ? R.color.text_color_primary_dark : R.color.text_color_primary_light; + label.setText(text); + label.setTextColor(ContextCompat.getColorStateList(getContext(), colorId)); } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/dialogs/GpxAppearanceAdapter.java b/OsmAnd/src/net/osmand/plus/dialogs/GpxAppearanceAdapter.java new file mode 100644 index 0000000000..048461da55 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/GpxAppearanceAdapter.java @@ -0,0 +1,214 @@ +package net.osmand.plus.dialogs; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import net.osmand.AndroidUtils; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.SettingsActivity; +import net.osmand.render.RenderingRule; +import net.osmand.render.RenderingRuleProperty; +import net.osmand.render.RenderingRulesStorage; +import net.osmand.util.Algorithms; + +import java.util.List; + +public class GpxAppearanceAdapter extends ArrayAdapter { + + private OsmandApplication app; + private GpxAppearanceAdapterType adapterType; + private int currentColor; + + public enum GpxAppearanceAdapterType { + TRACK_WIDTH, + TRACK_COLOR, + TRACK_WIDTH_COLOR + } + + public GpxAppearanceAdapter(Context context, String currentColorValue, GpxAppearanceAdapterType adapterType) { + super(context, R.layout.rendering_prop_menu_item); + this.app = (OsmandApplication) context.getApplicationContext(); + this.adapterType = adapterType; + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + this.currentColor = parseTrackColor(renderer, currentColorValue); + init(); + } + + public GpxAppearanceAdapter(Context context, int currentColor, GpxAppearanceAdapterType adapterType) { + super(context, R.layout.rendering_prop_menu_item); + this.app = (OsmandApplication) context.getApplicationContext(); + this.adapterType = adapterType; + this.currentColor = currentColor; + init(); + } + + @NonNull + @Override + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + AppearanceListItem item = getItem(position); + View v = convertView; + if (v == null) { + v = LayoutInflater.from(getContext()).inflate(R.layout.rendering_prop_menu_item, null); + } + if (item != null) { + TextView textView = (TextView) v.findViewById(R.id.text1); + textView.setText(item.localizedValue); + if (ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR.equals(item.attrName)) { + int iconId; + if ("bold".equals(item.value)) { + iconId = R.drawable.ic_action_gpx_width_bold; + } else if ("medium".equals(item.value)) { + iconId = R.drawable.ic_action_gpx_width_medium; + } else { + iconId = R.drawable.ic_action_gpx_width_thin; + } + textView.setCompoundDrawablesWithIntrinsicBounds(null, null, + app.getUIUtilities().getPaintedIcon(iconId, currentColor), null); + } else { + if (item.color == -1) { + textView.setCompoundDrawablesWithIntrinsicBounds(null, null, + app.getUIUtilities().getThemedIcon(R.drawable.ic_action_circle), null); + } else { + textView.setCompoundDrawablesWithIntrinsicBounds(null, null, + app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, item.color), null); + } + } + textView.setCompoundDrawablePadding(AndroidUtils.dpToPx(getContext(), 10f)); + v.findViewById(R.id.divider).setVisibility(item.lastItem + && position < getCount() - 1 ? View.VISIBLE : View.GONE); + } + return v; + } + + public void init() { + RenderingRuleProperty trackWidthProp = null; + RenderingRuleProperty trackColorProp = null; + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + if (renderer != null) { + if (adapterType == GpxAppearanceAdapterType.TRACK_WIDTH || adapterType == GpxAppearanceAdapterType.TRACK_WIDTH_COLOR) { + trackWidthProp = renderer.PROPS.getCustomRule(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR); + } + if (adapterType == GpxAppearanceAdapterType.TRACK_COLOR || adapterType == GpxAppearanceAdapterType.TRACK_WIDTH_COLOR) { + trackColorProp = renderer.PROPS.getCustomRule(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR); + } + } + + if (trackWidthProp != null) { + AppearanceListItem item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR, "", + SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getDefaultValueDescription())); + add(item); + for (int j = 0; j < trackWidthProp.getPossibleValues().length; j++) { + item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR, + trackWidthProp.getPossibleValues()[j], + SettingsActivity.getStringPropertyValue(getContext(), trackWidthProp.getPossibleValues()[j])); + add(item); + } + item.setLastItem(true); + } + if (trackColorProp != null) { + AppearanceListItem item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR, "", + SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getDefaultValueDescription()), + parseTrackColor(renderer, "")); + add(item); + for (int j = 0; j < trackColorProp.getPossibleValues().length; j++) { + item = new AppearanceListItem(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR, + trackColorProp.getPossibleValues()[j], + SettingsActivity.getStringPropertyValue(getContext(), trackColorProp.getPossibleValues()[j]), + parseTrackColor(renderer, trackColorProp.getPossibleValues()[j])); + add(item); + } + item.setLastItem(true); + } + } + + public static int parseTrackColor(RenderingRulesStorage renderer, String colorName) { + int defaultColor = -1; + RenderingRule gpxRule = null; + if (renderer != null) { + gpxRule = renderer.getRenderingAttributeRule("gpx"); + } + if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) { + List rules = gpxRule.getIfElseChildren().get(0).getIfElseChildren(); + for (RenderingRule r : rules) { + String cName = r.getStringPropertyValue(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR); + if (!Algorithms.isEmpty(cName) && cName.equals(colorName)) { + return r.getIntPropertyValue(ConfigureMapMenu.COLOR_ATTR); + } + if (cName == null && defaultColor == -1) { + defaultColor = r.getIntPropertyValue(ConfigureMapMenu.COLOR_ATTR); + } + } + } + return defaultColor; + } + + public static String parseTrackColorName(RenderingRulesStorage renderer, int color) { + RenderingRule gpxRule = null; + if (renderer != null) { + gpxRule = renderer.getRenderingAttributeRule("gpx"); + } + if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) { + List rules = gpxRule.getIfElseChildren().get(0).getIfElseChildren(); + for (RenderingRule r : rules) { + String cName = r.getStringPropertyValue(ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR); + if (!Algorithms.isEmpty(cName) && color == r.getIntPropertyValue(ConfigureMapMenu.COLOR_ATTR)) { + return cName; + } + } + } + return Algorithms.colorToString(color); + } + + public static class AppearanceListItem { + + private String attrName; + private String value; + private String localizedValue; + private int color; + private boolean lastItem; + + public AppearanceListItem(String attrName, String value, String localizedValue) { + this.attrName = attrName; + this.value = value; + this.localizedValue = localizedValue; + } + + public AppearanceListItem(String attrName, String value, String localizedValue, int color) { + this.attrName = attrName; + this.value = value; + this.localizedValue = localizedValue; + this.color = color; + } + + public String getAttrName() { + return attrName; + } + + public String getValue() { + return value; + } + + public String getLocalizedValue() { + return localizedValue; + } + + public int getColor() { + return color; + } + + public boolean isLastItem() { + return lastItem; + } + + public void setLastItem(boolean lastItem) { + this.lastItem = lastItem; + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/dialogs/MapLayerMenuListener.java b/OsmAnd/src/net/osmand/plus/dialogs/MapLayerMenuListener.java new file mode 100644 index 0000000000..91e55e1d73 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/MapLayerMenuListener.java @@ -0,0 +1,210 @@ +package net.osmand.plus.dialogs; + +import android.content.DialogInterface; +import android.content.Intent; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.CompoundButton; + +import androidx.appcompat.app.AlertDialog; + +import net.osmand.CallbackWithObject; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.plus.ContextMenuAdapter; +import net.osmand.plus.ContextMenuAdapter.OnRowItemClick; +import net.osmand.plus.ContextMenuItem; +import net.osmand.plus.GpxSelectionHelper; +import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.MapActivityLayers; +import net.osmand.plus.activities.PluginActivity; +import net.osmand.plus.poi.PoiFiltersHelper; +import net.osmand.plus.poi.PoiUIFilter; +import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.transport.TransportLinesMenu; +import net.osmand.util.Algorithms; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +final class MapLayerMenuListener extends OnRowItemClick { + + private MapActivity mapActivity; + private ContextMenuAdapter menuAdapter; + + MapLayerMenuListener(MapActivity mapActivity, ContextMenuAdapter menuAdapter) { + this.mapActivity = mapActivity; + this.menuAdapter = menuAdapter; + } + + private List getAlreadySelectedGpx() { + GpxSelectionHelper selectedGpxHelper = mapActivity.getMyApplication().getSelectedGpxHelper(); + List selectedGpxFiles = selectedGpxHelper.getSelectedGPXFiles(); + + List files = new ArrayList<>(); + for (SelectedGpxFile file : selectedGpxFiles) { + files.add(file.getGpxFile().path); + } + if (selectedGpxFiles.isEmpty()) { + Map fls = selectedGpxHelper.getSelectedGpxFilesBackUp(); + for (Map.Entry f : fls.entrySet()) { + if (!Algorithms.isEmpty(f.getKey().path)) { + File file = new File(f.getKey().path); + if (file.exists() && !file.isDirectory()) { + files.add(f.getKey().path); + } + } + } + } + + return files; + } + + @Override + public boolean onRowItemClick(final ArrayAdapter adapter, View view, int itemId, int pos) { + if (itemId == R.string.layer_poi) { + showPoiFilterDialog(adapter, adapter.getItem(pos)); + return false; + } else if (itemId == R.string.layer_gpx_layer && menuAdapter.getItem(pos).getSelected()) { + showGpxSelectionDialog(adapter, adapter.getItem(pos)); + return false; + } else if (itemId == R.string.rendering_category_transport) { + final ContextMenuItem item = adapter.getItem(pos); + TransportLinesMenu.showTransportsDialog(mapActivity, new CallbackWithObject() { + @Override + public boolean processResult(Boolean result) { + if (item != null) { + item.setSelected(result); + item.setColorRes(result ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); + adapter.notifyDataSetChanged(); + } + return true; + } + }); + boolean selected = TransportLinesMenu.isShowLines(mapActivity.getMyApplication()); + if (!selected && item != null) { + item.setSelected(true); + item.setColorRes(R.color.osmand_orange); + adapter.notifyDataSetChanged(); + } + return false; + } else { + CompoundButton btn = (CompoundButton) view.findViewById(R.id.toggle_item); + if (btn != null && btn.getVisibility() == View.VISIBLE) { + btn.setChecked(!btn.isChecked()); + menuAdapter.getItem(pos).setColorRes(btn.isChecked() ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); + adapter.notifyDataSetChanged(); + return false; + } else { + return onContextMenuClick(adapter, itemId, pos, false, null); + } + } + } + + @Override + public boolean onContextMenuClick(final ArrayAdapter adapter, int itemId, + final int pos, boolean isChecked, int[] viewCoordinates) { + final OsmandSettings settings = mapActivity.getMyApplication().getSettings(); + final PoiFiltersHelper poiFiltersHelper = mapActivity.getMyApplication().getPoiFilters(); + final ContextMenuItem item = menuAdapter.getItem(pos); + if (item.getSelected() != null) { + item.setColorRes(isChecked ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); + } + if (itemId == R.string.layer_poi) { + PoiUIFilter wiki = poiFiltersHelper.getTopWikiPoiFilter(); + poiFiltersHelper.clearSelectedPoiFilters(wiki); + if (isChecked) { + showPoiFilterDialog(adapter, adapter.getItem(pos)); + } else { + adapter.getItem(pos).setDescription( + poiFiltersHelper.getSelectedPoiFiltersName(wiki)); + } + } else if (itemId == R.string.layer_amenity_label) { + settings.SHOW_POI_LABEL.set(isChecked); + } else if (itemId == R.string.shared_string_favorites) { + settings.SHOW_FAVORITES.set(isChecked); + } else if (itemId == R.string.layer_gpx_layer) { + final GpxSelectionHelper selectedGpxHelper = mapActivity.getMyApplication().getSelectedGpxHelper(); + if (selectedGpxHelper.isShowingAnyGpxFiles()) { + selectedGpxHelper.clearAllGpxFilesToShow(true); + adapter.getItem(pos).setDescription(selectedGpxHelper.getGpxDescription()); + } else { + showGpxSelectionDialog(adapter, adapter.getItem(pos)); + } + } else if (itemId == R.string.rendering_category_transport) { + boolean selected = TransportLinesMenu.isShowLines(mapActivity.getMyApplication()); + TransportLinesMenu.toggleTransportLines(mapActivity, !selected, new CallbackWithObject() { + @Override + public boolean processResult(Boolean result) { + item.setSelected(result); + item.setColorRes(result ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); + adapter.notifyDataSetChanged(); + return true; + } + }); + } else if (itemId == R.string.map_markers) { + settings.SHOW_MAP_MARKERS.set(isChecked); + } else if (itemId == R.string.layer_map) { + if (OsmandPlugin.getEnabledPlugin(OsmandRasterMapsPlugin.class) == null) { + Intent intent = new Intent(mapActivity, PluginActivity.class); + intent.putExtra(PluginActivity.EXTRA_PLUGIN_ID, OsmandRasterMapsPlugin.ID); + mapActivity.startActivity(intent); + } else { + ContextMenuItem it = adapter.getItem(pos); + mapActivity.getMapLayers().selectMapLayer(mapActivity.getMapView(), it, adapter); + } + } + adapter.notifyDataSetChanged(); + mapActivity.getMapLayers().updateLayers(mapActivity.getMapView()); + mapActivity.getMapView().refreshMap(); + return false; + } + + private void showGpxSelectionDialog(final ArrayAdapter adapter, + final ContextMenuItem item) { + AlertDialog dialog = mapActivity.getMapLayers().showGPXFileLayer(getAlreadySelectedGpx(), + mapActivity.getMapView()); + dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + OsmandApplication app = mapActivity.getMyApplication(); + boolean selected = app.getSelectedGpxHelper().isShowingAnyGpxFiles(); + item.setSelected(selected); + item.setDescription(app.getSelectedGpxHelper().getGpxDescription()); + item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); + adapter.notifyDataSetChanged(); + } + }); + } + + protected void showPoiFilterDialog(final ArrayAdapter adapter, + final ContextMenuItem item) { + final PoiFiltersHelper poiFiltersHelper = mapActivity.getMyApplication().getPoiFilters(); + final PoiUIFilter wiki = poiFiltersHelper.getTopWikiPoiFilter(); + MapActivityLayers.DismissListener dismissListener = + new MapActivityLayers.DismissListener() { + @Override + public void dismiss() { + PoiFiltersHelper pf = mapActivity.getMyApplication().getPoiFilters(); + boolean selected = pf.isShowingAnyPoi(wiki); + item.setSelected(selected); + item.setDescription(pf.getSelectedPoiFiltersName(wiki)); + item.setColorRes(selected ? R.color.osmand_orange : ContextMenuItem.INVALID_ID); + adapter.notifyDataSetChanged(); + } + }; + if (poiFiltersHelper.isShowingAnyPoi(wiki)) { + mapActivity.getMapLayers().showMultichoicePoiFilterDialog(mapActivity.getMapView(), + dismissListener); + } else { + mapActivity.getMapLayers().showSingleChoicePoiFilterDialog(mapActivity.getMapView(), + dismissListener); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 356f8c9870..c3dc6c2ae6 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -80,7 +80,6 @@ import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.Version; @@ -90,10 +89,11 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.PluginActivity; import net.osmand.plus.activities.SettingsActivity; import net.osmand.plus.dialogs.ConfigureMapMenu; -import net.osmand.plus.dialogs.ConfigureMapMenu.AppearanceListItem; -import net.osmand.plus.dialogs.ConfigureMapMenu.GpxAppearanceAdapter; +import net.osmand.plus.dialogs.GpxAppearanceAdapter; +import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.routing.RouteCalculationResult; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.render.RenderingRuleProperty; import net.osmand.render.RenderingRulesStorage; import net.osmand.router.RouteStatisticsHelper; @@ -540,9 +540,9 @@ public class GpxUiHelper { public void onItemClick(AdapterView parent, View view, int position, long id) { AppearanceListItem item = gpxApprAdapter.getItem(position); if (item != null) { - if (item.getAttrName() == CURRENT_TRACK_WIDTH_ATTR) { + if (CURRENT_TRACK_WIDTH_ATTR.equals(item.getAttrName())) { gpxAppearanceParams.put(CURRENT_TRACK_WIDTH_ATTR, item.getValue()); - } else if (item.getAttrName() == CURRENT_TRACK_COLOR_ATTR) { + } else if (CURRENT_TRACK_COLOR_ATTR.equals(item.getAttrName())) { gpxAppearanceParams.put(CURRENT_TRACK_COLOR_ATTR, item.getValue()); } } @@ -592,7 +592,7 @@ public class GpxUiHelper { } dialog.dismiss(); loadGPXFileInDifferentThread(activity, callbackWithObject, dir, currentGPX, - s.toArray(new String[s.size()])); + s.toArray(new String[0])); } }); builder.setNegativeButton(R.string.shared_string_cancel, null); diff --git a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java index fe33fa61d4..36d5b9ab92 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/ImportHelper.java @@ -32,7 +32,7 @@ import net.osmand.data.FavouritePoint.BackgroundType; import net.osmand.plus.AppInitializer; import net.osmand.plus.CustomOsmandPlugin; import net.osmand.plus.FavouritesDbHelper; -import net.osmand.plus.GPXDatabase; +import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; @@ -1017,10 +1017,10 @@ public class ImportHelper { gpxFile.path = toWrite.getAbsolutePath(); File file = new File(gpxFile.path); if (!destinationExists) { - GPXDatabase.GpxDataItem item = new GPXDatabase.GpxDataItem(file, gpxFile.getColor(0)); + GpxDataItem item = new GpxDataItem(file, gpxFile); app.getGpxDbHelper().add(item); } else { - GPXDatabase.GpxDataItem item = app.getGpxDbHelper().getItem(file); + GpxDataItem item = app.getGpxDbHelper().getItem(file); if (item != null) { app.getGpxDbHelper().clearAnalysis(item); } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/FavoritePointEditorFragmentNew.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/FavoritePointEditorFragmentNew.java index 2362252307..b3159922cf 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/FavoritePointEditorFragmentNew.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/FavoritePointEditorFragmentNew.java @@ -97,7 +97,7 @@ public class FavoritePointEditorFragmentNew extends PointEditorFragmentNew { } }); if (editor != null && editor.isNew()) { - ImageView toolbarAction = (ImageView) view.findViewById(R.id.toolbar_action); + ImageView toolbarAction = view.findViewById(R.id.toolbar_action); toolbarAction.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -460,30 +460,36 @@ public class FavoritePointEditorFragmentNew extends PointEditorFragmentNew { @Override public Set getCategories() { Set categories = new LinkedHashSet<>(); + Set categoriesHidden = new LinkedHashSet<>(); FavouritesDbHelper helper = getHelper(); if (helper != null && editor != null) { OsmandApplication app = getMyApplication(); - if (editor.isNew()) { - FavoriteGroup lastUsedGroup = helper.getGroup(getLastUsedGroup()); - if (lastUsedGroup != null && lastUsedGroup.isVisible()) { - categories.add(lastUsedGroup.getDisplayName(app)); - } - for (FavouritesDbHelper.FavoriteGroup fg : getHelper().getFavoriteGroups()) { - if (!fg.equals(lastUsedGroup) && fg.isVisible()) { - categories.add(fg.getDisplayName(app)); - } - } - } else { - for (FavoriteGroup fg : helper.getFavoriteGroups()) { + FavoriteGroup lastUsedGroup = helper.getGroup(getLastUsedGroup()); + if (lastUsedGroup != null) { + categories.add(lastUsedGroup.getDisplayName(app)); + } + for (FavouritesDbHelper.FavoriteGroup fg : helper.getFavoriteGroups()) { + if (!fg.equals(lastUsedGroup)) { if (fg.isVisible()) { categories.add(fg.getDisplayName(app)); + } else { + categoriesHidden.add(fg.getDisplayName(app)); } } } + categories.addAll(categoriesHidden); } return categories; } + @Override + public boolean isCategoryVisible(String name) { + if (getHelper() != null) { + return getHelper().isGroupVisible(name); + } + return true; + } + @Override public int getCategoryPointsCount(String category) { FavouritesDbHelper helper = getHelper(); @@ -498,6 +504,7 @@ public class FavoritePointEditorFragmentNew extends PointEditorFragmentNew { } @Override + @ColorInt public int getCategoryColor(String category) { FavouritesDbHelper helper = getHelper(); if (helper != null) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java index 70697426ed..68ada0922b 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/PointEditorFragmentNew.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.graphics.Rect; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; @@ -675,6 +676,7 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment { public void setCategory(String name, int color) { setSelectedItemWithScroll(name); + updateColorSelector(color, groupRecyclerView.getRootView()); } private void setSelectedItemWithScroll(String name) { @@ -732,6 +734,7 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment { public abstract String getToolbarTitle(); + @ColorInt public abstract int getCategoryColor(String category); public abstract int getCategoryPointsCount(String category); @@ -762,6 +765,12 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment { public abstract Set getCategories(); + protected boolean isCategoryVisible(String name) { + return true; + } + + ; + String getNameTextValue() { EditText nameEdit = view.findViewById(R.id.name_edit); return nameEdit.getText().toString().trim(); @@ -885,16 +894,13 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment { public void onClick(View view) { int previousSelectedPosition = getItemPosition(selectedItemName); selectedItemName = items.get(holder.getAdapterPosition()); + updateColorSelector(getCategoryColor(selectedItemName), groupRecyclerView.getRootView()); notifyItemChanged(holder.getAdapterPosition()); notifyItemChanged(previousSelectedPosition); } }); final String group = items.get(position); holder.groupName.setText(group); - int categoryColor = getCategoryColor(group); - int color = categoryColor == 0 ? getDefaultColor() : categoryColor; - holder.groupIcon.setImageDrawable(UiUtilities.tintDrawable( - AppCompatResources.getDrawable(app, R.drawable.ic_action_folder), color)); holder.pointsCounter.setText(String.valueOf(getCategoryPointsCount(group))); int strokeColor; int strokeWidth; @@ -913,6 +919,20 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment { rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, strokeWidth), strokeColor); holder.groupButton.setImageDrawable(rectContourDrawable); } + int color; + int iconID; + if (!isCategoryVisible(group)) { + color = ContextCompat.getColor(app, R.color.text_color_secondary_light); + iconID = R.drawable.ic_action_hide; + holder.groupName.setTypeface(null, Typeface.ITALIC); + } else { + int categoryColor = getCategoryColor(group); + color = categoryColor == 0 ? getDefaultColor() : categoryColor; + iconID = R.drawable.ic_action_folder; + holder.groupName.setTypeface(null, Typeface.NORMAL); + } + holder.groupIcon.setImageDrawable(UiUtilities.tintDrawable( + AppCompatResources.getDrawable(app, iconID), color)); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { AndroidUtils.setBackground(app, holder.groupButton, nightMode, R.drawable.ripple_solid_light_6dp, diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java index e74539a06a..94ecff5478 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/editors/WptPtEditorFragmentNew.java @@ -8,6 +8,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.view.View; +import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; @@ -454,6 +455,7 @@ public class WptPtEditorFragmentNew extends PointEditorFragmentNew { } @Override + @ColorInt public int getCategoryColor(String category) { if (categoriesMap != null) { Integer color = categoriesMap.get(category); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java index fdc58e7831..586a301d45 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/other/TrackDetailsMenu.java @@ -46,6 +46,7 @@ import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.views.GPXLayer; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; +import net.osmand.util.MapUtils; import java.util.ArrayList; import java.util.Collections; @@ -312,18 +313,15 @@ public class TrackDetailsMenu { } } else { float distance = pos * dataSet.getDivX(); - double previousSplitDistance = 0; + double totalDistance = 0; WptPt previousPoint = null; for (int i = 0; i < segment.points.size(); i++) { WptPt currentPoint = segment.points.get(i); if (previousPoint != null) { - if (currentPoint.distance < previousPoint.distance) { - previousSplitDistance += previousPoint.distance; - } + totalDistance += MapUtils.getDistance(previousPoint.lat, previousPoint.lon, currentPoint.lat, currentPoint.lon); } - double totalDistance = previousSplitDistance + currentPoint.distance; - if (totalDistance >= distance) { - if (previousPoint != null) { + if (currentPoint.distance >= distance || Math.abs(totalDistance - distance) < 0.1) { + if (previousPoint != null && currentPoint.distance >= distance) { double percent = 1 - (totalDistance - distance) / (currentPoint.distance - previousPoint.distance); double dLat = (currentPoint.lat - previousPoint.lat) * percent; double dLon = (currentPoint.lon - previousPoint.lon) * percent; @@ -500,6 +498,9 @@ public class TrackDetailsMenu { } else { mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints); } + if (location != null) { + mapActivity.refreshMap(); + } fitTrackOnMap(chart, location, forceFit); } diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java index 25d9d7450a..260d7fccda 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java @@ -1,5 +1,6 @@ package net.osmand.plus.myplaces; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; @@ -14,8 +15,10 @@ import android.view.LayoutInflater; import android.view.View; import android.widget.AbsListView; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ImageView; +import android.widget.ListAdapter; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; @@ -36,12 +39,12 @@ import com.squareup.picasso.RequestCreator; import net.osmand.AndroidUtils; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.GPXFile.GpxSplitType; import net.osmand.GPXUtilities.WptPt; import net.osmand.PicassoUtils; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; -import net.osmand.plus.GPXDatabase; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; @@ -49,13 +52,16 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.TrackActivity; -import net.osmand.plus.dialogs.ConfigureMapMenu; +import net.osmand.plus.dialogs.GpxAppearanceAdapter; +import net.osmand.plus.dialogs.GpxAppearanceAdapter.AppearanceListItem; +import net.osmand.plus.dialogs.GpxAppearanceAdapter.GpxAppearanceAdapterType; import net.osmand.plus.measurementtool.NewGpxData; import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.plus.widgets.tools.CropCircleTransformation; import net.osmand.plus.wikipedia.WikiArticleHelper; import net.osmand.plus.wikivoyage.WikivoyageUtils; @@ -71,6 +77,7 @@ import java.util.Map; import gnu.trove.list.array.TIntArrayList; import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR; +import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR; public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { @@ -356,50 +363,27 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { @Override public void onClick(View v) { TrackActivity activity = getTrackActivity(); - if (activity != null) { - colorListPopupWindow = new ListPopupWindow(activity); - colorListPopupWindow.setAnchorView(colorView); - colorListPopupWindow.setContentWidth(AndroidUtils.dpToPx(app, 200f)); - colorListPopupWindow.setModal(true); - colorListPopupWindow.setDropDownGravity(Gravity.RIGHT | Gravity.TOP); - colorListPopupWindow.setVerticalOffset(AndroidUtils.dpToPx(app, -48f)); - colorListPopupWindow.setHorizontalOffset(AndroidUtils.dpToPx(app, -6f)); - GPXFile gpxFile = getGpx(); - final ConfigureMapMenu.GpxAppearanceAdapter gpxApprAdapter = new ConfigureMapMenu.GpxAppearanceAdapter(activity, - gpxFile.getColor(0), ConfigureMapMenu.GpxAppearanceAdapter.GpxAppearanceAdapterType.TRACK_COLOR); - colorListPopupWindow.setAdapter(gpxApprAdapter); - colorListPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() { + final GPXFile gpxFile = getGpx(); + if (activity != null && gpxFile != null) { + final GpxAppearanceAdapter appearanceAdapter = new GpxAppearanceAdapter(activity, + gpxFile.getColor(0), GpxAppearanceAdapterType.TRACK_WIDTH_COLOR); + OnItemClickListener itemClickListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - ConfigureMapMenu.AppearanceListItem item = gpxApprAdapter.getItem(position); + AppearanceListItem item = appearanceAdapter.getItem(position); if (item != null) { if (CURRENT_TRACK_COLOR_ATTR.equals(item.getAttrName())) { - GPXFile gpx = getGpx(); - int clr = item.getColor(); - if (vis.isChecked()) { - if (gpx != null) { - SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpx, vis.isChecked(), false); - if (clr != 0 && sf.getModifiableGpxFile() != null) { - sf.getModifiableGpxFile().setColor(clr); - if (getGpxDataItem() != null) { - app.getGpxDbHelper().updateColor(getGpxDataItem(), clr); - } - } - } - } else if (getGpxDataItem() != null) { - app.getGpxDbHelper().updateColor(getGpxDataItem(), clr); - } - if (gpx != null && gpx.showCurrentTrack) { - app.getSettings().CURRENT_TRACK_COLOR.set(clr); - } - refreshTrackBitmap(); + setGpxColor(item, gpxFile); + } else if (CURRENT_TRACK_WIDTH_ATTR.equals(item.getAttrName())) { + setGpxWidth(item, gpxFile); } } colorListPopupWindow.dismiss(); updateColorView(colorView); } - }); + }; + colorListPopupWindow = createPopupWindow(activity, splitIntervalView, appearanceAdapter, itemClickListener); colorListPopupWindow.show(); } } @@ -415,16 +399,8 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { public void onClick(View v) { TrackActivity activity = getTrackActivity(); if (activity != null) { - splitListPopupWindow = new ListPopupWindow(activity); - splitListPopupWindow.setAnchorView(splitIntervalView); - splitListPopupWindow.setContentWidth(AndroidUtils.dpToPx(app, 200f)); - splitListPopupWindow.setModal(true); - splitListPopupWindow.setDropDownGravity(Gravity.RIGHT | Gravity.TOP); - splitListPopupWindow.setVerticalOffset(AndroidUtils.dpToPx(app, -48f)); - splitListPopupWindow.setHorizontalOffset(AndroidUtils.dpToPx(app, -6f)); - splitListPopupWindow.setAdapter(new ArrayAdapter<>(activity, - R.layout.popup_list_text_item, options)); - splitListPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() { + ListAdapter adapter = new ArrayAdapter<>(activity, R.layout.popup_list_text_item, options); + OnItemClickListener itemClickListener = new OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { @@ -433,7 +409,8 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { splitListPopupWindow.dismiss(); updateSplitIntervalView(splitIntervalView); } - }); + }; + splitListPopupWindow = createPopupWindow(activity, splitIntervalView, adapter, itemClickListener); splitListPopupWindow.show(); } } @@ -451,6 +428,55 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { } } + private void setGpxColor(AppearanceListItem item, GPXFile gpxFile) { + int color = item.getColor(); + if (vis.isChecked()) { + SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpxFile, vis.isChecked(), false); + if (color != 0 && sf.getModifiableGpxFile() != null) { + sf.getModifiableGpxFile().setColor(color); + if (getGpxDataItem() != null) { + app.getGpxDbHelper().updateColor(getGpxDataItem(), color); + } + } + } else if (getGpxDataItem() != null) { + app.getGpxDbHelper().updateColor(getGpxDataItem(), color); + } + if (gpxFile.showCurrentTrack) { + app.getSettings().CURRENT_TRACK_COLOR.set(color); + } + refreshTrackBitmap(); + } + + private void setGpxWidth(AppearanceListItem item, GPXFile gpxFile) { + String width = item.getValue(); + if (vis.isChecked()) { + SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpxFile, vis.isChecked(), false); + if (width != null && sf.getModifiableGpxFile() != null) { + sf.getModifiableGpxFile().setWidth(width); + if (getGpxDataItem() != null) { + app.getGpxDbHelper().updateWidth(getGpxDataItem(), width); + } + } + } else if (getGpxDataItem() != null) { + app.getGpxDbHelper().updateWidth(getGpxDataItem(), width); + } + refreshTrackBitmap(); + } + + private ListPopupWindow createPopupWindow(Activity activity, View anchorView, ListAdapter adapter, OnItemClickListener itemClickListener) { + ListPopupWindow popupWindow = new ListPopupWindow(activity); + popupWindow.setAnchorView(anchorView); + popupWindow.setContentWidth(AndroidUtils.dpToPx(app, 200f)); + popupWindow.setModal(true); + popupWindow.setDropDownGravity(Gravity.RIGHT | Gravity.TOP); + popupWindow.setVerticalOffset(AndroidUtils.dpToPx(app, -48f)); + popupWindow.setHorizontalOffset(AndroidUtils.dpToPx(app, -6f)); + popupWindow.setAdapter(adapter); + popupWindow.setOnItemClickListener(itemClickListener); + + return popupWindow; + } + @Nullable private View getDescriptionCardView(Context context) { GPXFile gpx = getGpx(); @@ -729,7 +755,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { text.setText(options.get(selectedSplitInterval)); } } - + private int getSelectedSplitInterval() { if (getGpxDataItem() == null) { return 0; @@ -737,14 +763,14 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { int splitType = getGpxDataItem().getSplitType(); double splitInterval = getGpxDataItem().getSplitInterval(); int position = 0; - - if (splitType == GPXDatabase.GPX_SPLIT_TYPE_DISTANCE) { + + if (splitType == GpxSplitType.DISTANCE.getType()) { position = distanceSplit.indexOf(splitInterval); - } else if (splitType == GPXDatabase.GPX_SPLIT_TYPE_TIME) { + } else if (splitType == GpxSplitType.TIME.getType()) { position = timeSplit.indexOf((int) splitInterval); } - - return position > 0 ? position : 0; + + return Math.max(position, 0); } private void updateColorView(View colorView) { @@ -759,10 +785,9 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { } } if (color == 0) { - final RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); - final OsmandSettings.CommonPreference prefColor - = app.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR); - color = ConfigureMapMenu.GpxAppearanceAdapter.parseTrackColor(renderer, prefColor.get()); + RenderingRulesStorage renderer = app.getRendererRegistry().getCurrentSelectedRenderer(); + CommonPreference prefColor = app.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR); + color = GpxAppearanceAdapter.parseTrackColor(renderer, prefColor.get()); } if (color == 0) { colorImageView.setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_circle)); @@ -852,20 +877,20 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { } private void updateSplitInDatabase() { - int splitType = 0; double splitInterval = 0; + GpxSplitType splitType = null; if (selectedSplitInterval == 0) { - splitType = GPXDatabase.GPX_SPLIT_TYPE_NO_SPLIT; + splitType = GpxSplitType.NO_SPLIT; splitInterval = 0; } else if (distanceSplit.get(selectedSplitInterval) > 0) { - splitType = GPXDatabase.GPX_SPLIT_TYPE_DISTANCE; + splitType = GpxSplitType.DISTANCE; splitInterval = distanceSplit.get(selectedSplitInterval); } else if (timeSplit.get(selectedSplitInterval) > 0) { - splitType = GPXDatabase.GPX_SPLIT_TYPE_TIME; + splitType = GpxSplitType.TIME; splitInterval = timeSplit.get(selectedSplitInterval); } GpxDataItem item = getGpxDataItem(); - if (item != null) { + if (item != null && splitType != null) { app.getGpxDbHelper().updateSplit(item, splitType, splitInterval); } } diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java index 8207d401ff..41343f0fa3 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackSegmentFragment.java @@ -57,7 +57,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; @@ -70,12 +69,14 @@ import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; import net.osmand.plus.measurementtool.NewGpxData; import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.views.controls.PagerSlidingTabStrip; import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider; import net.osmand.plus.views.controls.WrapContentHeightViewPager; import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface; import net.osmand.plus.widgets.IconPopupMenu; import net.osmand.util.Algorithms; +import net.osmand.util.MapUtils; import java.io.File; import java.lang.ref.WeakReference; @@ -525,16 +526,14 @@ public class TrackSegmentFragment extends OsmAndListFragment implements TrackBit } } else { float distance = pos * dataSet.getDivX(); - double previousSplitDistance = 0; + double totalDistance = 0; for (int i = 0; i < segment.points.size(); i++) { WptPt currentPoint = segment.points.get(i); if (i != 0) { WptPt previousPoint = segment.points.get(i - 1); - if (currentPoint.distance < previousPoint.distance) { - previousSplitDistance += previousPoint.distance; - } + totalDistance += MapUtils.getDistance(previousPoint.lat, previousPoint.lon, currentPoint.lat, currentPoint.lon); } - if (previousSplitDistance + currentPoint.distance >= distance) { + if (currentPoint.distance >= distance || Math.abs(totalDistance - distance) < 0.1) { wpt = currentPoint; break; } diff --git a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java index 4b1471a396..6629228696 100644 --- a/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java +++ b/OsmAnd/src/net/osmand/plus/poi/PoiUIFilter.java @@ -682,7 +682,8 @@ public class PoiUIFilter implements SearchPoiTypeFilter, Comparable if (subtype != null) { PoiCategory c = subtype.getCategory(); String typeName = subtype.getKeyName(); - if (!getAcceptedSubtypes(c).contains(typeName)) { + Set acceptedSubtypes = getAcceptedSubtypes(c); + if (acceptedSubtypes != null && !acceptedSubtypes.contains(typeName)) { LinkedHashSet typeNames = acceptedTypesOrigin.get(c); if (typeNames == null) { typeNames = new LinkedHashSet<>(); diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java index 46ceaf70ea..e70752b7f1 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java @@ -140,9 +140,13 @@ public class RouteCalculationResult { OsmandApplication ctx, boolean leftSide, RoutingContext rctx, List waypoints, ApplicationMode mode) { if (rctx != null) { this.routingTime = rctx.routingTime; - this.visitedSegments = rctx.visitedSegments; - this.loadedTiles = rctx.loadedTiles; - this.calculateTime = (float) (((System.nanoTime() - rctx.timeToCalculate) / 1e6) / 1000f); + this.visitedSegments = rctx.getVisitedSegments(); + this.loadedTiles = rctx.getLoadedTiles(); + if (rctx.calculationProgress != null) { + this.calculateTime = (float) (rctx.calculationProgress.timeToCalculate / 1.0e9); + } else { + this.calculateTime = 0; + } } else { this.routingTime = 0; this.visitedSegments = 0; diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/SettingsHelper.java b/OsmAnd/src/net/osmand/plus/settings/backend/SettingsHelper.java index 2abbd10e22..41d251ea06 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/SettingsHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/SettingsHelper.java @@ -126,7 +126,7 @@ public class SettingsHelper { void onSettingsExportFinished(@NonNull File file, boolean succeed); } - public SettingsHelper(OsmandApplication app) { + public SettingsHelper(@NonNull OsmandApplication app) { this.app = app; } @@ -149,18 +149,27 @@ public class SettingsHelper { protected OsmandApplication app; - private String pluginId; - private String fileName; + protected String pluginId; + protected String fileName; boolean shouldReplace = false; protected List warnings; - SettingsItem(OsmandApplication app) { + SettingsItem(@NonNull OsmandApplication app) { this.app = app; init(); } + SettingsItem(@NonNull OsmandApplication app, @Nullable SettingsItem baseItem) { + this.app = app; + if (baseItem != null) { + this.pluginId = baseItem.pluginId; + this.fileName = baseItem.fileName; + } + init(); + } + SettingsItem(OsmandApplication app, @NonNull JSONObject json) throws JSONException { this.app = app; init(); @@ -203,10 +212,6 @@ public class SettingsHelper { return fileName; } - public void setFileName(String fileName) { - this.fileName = fileName; - } - public boolean applyFileName(@NonNull String fileName) { String n = getFileName(); return n != null && n.endsWith(fileName); @@ -281,13 +286,13 @@ public class SettingsHelper { } @Nullable - abstract SettingsItemReader getReader(); + abstract SettingsItemReader getReader(); @Nullable - abstract SettingsItemWriter getWriter(); + abstract SettingsItemWriter getWriter(); @NonNull - SettingsItemReader getJsonReader() { + SettingsItemReader getJsonReader() { return new SettingsItemReader(this) { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { @@ -315,7 +320,7 @@ public class SettingsHelper { } @NonNull - SettingsItemWriter getJsonWriter() { + SettingsItemWriter getJsonWriter() { return new SettingsItemWriter(this) { @Override public boolean writeToStream(@NonNull OutputStream outputStream) throws IOException { @@ -445,13 +450,13 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return null; } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } @@ -555,13 +560,13 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return null; } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } @@ -638,13 +643,13 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return null; } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } @@ -664,12 +669,12 @@ public class SettingsHelper { duplicateItems = new ArrayList<>(); } - CollectionSettingsItem(OsmandApplication app, @NonNull List items) { - super(app); + CollectionSettingsItem(@NonNull OsmandApplication app, @Nullable CollectionSettingsItem baseItem, @NonNull List items) { + super(app, baseItem); this.items = items; } - CollectionSettingsItem(OsmandApplication app, @NonNull JSONObject json) throws JSONException { + CollectionSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { super(app, json); } @@ -747,6 +752,11 @@ public class SettingsHelper { this.settings = settings; } + protected OsmandSettingsItem(@NonNull OsmandSettings settings, @Nullable OsmandSettingsItem baseItem) { + super(settings.getContext(), baseItem); + this.settings = settings; + } + protected OsmandSettingsItem(@NonNull SettingsItemType type, @NonNull OsmandSettings settings, @NonNull JSONObject json) throws JSONException { super(settings.getContext(), json); this.settings = settings; @@ -885,7 +895,7 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return new OsmandSettingsItemReader(this, getSettings()) { @Override protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -896,7 +906,7 @@ public class SettingsHelper { @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -920,8 +930,8 @@ public class SettingsHelper { this.appMode = appMode; } - public ProfileSettingsItem(@NonNull OsmandApplication app, @NonNull ApplicationModeBean modeBean) { - super(app.getSettings()); + public ProfileSettingsItem(@NonNull OsmandApplication app, @Nullable ProfileSettingsItem baseItem, @NonNull ApplicationModeBean modeBean) { + super(app.getSettings(), baseItem); this.modeBean = modeBean; builder = ApplicationMode.fromModeBean(app, modeBean); appMode = builder.getApplicationMode(); @@ -1059,7 +1069,7 @@ public class SettingsHelper { if (additionalPrefsJson != null) { updatePluginResPrefs(); - SettingsItemReader reader = getReader(); + SettingsItemReader reader = getReader(); if (reader instanceof OsmandSettingsItemReader) { ((OsmandSettingsItemReader) reader).readPreferencesFromJson(additionalPrefsJson); } @@ -1116,7 +1126,7 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return new OsmandSettingsItemReader(this, getSettings()) { @Override protected void readPreferenceFromJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -1129,7 +1139,7 @@ public class SettingsHelper { @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return new OsmandSettingsItemWriter(this, getSettings()) { @Override protected void writePreferenceToJson(@NonNull OsmandPreference preference, @NonNull JSONObject json) throws JSONException { @@ -1182,7 +1192,7 @@ public class SettingsHelper { public StreamSettingsItem(@NonNull OsmandApplication app, @NonNull String name) { super(app); this.name = name; - setFileName(name); + this.fileName = name; } StreamSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { @@ -1193,7 +1203,7 @@ public class SettingsHelper { super(app); this.inputStream = inputStream; this.name = name; - setFileName(name); + this.fileName = name; } @Nullable @@ -1231,7 +1241,7 @@ public class SettingsHelper { @Nullable @Override - public SettingsItemWriter getWriter() { + public SettingsItemWriter getWriter() { return new StreamSettingsItemWriter(this); } } @@ -1282,7 +1292,7 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { @@ -1301,7 +1311,7 @@ public class SettingsHelper { @Nullable @Override - public SettingsItemWriter getWriter() { + public SettingsItemWriter getWriter() { setInputStream(new ByteArrayInputStream(data)); return super.getWriter(); } @@ -1370,6 +1380,7 @@ public class SettingsHelper { return UNKNOWN; } + @NonNull @Override public String toString() { return subtypeName; @@ -1480,7 +1491,7 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return new StreamSettingsItemReader(this) { @Override public void readFromStream(@NonNull InputStream inputStream) throws IOException, IllegalArgumentException { @@ -1509,7 +1520,7 @@ public class SettingsHelper { @Nullable @Override - public SettingsItemWriter getWriter() { + public SettingsItemWriter getWriter() { try { setInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { @@ -1527,7 +1538,7 @@ public class SettingsHelper { shouldReplace = true; String fileName = getFileName(); if (!Algorithms.isEmpty(fileName) && !fileName.endsWith(File.separator)) { - setFileName(fileName + File.separator); + this.fileName = fileName + File.separator; } } @@ -1575,7 +1586,7 @@ public class SettingsHelper { @Nullable @Override - public SettingsItemWriter getWriter() { + public SettingsItemWriter getWriter() { return null; } } @@ -1585,7 +1596,11 @@ public class SettingsHelper { private QuickActionRegistry actionRegistry; public QuickActionsSettingsItem(@NonNull OsmandApplication app, @NonNull List items) { - super(app, items); + super(app, null, items); + } + + public QuickActionsSettingsItem(@NonNull OsmandApplication app, @Nullable QuickActionsSettingsItem baseItem, @NonNull List items) { + super(app, baseItem, items); } QuickActionsSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { @@ -1725,24 +1740,28 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return getJsonReader(); } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } - public static class PoiUiFilterSettingsItem extends CollectionSettingsItem { + public static class PoiUiFiltersSettingsItem extends CollectionSettingsItem { - public PoiUiFilterSettingsItem(@NonNull OsmandApplication app, @NonNull List items) { - super(app, items); + public PoiUiFiltersSettingsItem(@NonNull OsmandApplication app, @NonNull List items) { + super(app, null, items); } - PoiUiFilterSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { + public PoiUiFiltersSettingsItem(@NonNull OsmandApplication app, @Nullable PoiUiFiltersSettingsItem baseItem, @NonNull List items) { + super(app, baseItem, items); + } + + PoiUiFiltersSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { super(app, json); } @@ -1873,13 +1892,13 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return getJsonReader(); } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } @@ -1889,7 +1908,11 @@ public class SettingsHelper { private List existingItemsNames; public MapSourcesSettingsItem(@NonNull OsmandApplication app, @NonNull List items) { - super(app, items); + super(app, null, items); + } + + public MapSourcesSettingsItem(@NonNull OsmandApplication app, @Nullable MapSourcesSettingsItem baseItem, @NonNull List items) { + super(app, baseItem, items); } MapSourcesSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { @@ -2085,13 +2108,13 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return getJsonReader(); } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } @@ -2102,7 +2125,11 @@ public class SettingsHelper { private AvoidSpecificRoads specificRoads; public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull List items) { - super(app, items); + super(app, null, items); + } + + public AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @Nullable AvoidRoadsSettingsItem baseItem, @NonNull List items) { + super(app, baseItem, items); } AvoidRoadsSettingsItem(@NonNull OsmandApplication app, @NonNull JSONObject json) throws JSONException { @@ -2240,13 +2267,13 @@ public class SettingsHelper { @Nullable @Override - SettingsItemReader getReader() { + SettingsItemReader getReader() { return getJsonReader(); } @Nullable @Override - SettingsItemWriter getWriter() { + SettingsItemWriter getWriter() { return null; } } @@ -2256,7 +2283,7 @@ public class SettingsHelper { private OsmandApplication app; private List items = new ArrayList<>(); - SettingsItemsFactory(OsmandApplication app, String jsonStr) throws IllegalArgumentException, JSONException { + SettingsItemsFactory(@NonNull OsmandApplication app, String jsonStr) throws IllegalArgumentException, JSONException { this.app = app; collectItems(new JSONObject(jsonStr)); } @@ -2346,7 +2373,7 @@ public class SettingsHelper { item = new QuickActionsSettingsItem(app, json); break; case POI_UI_FILTERS: - item = new PoiUiFilterSettingsItem(app, json); + item = new PoiUiFiltersSettingsItem(app, json); break; case MAP_SOURCES: item = new MapSourcesSettingsItem(app, json); @@ -2410,7 +2437,7 @@ public class SettingsHelper { private void writeItemFiles(ZipOutputStream zos) throws IOException { for (SettingsItem item : items.values()) { - SettingsItemWriter writer = item.getWriter(); + SettingsItemWriter writer = item.getWriter(); if (writer != null) { String fileName = item.getFileName(); if (Algorithms.isEmpty(fileName)) { @@ -2520,7 +2547,7 @@ public class SettingsHelper { if (item != null && collecting && item.shouldReadOnCollecting() || item != null && !collecting && !item.shouldReadOnCollecting()) { try { - SettingsItemReader reader = item.getReader(); + SettingsItemReader reader = item.getReader(); if (reader != null) { reader.readFromStream(ois); } @@ -2699,8 +2726,8 @@ public class SettingsHelper { if (item.exists()) { duplicateItems.add(((ProfileSettingsItem) item).getModeBean()); } - } else if (item instanceof CollectionSettingsItem) { - List duplicates = ((CollectionSettingsItem) item).processDuplicateItems(); + } else if (item instanceof CollectionSettingsItem) { + List duplicates = ((CollectionSettingsItem) item).processDuplicateItems(); if (!duplicates.isEmpty()) { duplicateItems.addAll(duplicates); } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java index cf2b8d6a11..18e8900203 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportImportSettingsAdapter.java @@ -49,7 +49,7 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { private static final Log LOG = PlatformUtil.getLog(ExportImportSettingsAdapter.class.getName()); private OsmandApplication app; private UiUtilities uiUtilities; - private List dataToOperate; + private List data; private Map> itemsMap; private List itemsTypes; private boolean nightMode; @@ -63,8 +63,7 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { this.importState = importState; this.itemsMap = new HashMap<>(); this.itemsTypes = new ArrayList<>(); - this.dataToOperate = new ArrayList<>(); - dataToOperate = new ArrayList<>(); + this.data = new ArrayList<>(); uiUtilities = app.getUIUtilities(); activeColorRes = nightMode ? R.color.icon_color_active_dark @@ -102,12 +101,12 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { final List listItems = itemsMap.get(type); subTextTv.setText(getSelectedItemsAmount(listItems)); - if (dataToOperate.containsAll(listItems)) { + if (data.containsAll(listItems)) { checkBox.setState(CHECKED); } else { boolean contains = false; for (Object object : listItems) { - if (dataToOperate.contains(object)) { + if (data.contains(object)) { contains = true; break; } @@ -122,12 +121,12 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { checkBox.performClick(); if (checkBox.getState() == CHECKED) { for (Object object : listItems) { - if (!dataToOperate.contains(object)) { - dataToOperate.add(object); + if (!data.contains(object)) { + data.add(object); } } } else { - dataToOperate.removeAll(listItems); + data.removeAll(listItems); } notifyDataSetChanged(); } @@ -146,7 +145,7 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { final Object currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition); boolean isLastGroup = groupPosition == getGroupCount() - 1; - boolean itemSelected = dataToOperate.contains(currentItem); + boolean itemSelected = data.contains(currentItem); final Type type = itemsTypes.get(groupPosition); TextView title = child.findViewById(R.id.title_tv); @@ -166,10 +165,10 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { child.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (dataToOperate.contains(currentItem)) { - dataToOperate.remove(currentItem); + if (data.contains(currentItem)) { + data.remove(currentItem); } else { - dataToOperate.add(currentItem); + data.add(currentItem); } notifyDataSetChanged(); } @@ -293,7 +292,7 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { private String getSelectedItemsAmount(List listItems) { int amount = 0; for (Object item : listItems) { - if (dataToOperate.contains(item)) { + if (data.contains(item)) { amount++; } } @@ -343,17 +342,17 @@ class ExportImportSettingsAdapter extends OsmandBaseExpandableListAdapter { } public void selectAll(boolean selectAll) { - dataToOperate.clear(); + data.clear(); if (selectAll) { for (List values : itemsMap.values()) { - dataToOperate.addAll(values); + data.addAll(values); } } notifyDataSetChanged(); } - List getDataToOperate() { - return this.dataToOperate; + List getData() { + return this.data; } public enum Type { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java index fc25b7990c..a09a8ba435 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ExportProfileBottomSheet.java @@ -26,6 +26,7 @@ import net.osmand.PlatformUtil; import net.osmand.data.LatLon; import net.osmand.map.ITileSource; import net.osmand.map.TileSourceManager; +import net.osmand.map.TileSourceManager.TileSourceTemplate; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.SQLiteTileSource; @@ -40,7 +41,12 @@ import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.quickaction.QuickActionRegistry; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.SettingsHelper; +import net.osmand.plus.settings.backend.SettingsHelper.AvoidRoadsSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.FileSettingsItem; +import net.osmand.plus.settings.backend.SettingsHelper.MapSourcesSettingsItem; +import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFiltersSettingsItem; +import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem; +import net.osmand.plus.settings.backend.SettingsHelper.QuickActionsSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem; import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet; import net.osmand.plus.settings.fragments.ExportImportSettingsAdapter.Type; @@ -274,7 +280,7 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { private List prepareSettingsItemsForExport() { List settingsItems = new ArrayList<>(); - settingsItems.add(new SettingsHelper.ProfileSettingsItem(app, profile)); + settingsItems.add(new ProfileSettingsItem(app, profile)); if (includeAdditionalData) { settingsItems.addAll(prepareAdditionalSettingsItems()); } @@ -287,13 +293,12 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { List poiUIFilters = new ArrayList<>(); List tileSourceTemplates = new ArrayList<>(); List avoidRoads = new ArrayList<>(); - for (Object object : adapter.getDataToOperate()) { + for (Object object : adapter.getData()) { if (object instanceof QuickAction) { quickActions.add((QuickAction) object); } else if (object instanceof PoiUIFilter) { poiUIFilters.add((PoiUIFilter) object); - } else if (object instanceof TileSourceManager.TileSourceTemplate - || object instanceof SQLiteTileSource) { + } else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { try { @@ -306,16 +311,16 @@ public class ExportProfileBottomSheet extends BasePreferenceBottomSheet { } } if (!quickActions.isEmpty()) { - settingsItems.add(new SettingsHelper.QuickActionsSettingsItem(app, quickActions)); + settingsItems.add(new QuickActionsSettingsItem(app, quickActions)); } if (!poiUIFilters.isEmpty()) { - settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); + settingsItems.add(new PoiUiFiltersSettingsItem(app, poiUIFilters)); } if (!tileSourceTemplates.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); + settingsItems.add(new MapSourcesSettingsItem(app, tileSourceTemplates)); } if (!avoidRoads.isEmpty()) { - settingsItems.add(new SettingsHelper.AvoidRoadsSettingsItem(app, avoidRoads)); + settingsItems.add(new AvoidRoadsSettingsItem(app, avoidRoads)); } return settingsItems; } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java index b7ab4e13ea..a521e8e079 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportCompleteFragment.java @@ -36,7 +36,6 @@ import java.util.List; import static net.osmand.aidlapi.OsmAndCustomizationConstants.DRAWER_SETTINGS_ID; import static net.osmand.plus.settings.fragments.ImportSettingsFragment.IMPORT_SETTINGS_TAG; -import static net.osmand.plus.settings.fragments.ImportSettingsFragment.getSettingsToOperate; public class ImportCompleteFragment extends BaseOsmAndFragment { public static final String TAG = ImportCompleteFragment.class.getSimpleName(); @@ -111,7 +110,7 @@ public class ImportCompleteFragment extends BaseOsmAndFragment { if (settingsItems != null) { ImportedSettingsItemsAdapter adapter = new ImportedSettingsItemsAdapter( app, - getSettingsToOperate(settingsItems, true), + ImportSettingsFragment.getSettingsToOperate(settingsItems, true), nightMode, new ImportedSettingsItemsAdapter.OnItemClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java index bf3df71f48..13dc2f94ce 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/ImportSettingsFragment.java @@ -28,12 +28,12 @@ import com.google.android.material.appbar.CollapsingToolbarLayout; import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; import net.osmand.map.ITileSource; -import net.osmand.map.TileSourceManager; +import net.osmand.map.TileSourceManager.TileSourceTemplate; import net.osmand.plus.AppInitializer; -import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.SQLiteTileSource; +import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.plus.settings.backend.SettingsHelper; import net.osmand.plus.settings.backend.SettingsHelper.AvoidRoadsSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.FileSettingsItem; @@ -41,7 +41,7 @@ import net.osmand.plus.settings.backend.SettingsHelper.FileSettingsItem.FileSubt import net.osmand.plus.settings.backend.SettingsHelper.ImportAsyncTask; import net.osmand.plus.settings.backend.SettingsHelper.ImportType; import net.osmand.plus.settings.backend.SettingsHelper.MapSourcesSettingsItem; -import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFilterSettingsItem; +import net.osmand.plus.settings.backend.SettingsHelper.PoiUiFiltersSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.ProfileSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.QuickActionsSettingsItem; import net.osmand.plus.settings.backend.SettingsHelper.SettingsItem; @@ -54,6 +54,7 @@ import net.osmand.plus.poi.PoiUIFilter; import net.osmand.plus.quickaction.QuickAction; import net.osmand.plus.settings.fragments.ExportImportSettingsAdapter.Type; import net.osmand.plus.widgets.TextViewEx; +import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -218,7 +219,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment break; } case R.id.continue_button: { - if (adapter.getDataToOperate().isEmpty()) { + if (adapter.getData().isEmpty()) { app.showShortToastMessage(getString(R.string.shared_string_nothing_selected)); } else { importItems(); @@ -244,7 +245,7 @@ public class ImportSettingsFragment extends BaseOsmAndFragment private void importItems() { updateUi(R.string.shared_string_preparing, R.string.checking_for_duplicate_description); - List selectedItems = getSettingsItemsFromData(adapter.getDataToOperate()); + List selectedItems = getSettingsItemsFromData(adapter.getData()); if (file != null && settingsItems != null) { duplicateStartTime = System.currentTimeMillis(); settingsHelper.checkDuplicates(file, settingsItems, selectedItems, getDuplicatesListener()); @@ -316,22 +317,75 @@ public class ImportSettingsFragment extends BaseOsmAndFragment this.settingsItems = settingsItems; } - private List getSettingsItemsFromData(List dataToOperate) { + @Nullable + private ProfileSettingsItem getBaseProfileSettingsItem(ApplicationModeBean modeBean) { + for (SettingsItem settingsItem : settingsItems) { + if (settingsItem.getType() == SettingsItemType.PROFILE) { + ProfileSettingsItem profileItem = (ProfileSettingsItem) settingsItem; + ApplicationModeBean bean = profileItem.getModeBean(); + if (Algorithms.objectEquals(bean.stringKey, modeBean.stringKey) && Algorithms.objectEquals(bean.userProfileName, modeBean.userProfileName)) { + return profileItem; + } + } + } + return null; + } + + @Nullable + private QuickActionsSettingsItem getBaseQuickActionsSettingsItem() { + for (SettingsItem settingsItem : settingsItems) { + if (settingsItem.getType() == SettingsItemType.QUICK_ACTIONS) { + return (QuickActionsSettingsItem) settingsItem; + } + } + return null; + } + + @Nullable + private PoiUiFiltersSettingsItem getBasePoiUiFiltersSettingsItem() { + for (SettingsItem settingsItem : settingsItems) { + if (settingsItem.getType() == SettingsItemType.POI_UI_FILTERS) { + return (PoiUiFiltersSettingsItem) settingsItem; + } + } + return null; + } + + @Nullable + private MapSourcesSettingsItem getBaseMapSourcesSettingsItem() { + for (SettingsItem settingsItem : settingsItems) { + if (settingsItem.getType() == SettingsItemType.MAP_SOURCES) { + return (MapSourcesSettingsItem) settingsItem; + } + } + return null; + } + + @Nullable + private AvoidRoadsSettingsItem getBaseAvoidRoadsSettingsItem() { + for (SettingsItem settingsItem : settingsItems) { + if (settingsItem.getType() == SettingsItemType.AVOID_ROADS) { + return (AvoidRoadsSettingsItem) settingsItem; + } + } + return null; + } + + private List getSettingsItemsFromData(List data) { List settingsItems = new ArrayList<>(); + List appModeBeans = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); List tileSourceTemplates = new ArrayList<>(); List avoidRoads = new ArrayList<>(); - for (Object object : dataToOperate) { - if (object instanceof ApplicationMode.ApplicationModeBean) { - settingsItems.add(new SettingsHelper.ProfileSettingsItem(app, (ApplicationMode.ApplicationModeBean) object)); - } - if (object instanceof QuickAction) { + for (Object object : data) { + if (object instanceof ApplicationModeBean) { + appModeBeans.add((ApplicationModeBean) object); + } else if (object instanceof QuickAction) { quickActions.add((QuickAction) object); } else if (object instanceof PoiUIFilter) { poiUIFilters.add((PoiUIFilter) object); - } else if (object instanceof TileSourceManager.TileSourceTemplate - || object instanceof SQLiteTileSource) { + } else if (object instanceof TileSourceTemplate || object instanceof SQLiteTileSource) { tileSourceTemplates.add((ITileSource) object); } else if (object instanceof File) { settingsItems.add(new FileSettingsItem(app, (File) object)); @@ -339,69 +393,82 @@ public class ImportSettingsFragment extends BaseOsmAndFragment avoidRoads.add((AvoidRoadInfo) object); } } + if (!appModeBeans.isEmpty()) { + for (ApplicationModeBean modeBean : appModeBeans) { + settingsItems.add(new ProfileSettingsItem(app, getBaseProfileSettingsItem(modeBean), modeBean)); + } + } if (!quickActions.isEmpty()) { - settingsItems.add(new QuickActionsSettingsItem(app, quickActions)); + settingsItems.add(new QuickActionsSettingsItem(app, getBaseQuickActionsSettingsItem(), quickActions)); } if (!poiUIFilters.isEmpty()) { - settingsItems.add(new SettingsHelper.PoiUiFilterSettingsItem(app, poiUIFilters)); + settingsItems.add(new PoiUiFiltersSettingsItem(app, getBasePoiUiFiltersSettingsItem(), poiUIFilters)); } if (!tileSourceTemplates.isEmpty()) { - settingsItems.add(new SettingsHelper.MapSourcesSettingsItem(app, tileSourceTemplates)); + settingsItems.add(new MapSourcesSettingsItem(app, getBaseMapSourcesSettingsItem(), tileSourceTemplates)); } if (!avoidRoads.isEmpty()) { - settingsItems.add(new SettingsHelper.AvoidRoadsSettingsItem(app, avoidRoads)); + settingsItems.add(new AvoidRoadsSettingsItem(app, getBaseAvoidRoadsSettingsItem(), avoidRoads)); } return settingsItems; } public static Map> getSettingsToOperate(List settingsItems, boolean importComplete) { Map> settingsToOperate = new HashMap<>(); - List profiles = new ArrayList<>(); + List profiles = new ArrayList<>(); List quickActions = new ArrayList<>(); List poiUIFilters = new ArrayList<>(); List tileSourceTemplates = new ArrayList<>(); List routingFilesList = new ArrayList<>(); List renderFilesList = new ArrayList<>(); List avoidRoads = new ArrayList<>(); - for (SettingsItem item : settingsItems) { - if (item.getType().equals(SettingsItemType.PROFILE)) { - profiles.add(((ProfileSettingsItem) item).getModeBean()); - } else if (item.getType().equals(SettingsItemType.QUICK_ACTIONS)) { - QuickActionsSettingsItem quickActionsItem = (QuickActionsSettingsItem) item; - if (importComplete) { - quickActions.addAll(quickActionsItem.getAppliedItems()); - } else { - quickActions.addAll(quickActionsItem.getItems()); - } - } else if (item.getType().equals(SettingsItemType.POI_UI_FILTERS)) { - PoiUiFilterSettingsItem poiUiFilterItem = (PoiUiFilterSettingsItem) item; - if (importComplete) { - poiUIFilters.addAll(poiUiFilterItem.getAppliedItems()); - } else { - poiUIFilters.addAll(poiUiFilterItem.getItems()); - } - } else if (item.getType().equals(SettingsItemType.MAP_SOURCES)) { - MapSourcesSettingsItem mapSourcesItem = (MapSourcesSettingsItem) item; - if (importComplete) { - tileSourceTemplates.addAll(mapSourcesItem.getAppliedItems()); - } else { - tileSourceTemplates.addAll(mapSourcesItem.getItems()); - } - } else if (item.getType().equals(SettingsItemType.FILE)) { - FileSettingsItem fileItem = (FileSettingsItem) item; - if (fileItem.getSubtype() == FileSubtype.RENDERING_STYLE) { - renderFilesList.add(fileItem.getFile()); - } else if (fileItem.getSubtype() == FileSubtype.ROUTING_CONFIG) { - routingFilesList.add(fileItem.getFile()); - } - } else if (item.getType().equals(SettingsItemType.AVOID_ROADS)) { - AvoidRoadsSettingsItem avoidRoadsItem = (AvoidRoadsSettingsItem) item; - if (importComplete) { - avoidRoads.addAll(avoidRoadsItem.getAppliedItems()); - } else { - avoidRoads.addAll(avoidRoadsItem.getItems()); - } + switch (item.getType()) { + case PROFILE: + profiles.add(((ProfileSettingsItem) item).getModeBean()); + break; + case FILE: + FileSettingsItem fileItem = (FileSettingsItem) item; + if (fileItem.getSubtype() == FileSubtype.RENDERING_STYLE) { + renderFilesList.add(fileItem.getFile()); + } else if (fileItem.getSubtype() == FileSubtype.ROUTING_CONFIG) { + routingFilesList.add(fileItem.getFile()); + } + break; + case QUICK_ACTIONS: + QuickActionsSettingsItem quickActionsItem = (QuickActionsSettingsItem) item; + if (importComplete) { + quickActions.addAll(quickActionsItem.getAppliedItems()); + } else { + quickActions.addAll(quickActionsItem.getItems()); + } + break; + case POI_UI_FILTERS: + PoiUiFiltersSettingsItem poiUiFilterItem = (PoiUiFiltersSettingsItem) item; + if (importComplete) { + poiUIFilters.addAll(poiUiFilterItem.getAppliedItems()); + } else { + poiUIFilters.addAll(poiUiFilterItem.getItems()); + } + break; + case MAP_SOURCES: + MapSourcesSettingsItem mapSourcesItem = (MapSourcesSettingsItem) item; + if (importComplete) { + tileSourceTemplates.addAll(mapSourcesItem.getAppliedItems()); + } else { + tileSourceTemplates.addAll(mapSourcesItem.getItems()); + } + break; + case AVOID_ROADS: + AvoidRoadsSettingsItem avoidRoadsItem = (AvoidRoadsSettingsItem) item; + if (importComplete) { + avoidRoads.addAll(avoidRoadsItem.getAppliedItems()); + } else { + avoidRoads.addAll(avoidRoadsItem.getItems()); + } + break; + default: + break; } } diff --git a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java index fdc9ab950e..7cc2e97f63 100644 --- a/OsmAnd/src/net/osmand/plus/views/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/GPXLayer.java @@ -2,7 +2,6 @@ package net.osmand.plus.views; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; @@ -11,6 +10,7 @@ import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.AsyncTask; import android.util.Pair; @@ -21,11 +21,13 @@ import androidx.annotation.Nullable; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.content.ContextCompat; +import net.osmand.AndroidUtils; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; +import net.osmand.PlatformUtil; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; @@ -40,6 +42,7 @@ import net.osmand.plus.MapMarkersHelper.MapMarker; import net.osmand.plus.MapMarkersHelper.MapMarkersGroup; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.base.PointImageDrawable; import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; @@ -55,6 +58,8 @@ import net.osmand.render.RenderingRulesStorage; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; +import org.apache.commons.logging.Log; + import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -67,29 +72,30 @@ import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_WIDTH_ATTR; public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IMoveObjectProvider, MapTextProvider { + private static final Log log = PlatformUtil.getLog(GPXLayer.class); + private static final double TOUCH_RADIUS_MULTIPLIER = 1.5; + private static final int DEFAULT_WIDTH_MULTIPLIER = 7; private static final int START_ZOOM = 7; private OsmandMapTileView view; private Paint paint; - private Paint paint2; - private boolean isPaint2; private Paint shadowPaint; - private boolean isShadowPaint; - private Paint paint_1; - private boolean isPaint_1; + private Paint paintIcon; private int cachedHash; private int cachedColor; - private Paint paintIcon; private int currentTrackColor; + private float defaultTrackWidth; + private Map cachedTrackWidth = new HashMap<>(); + private Drawable startPointIcon; + private Drawable finishPointIcon; private LayerDrawable selectedPoint; private TrackChartPoints trackChartPoints; private GpxSelectionHelper selectedGpxHelper; private MapMarkersHelper mapMarkersHelper; - private Paint paintBmp; private List cache = new ArrayList<>(); private Map pointFileMap = new HashMap<>(); private MapTextLayer textLayer; @@ -134,26 +140,14 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM paint = new Paint(); paint.setStyle(Style.STROKE); paint.setAntiAlias(true); - paint2 = new Paint(); - paint2.setStyle(Style.STROKE); - paint2.setAntiAlias(true); shadowPaint = new Paint(); shadowPaint.setStyle(Style.STROKE); shadowPaint.setAntiAlias(true); - paint_1 = new Paint(); - paint_1.setStyle(Style.STROKE); - paint_1.setAntiAlias(true); - - paintBmp = new Paint(); - paintBmp.setAntiAlias(true); - paintBmp.setFilterBitmap(true); - paintBmp.setDither(true); paintTextIcon = new Paint(); paintTextIcon.setTextSize(10 * view.getDensity()); paintTextIcon.setTextAlign(Align.CENTER); paintTextIcon.setFakeBoldText(true); -// paintTextIcon.setColor(Color.WHITE); paintTextIcon.setAntiAlias(true); textLayer = view.getLayerByClass(MapTextLayer.class); @@ -164,21 +158,24 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM paintOuterRect = new Paint(); paintOuterRect.setStyle(Style.STROKE); paintOuterRect.setAntiAlias(true); -// paintOuterRect.setColor(Color.WHITE); paintOuterRect.setStrokeWidth(3); paintOuterRect.setAlpha(255); paintGridCircle = new Paint(); paintGridCircle.setStyle(Style.FILL_AND_STROKE); paintGridCircle.setAntiAlias(true); - paintGridOuterCircle = new Paint(); - paintGridOuterCircle.setStyle(Style.FILL_AND_STROKE); - paintGridOuterCircle.setAntiAlias(true); - paintGridOuterCircle.setColor(Color.WHITE); - paintGridOuterCircle.setAlpha(204); + paintGridOuterCircle = new Paint(); + paintGridOuterCircle.setStyle(Style.FILL_AND_STROKE); + paintGridOuterCircle.setAntiAlias(true); + paintGridOuterCircle.setColor(Color.WHITE); + paintGridOuterCircle.setAlpha(204); paintIcon = new Paint(); selectedPoint = (LayerDrawable) AppCompatResources.getDrawable(view.getContext(), R.drawable.map_location_default); + UiUtilities iconsCache = view.getApplication().getUIUtilities(); + startPointIcon = iconsCache.getIcon(R.drawable.map_track_point_start); + finishPointIcon = iconsCache.getIcon(R.drawable.map_track_point_finish); + contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class); visitedColor = ContextCompat.getColor(view.getApplication(), R.color.color_ok); @@ -213,6 +210,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } drawSelectedFilesSplits(canvas, tileBox, selectedGPXFiles, settings); drawSelectedFilesPoints(canvas, tileBox, selectedGPXFiles); + drawSelectedFilesStartEndPoints(canvas, tileBox, selectedGPXFiles); } if (textLayer != null && isTextVisible()) { textLayer.putData(this, cache); @@ -220,29 +218,28 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } - private int updatePaints(int color, boolean routePoints, boolean currentTrack, DrawSettings nightMode, RotatedTileBox tileBox) { + private int updatePaints(int color, String width, boolean routePoints, boolean currentTrack, DrawSettings drawSettings, RotatedTileBox tileBox) { RenderingRulesStorage rrs = view.getApplication().getRendererRegistry().getCurrentSelectedRenderer(); - final boolean isNight = nightMode != null && nightMode.isNightMode(); - int hsh = calculateHash(rrs, routePoints, isNight, tileBox.getMapDensity(), tileBox.getZoom(), - currentTrackColorPref.get(), currentTrackWidthPref.get()); - if (hsh != cachedHash) { - cachedHash = hsh; + boolean nightMode = drawSettings != null && drawSettings.isNightMode(); + int hash = calculateHash(rrs, cachedTrackWidth, routePoints, nightMode, tileBox.getMapDensity(), tileBox.getZoom(), + currentTrackColorPref.get(), currentTrackWidthPref.get()); + if (hash != cachedHash) { + cachedHash = hash; cachedColor = ContextCompat.getColor(view.getApplication(), R.color.gpx_track); + defaultTrackWidth = DEFAULT_WIDTH_MULTIPLIER * view.getDensity(); if (rrs != null) { RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs); - req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, isNight); - CommonPreference p = view.getSettings().getCustomRenderProperty(CURRENT_TRACK_COLOR_ATTR); - if (p != null && p.isSet()) { + req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, nightMode); + if (currentTrackColorPref != null && currentTrackColorPref.isSet()) { RenderingRuleProperty ctColor = rrs.PROPS.get(CURRENT_TRACK_COLOR_ATTR); if (ctColor != null) { - req.setStringFilter(ctColor, p.get()); + req.setStringFilter(ctColor, currentTrackColorPref.get()); } } - CommonPreference p2 = view.getSettings().getCustomRenderProperty(CURRENT_TRACK_WIDTH_ATTR); - if (p2 != null && p2.isSet()) { + if (currentTrackWidthPref != null && currentTrackWidthPref.isSet()) { RenderingRuleProperty ctWidth = rrs.PROPS.get(CURRENT_TRACK_WIDTH_ATTR); if (ctWidth != null) { - req.setStringFilter(ctWidth, p2.get()); + req.setStringFilter(ctWidth, currentTrackWidthPref.get()); } } String additional = ""; @@ -262,32 +259,60 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM rc.setDensityValue((float) tileBox.getMapDensity()); cachedColor = req.getIntPropertyValue(rrs.PROPS.R_COLOR); osmandRenderer.updatePaint(req, paint, 0, false, rc); - isPaint2 = osmandRenderer.updatePaint(req, paint2, 1, false, rc); - isPaint_1 = osmandRenderer.updatePaint(req, paint_1, -1, false, rc); - isShadowPaint = req.isSpecified(rrs.PROPS.R_SHADOW_RADIUS); - if (isShadowPaint) { - ColorFilter cf = new PorterDuffColorFilter(req.getIntPropertyValue(rrs.PROPS.R_SHADOW_COLOR), - Mode.SRC_IN); - shadowPaint.setColorFilter(cf); - shadowPaint.setStrokeWidth(paint.getStrokeWidth() + 2 - * rc.getComplexValue(req, rrs.PROPS.R_SHADOW_RADIUS)); + + if (req.isSpecified(rrs.PROPS.R_SHADOW_RADIUS)) { + int shadowColor = req.getIntPropertyValue(rrs.PROPS.R_SHADOW_COLOR); + float shadowRadius = rc.getComplexValue(req, rrs.PROPS.R_SHADOW_RADIUS); + shadowPaint.setColorFilter(new PorterDuffColorFilter(shadowColor, Mode.SRC_IN)); + shadowPaint.setStrokeWidth(paint.getStrokeWidth() + 2 * shadowRadius); + } + for (String key : cachedTrackWidth.keySet()) { + acquireTrackWidth(key, rrs, req, rc); } } else { - System.err.println("Rendering attribute gpx is not found !"); - paint.setStrokeWidth(7 * view.getDensity()); + log.error("Rendering attribute gpx is not found !"); + for (String key : cachedTrackWidth.keySet()) { + cachedTrackWidth.put(key, defaultTrackWidth); + } } } } paint.setColor(color == 0 ? cachedColor : color); + Float strikeWidth = cachedTrackWidth.get(width); + if (strikeWidth != null) { + paint.setStrokeWidth(strikeWidth); + } return cachedColor; } + private void acquireTrackWidth(String widthKey, RenderingRulesStorage rrs, RenderingRuleSearchRequest req, RenderingContext rc) { + if (!Algorithms.isEmpty(widthKey) && Algorithms.isInt(widthKey)) { + try { + int widthDp = Integer.parseInt(widthKey); + float widthF = AndroidUtils.dpToPx(view.getApplication(), widthDp); + cachedTrackWidth.put(widthKey, widthF); + } catch (NumberFormatException e) { + log.error(e.getMessage(), e); + cachedTrackWidth.put(widthKey, defaultTrackWidth); + } + } else { + RenderingRuleProperty ctWidth = rrs.PROPS.get(CURRENT_TRACK_WIDTH_ATTR); + if (ctWidth != null) { + req.setStringFilter(ctWidth, widthKey); + } + if (req.searchRenderingAttribute("gpx")) { + float widthF = rc.getComplexValue(req, req.ALL.R_STROKE_WIDTH); + cachedTrackWidth.put(widthKey, widthF); + } + } + } + private int calculateHash(Object... o) { return Arrays.hashCode(o); } private void drawSelectedFilesSplits(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles, - DrawSettings settings) { + DrawSettings settings) { if (tileBox.getZoom() >= START_ZOOM) { // request to load for (SelectedGpxFile g : selectedGPXFiles) { @@ -354,11 +379,11 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM paintTextIcon.getTextBounds(nm, 0, nm.length(), bounds); int nmWidth = bounds.width(); int nmHeight = bounds.height(); - RectF rect = new RectF(x - nmWidth / 2 - 2 * (float) Math.ceil(tileBox.getDensity()), - y + nmHeight / 2 + 3 * (float) Math.ceil(tileBox.getDensity()), - x + nmWidth / 2 + 3 * (float) Math.ceil(tileBox.getDensity()), - y - nmHeight / 2 - 2 * (float) Math.ceil(tileBox.getDensity())); - canvas.drawRoundRect(rect, 0, 0, paintInnerRect); + RectF rect = new RectF(x - nmWidth / 2 - 2 * (float) Math.ceil(tileBox.getDensity()), + y + nmHeight / 2 + 3 * (float) Math.ceil(tileBox.getDensity()), + x + nmWidth / 2 + 3 * (float) Math.ceil(tileBox.getDensity()), + y - nmHeight / 2 - 2 * (float) Math.ceil(tileBox.getDensity())); + canvas.drawRoundRect(rect, 0, 0, paintInnerRect); canvas.drawRoundRect(rect, 0, 0, paintOuterRect); // canvas.drawRect(rect, paintInnerRect); // canvas.drawRect(rect, paintOuterRect); @@ -368,6 +393,34 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } } + private void drawSelectedFilesStartEndPoints(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles) { + if (tileBox.getZoom() >= START_ZOOM) { + for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { + if (selectedGpxFile.getGpxFile().isShowStartFinish()) { + List segments = selectedGpxFile.getPointsToDisplay(); + TrkSegment endSegment = segments.get(segments.size() - 1); + + WptPt start = segments.get(0).points.get(0); + WptPt end = endSegment.points.get(endSegment.points.size() - 1); + + drawPoint(canvas, tileBox, start, startPointIcon); + drawPoint(canvas, tileBox, end, finishPointIcon); + } + } + } + } + + private void drawPoint(Canvas canvas, RotatedTileBox tileBox, WptPt wptPt, Drawable icon) { + int pointX = (int) tileBox.getPixXFromLatLon(wptPt.lat, wptPt.lon); + int pointY = (int) tileBox.getPixYFromLatLon(wptPt.lat, wptPt.lon); + + icon.setBounds(pointX - icon.getIntrinsicWidth() / 2, + pointY - icon.getIntrinsicHeight() / 2, + pointX + icon.getIntrinsicWidth() / 2, + pointY + icon.getIntrinsicHeight() / 2); + icon.draw(canvas); + } + private void drawSelectedFilesPoints(Canvas canvas, RotatedTileBox tileBox, List selectedGPXFiles) { if (tileBox.getZoom() >= START_ZOOM) { float textScale = view.getSettings().TEXT_SCALE.get(); @@ -463,7 +516,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM trackChartPoints.setSegmentColor(color); } paintGridCircle.setColor(color); - paintGridCircle.setAlpha(255); + paintGridCircle.setAlpha(255); QuadRect latLonBounds = tileBox.getLatLonBounds(); float r = 3 * tileBox.getDensity(); List xAxisPoints = trackChartPoints.getXAxisPoints(); @@ -517,8 +570,13 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM } private void drawSelectedFilesSegments(Canvas canvas, RotatedTileBox tileBox, - List selectedGPXFiles, DrawSettings settings) { - + List selectedGPXFiles, DrawSettings settings) { + for (SelectedGpxFile selectedGpxFile : selectedGPXFiles) { + String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get()); + if (!cachedTrackWidth.containsKey(width)) { + cachedTrackWidth.put(width, null); + } + } SelectedGpxFile currentTrack = null; for (SelectedGpxFile g : selectedGPXFiles) { if (g.isShowCurrentTrack()) { @@ -536,6 +594,7 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM RotatedTileBox tileBox, DrawSettings settings) { List segments = selectedGpxFile.getPointsToDisplay(); for (TrkSegment ts : segments) { + String width = selectedGpxFile.getGpxFile().getWidth(currentTrackWidthPref.get()); int color = selectedGpxFile.getGpxFile().getColor(0); if (currentTrack) { color = currentTrackColor; @@ -550,8 +609,8 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM ts.renderer = new Renderable.StandardTrack(ts.points, 17.2); } } - updatePaints(color, selectedGpxFile.isRoutePoints(), currentTrack, settings, tileBox); - if(ts.renderer instanceof Renderable.RenderableSegment) { + updatePaints(color, width, selectedGpxFile.isRoutePoints(), currentTrack, settings, tileBox); + if (ts.renderer instanceof Renderable.RenderableSegment) { ((Renderable.RenderableSegment) ts.renderer).drawSegment(view.getZoom(), paint, canvas, tileBox); } } diff --git a/OsmAnd/src/net/osmand/plus/views/ImpassableRoadsLayer.java b/OsmAnd/src/net/osmand/plus/views/ImpassableRoadsLayer.java index 6acc0c8d7b..e2e715a029 100644 --- a/OsmAnd/src/net/osmand/plus/views/ImpassableRoadsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/ImpassableRoadsLayer.java @@ -92,9 +92,8 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements private void drawPoint(Canvas canvas, float x, float y, boolean active) { float textScale = activity.getMyApplication().getSettings().TEXT_SCALE.get(); - float left = x - roadWorkIcon.getWidth() / 2f * textScale; - float top = y - roadWorkIcon.getHeight() * textScale; - Rect destRect = getIconDestinationRect(left, top, roadWorkIcon.getWidth(), roadWorkIcon.getHeight(), textScale); + y -= roadWorkIcon.getHeight() / 2f * textScale; + Rect destRect = getIconDestinationRect(x, y, roadWorkIcon.getWidth(), roadWorkIcon.getHeight(), textScale); canvas.drawBitmap(roadWorkIcon, null, destRect, active ? activePaint : paint); } diff --git a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java index 351f1891d6..e490925754 100644 --- a/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java +++ b/OsmAndCore-sample/src/net/osmand/core/samples/android/sample1/CurrentPositionHelper.java @@ -191,6 +191,7 @@ public class CurrentPositionHelper { private void justifyResult(List res, final ResultMatcher result) { List complete = new ArrayList<>(); double minBuildingDistance = 0; + GeocodingUtilities gu = new GeocodingUtilities(); if (res != null) { for (GeocodingResult r : res) { BinaryMapIndexReader foundRepo = null; @@ -208,7 +209,7 @@ public class CurrentPositionHelper { } else if (foundRepo != null) { List justified = null; try { - justified = new GeocodingUtilities().justifyReverseGeocodingSearch(r, foundRepo, + justified = gu.justifyReverseGeocodingSearch(r, foundRepo, minBuildingDistance, result); } catch (IOException e) { log.error("Exception happened during reverse geocoding", e); @@ -227,6 +228,7 @@ public class CurrentPositionHelper { complete.add(r); } } + gu.filterDuplicateRegionResults(complete); } if (result.isCancelled()) { @@ -237,7 +239,7 @@ public class CurrentPositionHelper { }); return; } - Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); + // Collections.sort(complete, GeocodingUtilities.DISTANCE_COMPARATOR); // for(GeocodingResult rt : complete) { // System.out.println(rt.toString()); // }