diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/io/Base64.java b/OsmAnd-java/src/main/java/net/osmand/osm/io/Base64.java index 0a3da9bee2..0def1af562 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/io/Base64.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/io/Base64.java @@ -1,93 +1,104 @@ package net.osmand.osm.io; + /** * @source http://www.javaworld.com/javaworld/javatips/jw-javatip47.html -- 24.11.2008, (mb) */ public class Base64 { - /******************************************************************************************************************* - * BASE 64 encoding of a String or an array of bytes. See also RFC 1421. - * - * @author Unknown - * @author David W. Croft - * @version 1998-06-08 - ******************************************************************************************************************/ + /******************************************************************************************************************* + * BASE 64 encoding of a String or an array of bytes. See also RFC 1421. + * + * @author Unknown + * @author David W. Croft + * @version 1998-06-08 + ******************************************************************************************************************/ - ////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////// - public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7 - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15 - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23 - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31 - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39 - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47 - 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55 - '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63 + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + public static final char[] alphabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0 to 7 + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 8 to 15 + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 16 to 23 + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 24 to 31 + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 32 to 39 + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 40 to 47 + 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 48 to 55 + '4', '5', '6', '7', '8', '9', '+', '/' }; // 56 to 63 - ////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// - public static String encode(final String s) - ////////////////////////////////////////////////////////////////////// - { - return encode(s.getBytes()); - } + public static int indexOf(char c) { + for (int i = 0; i < alphabet.length; i++) { + if (alphabet[i] == c) { + return i; + } + } + return -1; + } - public static String encode(final byte[] octetString) - ////////////////////////////////////////////////////////////////////// - { - int bits24; - int bits6; - final char[] out = new char[((octetString.length - 1) / 3 + 1) * 4]; + public static String encode(final String s) + ////////////////////////////////////////////////////////////////////// + { + return encode(s.getBytes()); + } - int outIndex = 0; - int i = 0; + public static String encode(final byte[] octetString) + ////////////////////////////////////////////////////////////////////// + { + int bits24; + int bits6; - while ((i + 3) <= octetString.length) { - // store the octets - bits24 = (octetString[i++] & 0xFF) << 16; - bits24 |= (octetString[i++] & 0xFF) << 8; - bits24 |= (octetString[i++] & 0xFF); + final char[] out = new char[((octetString.length - 1) / 3 + 1) * 4]; - bits6 = (bits24 & 0x00FC0000) >> 18; - out[outIndex++] = alphabet[bits6]; - bits6 = (bits24 & 0x0003F000) >> 12; - out[outIndex++] = alphabet[bits6]; - bits6 = (bits24 & 0x00000FC0) >> 6; - out[outIndex++] = alphabet[bits6]; - bits6 = (bits24 & 0x0000003F); - out[outIndex++] = alphabet[bits6]; - } + int outIndex = 0; + int i = 0; - if (octetString.length - i == 2) { - // store the octets - bits24 = (octetString[i] & 0xFF) << 16; - bits24 |= (octetString[i + 1] & 0xFF) << 8; + while ((i + 3) <= octetString.length) { + // store the octets + bits24 = (octetString[i++] & 0xFF) << 16; + bits24 |= (octetString[i++] & 0xFF) << 8; + bits24 |= (octetString[i++] & 0xFF); - bits6 = (bits24 & 0x00FC0000) >> 18; - out[outIndex++] = alphabet[bits6]; - bits6 = (bits24 & 0x0003F000) >> 12; - out[outIndex++] = alphabet[bits6]; - bits6 = (bits24 & 0x00000FC0) >> 6; - out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x00FC0000) >> 18; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0003F000) >> 12; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x00000FC0) >> 6; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0000003F); + out[outIndex++] = alphabet[bits6]; + } - // padding - out[outIndex++] = '='; - } else if (octetString.length - i == 1) { - // store the octets - bits24 = (octetString[i] & 0xFF) << 16; + if (octetString.length - i == 2) { + // store the octets + bits24 = (octetString[i] & 0xFF) << 16; + bits24 |= (octetString[i + 1] & 0xFF) << 8; - bits6 = (bits24 & 0x00FC0000) >> 18; - out[outIndex++] = alphabet[bits6]; - bits6 = (bits24 & 0x0003F000) >> 12; - out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x00FC0000) >> 18; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0003F000) >> 12; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x00000FC0) >> 6; + out[outIndex++] = alphabet[bits6]; - // padding - out[outIndex++] = '='; - out[outIndex++] = '='; - } + // padding + out[outIndex++] = '='; + } else if (octetString.length - i == 1) { + // store the octets + bits24 = (octetString[i] & 0xFF) << 16; - return new String(out); - } + bits6 = (bits24 & 0x00FC0000) >> 18; + out[outIndex++] = alphabet[bits6]; + bits6 = (bits24 & 0x0003F000) >> 12; + out[outIndex++] = alphabet[bits6]; + + // padding + out[outIndex++] = '='; + out[outIndex++] = '='; + } + + return new String(out); + } } \ No newline at end of file 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 eb93e95699..2e6db09022 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteCalculationProgress.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteCalculationProgress.java @@ -49,14 +49,16 @@ public class RouteCalculationProgress { pr = Math.min(p * p / (all * all), 1); } float progress = INITIAL_PROGRESS; - if (totalIterations > 1) { + if (totalIterations <= 1) { + progress = INITIAL_PROGRESS + pr * (1 - INITIAL_PROGRESS); + } else if (totalIterations <= 2) { if (iteration < 1) { progress = pr * FIRST_ITERATION + INITIAL_PROGRESS; } else { progress = (INITIAL_PROGRESS + FIRST_ITERATION) + pr * (1 - FIRST_ITERATION - INITIAL_PROGRESS); } } else { - progress = INITIAL_PROGRESS + pr * (1 - INITIAL_PROGRESS); + progress = (float) ((iteration + Math.min(pr, 0.7)) / totalIterations); } return Math.min(progress * 100f, 99); } 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 f284a205aa..5aefb2ac44 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RoutePlannerFrontEnd.java @@ -64,8 +64,6 @@ public class RoutePlannerFrontEnd { public int routeGapDistance; public int routeDistanceUnmatched; - public boolean calculationCancelled; - private boolean calculationDone; public GpxRouteApproximation(RoutingContext ctx) { this.ctx = ctx; @@ -82,10 +80,6 @@ public class RoutePlannerFrontEnd { routeCalculations, routeDistCalculations, routePointsSearched, routeDistance, routeDistanceUnmatched); } - public boolean isCalculationDone() { - return calculationDone; - } - public double distFromLastPoint(LatLon startPoint) { if (result.size() > 0) { return MapUtils.getDistance(getLastPoint(), startPoint); @@ -239,18 +233,22 @@ public class RoutePlannerFrontEnd { public GpxRouteApproximation searchGpxRoute(GpxRouteApproximation gctx, List gpxPoints, ResultMatcher resultMatcher) throws IOException, InterruptedException { long timeToCalculate = System.nanoTime(); gctx.ctx.keepNativeRoutingContext = true; + if (gctx.ctx.calculationProgress == null) { + gctx.ctx.calculationProgress = new RouteCalculationProgress(); + } GpxPoint start = null; GpxPoint prev = null; if (gpxPoints.size() > 0) { gctx.ctx.calculationProgress.totalIterations = (int) (gpxPoints.get(gpxPoints.size() - 1).cumDist / gctx.MAXIMUM_STEP_APPROXIMATION + 1); start = gpxPoints.get(0); } - while (start != null && !gctx.calculationCancelled) { + while (start != null && !gctx.ctx.calculationProgress.isCancelled) { double routeDist = gctx.MAXIMUM_STEP_APPROXIMATION; GpxPoint next = findNextGpxPointWithin(gctx, gpxPoints, start, routeDist); boolean routeFound = false; - gctx.ctx.calculationProgress.nextIteration(); if (next != null && initRoutingPoint(start, gctx, gctx.MINIMUM_POINT_APPROXIMATION)) { + gctx.ctx.calculationProgress.totalEstimatedDistance = 0; + gctx.ctx.calculationProgress.iteration = (int) (next.cumDist / gctx.MAXIMUM_STEP_APPROXIMATION); while (routeDist >= gctx.MINIMUM_STEP_APPROXIMATION && !routeFound) { routeFound = initRoutingPoint(next, gctx, gctx.MINIMUM_POINT_APPROXIMATION); if (routeFound) { @@ -299,20 +297,19 @@ public class RoutePlannerFrontEnd { } start = next; } - if(gctx.ctx.calculationProgress != null) { - gctx.ctx.calculationProgress.timeToCalculate = System.nanoTime() - timeToCalculate; + if (gctx.ctx.calculationProgress != null) { + gctx.ctx.calculationProgress.timeToCalculate = System.nanoTime() - timeToCalculate; } gctx.ctx.deleteNativeRoutingContext(); BinaryRoutePlanner.printDebugMemoryInformation(gctx.ctx); calculateGpxRoute(gctx, gpxPoints); - if (!gctx.result.isEmpty() && !gctx.calculationCancelled) { + if (!gctx.result.isEmpty() && !gctx.ctx.calculationProgress.isCancelled) { new RouteResultPreparation().printResults(gctx.ctx, gpxPoints.get(0).loc, gpxPoints.get(gpxPoints.size() - 1).loc, gctx.result); System.out.println(gctx); } if (resultMatcher != null) { - resultMatcher.publish(gctx.calculationCancelled ? null : gctx); + resultMatcher.publish(gctx.ctx.calculationProgress.isCancelled ? null : gctx); } - gctx.calculationDone = true; return gctx; } @@ -365,7 +362,7 @@ public class RoutePlannerFrontEnd { reg.initRouteEncodingRule(0, "highway", RouteResultPreparation.UNMATCHED_HIGHWAY_TYPE); List lastStraightLine = null; GpxPoint straightPointStart = null; - for (int i = 0; i < gpxPoints.size() && !gctx.calculationCancelled; ) { + for (int i = 0; i < gpxPoints.size() && !gctx.ctx.calculationProgress.isCancelled; ) { GpxPoint pnt = gpxPoints.get(i); if (pnt.routeToTarget != null && !pnt.routeToTarget.isEmpty()) { LatLon startPoint = pnt.routeToTarget.get(0).getStartPoint(); @@ -459,7 +456,7 @@ public class RoutePlannerFrontEnd { private void cleanupResultAndAddTurns(GpxRouteApproximation gctx) { // cleanup double joints int LOOK_AHEAD = 4; - for(int i = 0; i < gctx.result.size() && !gctx.calculationCancelled; i++) { + for(int i = 0; i < gctx.result.size() && !gctx.ctx.calculationProgress.isCancelled; i++) { RouteSegmentResult s = gctx.result.get(i); for(int j = i + 2; j <= i + LOOK_AHEAD && j < gctx.result.size(); j++) { RouteSegmentResult e = gctx.result.get(j); @@ -476,7 +473,7 @@ public class RoutePlannerFrontEnd { r.setTurnType(null); r.setDescription(""); } - if (!gctx.calculationCancelled) { + if (!gctx.ctx.calculationProgress.isCancelled) { preparation.prepareTurnResults(gctx.ctx, gctx.result); } } diff --git a/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java b/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java index 9b2ce834b5..1383f4ae4a 100644 --- a/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java +++ b/OsmAnd-java/src/main/java/net/osmand/util/GeoPointParserUtil.java @@ -3,6 +3,8 @@ package net.osmand.util; import java.net.URI; import java.net.URLDecoder; import java.net.URLEncoder; +import java.util.Arrays; +import java.util.Base64; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Locale; @@ -11,6 +13,9 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import net.osmand.data.LatLon; +import net.osmand.util.GeoPointParserUtil.GeoParsedPoint; + public class GeoPointParserUtil { @@ -69,6 +74,31 @@ public class GeoPointParserUtil { } return map; } + + private static int kMaxPointBytes = 10; + private static int kMaxCoordBits = kMaxPointBytes * 3; + public static LatLon decodeMapsMeLatLonToInt(String s) { + // 44TvlEGXf- + int lat = 0, lon = 0; + int shift = kMaxCoordBits - 3; + for (int i = 0; i < s.length(); ++i, shift -= 3) { + int a = net.osmand.osm.io.Base64.indexOf(s.charAt(i)); + if (a < 0) + return null; + + int lat1 = (((a >> 5) & 1) << 2 | ((a >> 3) & 1) << 1 | ((a >> 1) & 1)); + int lon1 = (((a >> 4) & 1) << 2 | ((a >> 2) & 1) << 1 | (a & 1)); + lat |= lat1 << shift; + lon |= lon1 << shift; + } + double middleOfSquare = 1 << (3 * (kMaxPointBytes - s.length()) - 1); + lat += middleOfSquare; + lon += middleOfSquare; + + double dlat = ((double) lat) / ((1 << kMaxCoordBits) - 1) * 180 - 90; + double dlon = ((double) lon) / ((1 << kMaxCoordBits) - 1 + 1) * 360.0 - 180; + return new LatLon(dlat, dlon); + } /** * Parses geo and map intents: @@ -190,6 +220,31 @@ public class GeoPointParserUtil { int zoom = parseZoom(zm); return new GeoParsedPoint(lat, lon, zoom); } + } else if (host.equals("ge0.me")) { + // http:///44TvlEGXf-/Kyiv + if (path.startsWith("/")) { + path = path.substring(1); + } + String[] pms = path.split("/"); + String label = ""; + if (pms.length > 1) { + label = pms[1]; + } + String qry = pms[0]; + if (qry.length() < 10) { + return null; + } + int indZoom = net.osmand.osm.io.Base64.indexOf(qry.charAt(0)); + int zoom = 15; + if (indZoom >= 0) { + zoom = indZoom / 4 + 4; + } + LatLon l = decodeMapsMeLatLonToInt(qry.substring(1).replace('-', '/')); + if (l == null) { + return null; + } + return new GeoParsedPoint(l.getLatitude(), l.getLongitude(), zoom, label); + } else if (simpleDomains.contains(host)) { if (uri.getQuery() == null && params.size() == 0) { // DOUBLE check this may be wrong test of openstreetmap.de (looks very weird url and server doesn't respond) @@ -221,7 +276,6 @@ public class GeoPointParserUtil { String z = String.valueOf(GeoParsedPoint.NO_ZOOM); if (params.containsKey("q")) { - System.out.println("q=" + params.get("q")); Matcher matcher = commaSeparatedPairPattern.matcher(params.get("q")); if (matcher.matches()) { latString = matcher.group(1); diff --git a/OsmAnd-java/src/test/java/net/osmand/util/GeoPointParserUtilTest.java b/OsmAnd-java/src/test/java/net/osmand/util/GeoPointParserUtilTest.java index c869779c4d..2131bebcfd 100644 --- a/OsmAnd-java/src/test/java/net/osmand/util/GeoPointParserUtilTest.java +++ b/OsmAnd-java/src/test/java/net/osmand/util/GeoPointParserUtilTest.java @@ -43,6 +43,13 @@ public class GeoPointParserUtilTest { "https://www.google.co.in/maps/place/data=!3m2!1e3!4b1!4m6!3m5!1s0x0:0x0!7e2!8m2!3d10.1213237!4d76.348392?shorturl=1"); assertGeoPoint(actual, new GeoParsedPoint(10.1213237, 76.348392)); } + + @Test + public void testMapsMeParser() { + GeoParsedPoint actual = GeoPointParserUtil.parse( + "http://ge0.me/44TvlEGXf-/Kyiv"); + assertGeoPoint(actual, new GeoParsedPoint(50.45003, 30.52414, 18, "Kyiv")); + } @Test public void testGeoPoint() { @@ -449,21 +456,21 @@ public class GeoPointParserUtilTest { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint("paris")); - // TODO this URL does not work, where is it used? + // LEGACY this URL does not work, where is it used? // http://maps.google.com/maps/q=loc:34,-106&z=11 url = "http://maps.google.com/maps/q=loc:" + ilat + "," + ilon + "&z=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // TODO this URL does not work, where is it used? + // LEGACY this URL does not work, where is it used? // http://maps.google.com/maps/q=loc:34.99393,-106.61568&z=11 url = "http://maps.google.com/maps/q=loc:" + dlat + "," + dlon + "&z=" + z; System.out.println("url: " + url); actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(dlat, dlon, z)); - // TODO this URL does not work, where is it used? + // LEGACY this URL does not work, where is it used? // whatsapp // http://maps.google.com/maps/q=loc:34,-106 (You) z = GeoParsedPoint.NO_ZOOM; @@ -472,7 +479,7 @@ public class GeoPointParserUtilTest { actual = GeoPointParserUtil.parse(url); assertGeoPoint(actual, new GeoParsedPoint(ilat, ilon, z)); - // TODO this URL does not work, where is it used? + // LEGACY this URL does not work, where is it used? // whatsapp // http://maps.google.com/maps/q=loc:34.99393,-106.61568 (You) z = GeoParsedPoint.NO_ZOOM; diff --git a/OsmAnd/AndroidManifest.xml b/OsmAnd/AndroidManifest.xml index e1508f6ba2..f2d870080b 100644 --- a/OsmAnd/AndroidManifest.xml +++ b/OsmAnd/AndroidManifest.xml @@ -484,6 +484,7 @@ + diff --git a/OsmAnd/res/layout/fragment_measurement_tool.xml b/OsmAnd/res/layout/fragment_measurement_tool.xml index 425717f98a..fe1ba9b1d7 100644 --- a/OsmAnd/res/layout/fragment_measurement_tool.xml +++ b/OsmAnd/res/layout/fragment_measurement_tool.xml @@ -180,7 +180,10 @@ android:ellipsize="end" android:gravity="center_vertical" android:maxLines="1" - android:padding="@dimen/measurement_tool_text_button_padding_small" + android:paddingStart="@dimen/measurement_tool_text_button_padding_small" + android:paddingLeft="@dimen/measurement_tool_text_button_padding_small" + android:paddingEnd="@dimen/measurement_tool_text_button_padding_small" + android:paddingRight="@dimen/measurement_tool_text_button_padding_small" android:text="@string/shared_string_options" android:textColor="?attr/color_dialog_buttons" osmand:typeface="@string/font_roboto_medium"/> diff --git a/OsmAnd/res/values-be/phrases.xml b/OsmAnd/res/values-be/phrases.xml index f3672f5b22..018f7cff3b 100644 --- a/OsmAnd/res/values-be/phrases.xml +++ b/OsmAnd/res/values-be/phrases.xml @@ -3810,7 +3810,7 @@ Труба Сетка папаўнення пітной вадой Папаўненне пітной вадой: не - Папаўненне пітной вадой: так + Так Перашкода Узровень вады: ніжэй сярэдняга ўзроўню Узровень вады: вышэй сярэдняга ўзроўню @@ -3834,4 +3834,8 @@ Так Цэнтр дайвінгу Паляўнічая база + Папаўненне пітной вады + Так + Расклад адпраўленняў: не + Расклад адпраўленняў \ No newline at end of file diff --git a/OsmAnd/res/values-pt-rBR/phrases.xml b/OsmAnd/res/values-pt-rBR/phrases.xml index 08c57f9a39..4a969baf22 100644 --- a/OsmAnd/res/values-pt-rBR/phrases.xml +++ b/OsmAnd/res/values-pt-rBR/phrases.xml @@ -3815,7 +3815,7 @@ Nível de água: acima do nível médio da água Nível de água: abaixo do nível médio da água Obstrução - Recarga de água potável: sim + Sim Recarga de água potável: não Rede de recarga de água potável Sucção @@ -3834,4 +3834,11 @@ Burgo Flecha: não Elevador + Calendário + Demora + Tempo real + Sim + Quadro de partidas: não + Quadro de partidas + Recarga de água potável \ No newline at end of file diff --git a/OsmAnd/res/values-ru/phrases.xml b/OsmAnd/res/values-ru/phrases.xml index 5799269936..ffdab949ff 100644 --- a/OsmAnd/res/values-ru/phrases.xml +++ b/OsmAnd/res/values-ru/phrases.xml @@ -3730,7 +3730,7 @@ Только если разрешена ходьба Сеть заправки питьевой воды Заправка питьевой водой: нет - Заправка питьевой водой: да + Да Тип 3 Тип 2 комбинированный Тип 2 @@ -3822,4 +3822,8 @@ Подарочная коробка Стрелка: нет Лифт + Да + Расписание отправлений: нет + Расписание отправлений + Заправка питьевой воды \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rTW/phrases.xml b/OsmAnd/res/values-zh-rTW/phrases.xml index 6c2fe92bb8..f65ebd2d68 100644 --- a/OsmAnd/res/values-zh-rTW/phrases.xml +++ b/OsmAnd/res/values-zh-rTW/phrases.xml @@ -3814,7 +3814,7 @@ 水位:高於平均水位 水位:低於平均水位 堵塞 - 飲用水填充:是 + 飲用水填充:否 飲用水填充網路 吸力 @@ -3833,4 +3833,11 @@ 自治市鎮 箭頭:否 電梯 + 時刻表 + 即時 + 間隔時間 + + 時刻表:否 + 時刻表 + 飲用水補充 \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index ae510a0ab3..5a7f1cf925 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -11,6 +11,15 @@ Thx - Hardy --> + + • Updated "Plan Route" mode allows using different navigation types for each segment and attaches any track to the roads\n\n + • New "Appearance" options for tracks: select color, thickness turn on the direction arrows and start/finish marks\n\n + • Improved bicycle nodes visibility\n\n + • Context menu for tracks with basic info\n\n + • Improved "Search" algorithms\n\n + • Improved "Follow track" options in Navigation\n\n + • Fixed issues with import/export of profile settings\n\n + Redo Please add at least two points. is saved diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 7bccdd599f..2837bff6f8 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -103,7 +103,7 @@ public class AppInitializer implements IProgress { private static final String VECTOR_INDEXES_CHECK = "VECTOR_INDEXES_CHECK"; //$NON-NLS-1$ private static final String EXCEPTION_FILE_SIZE = "EXCEPTION_FS"; //$NON-NLS-1$ - public static final String LATEST_CHANGES_URL = "https://osmand.net/blog/osmand-3-7-released"; + public static final String LATEST_CHANGES_URL = "https://osmand.net/blog/osmand-3-8-released"; // public static final String LATEST_CHANGES_URL = null; // not enough to read public static final int APP_EXIT_CODE = 4; public static final String APP_EXIT_KEY = "APP_EXIT_KEY"; diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index 8281a127e4..7217e8af5f 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -9,6 +9,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; +import net.osmand.CallbackWithObject; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXTrackAnalysis; @@ -19,6 +20,7 @@ import net.osmand.GPXUtilities.WptPt; import net.osmand.IProgress; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; +import net.osmand.StateChangedListener; import net.osmand.data.LatLon; import net.osmand.plus.GPXDatabase.GpxDataItem; import net.osmand.plus.MapMarkersHelper.MapMarkersGroup; @@ -26,6 +28,7 @@ import net.osmand.plus.activities.SavingTrackHelper; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; +import net.osmand.plus.routing.RouteProvider; import net.osmand.plus.settings.backend.OsmandSettings.MetricsConstants; import net.osmand.plus.track.GpxSplitType; import net.osmand.plus.track.GradientScaleType; @@ -40,6 +43,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -48,6 +52,8 @@ import java.util.Set; public class GpxSelectionHelper { + private final static Log LOG = PlatformUtil.getLog(GpxSelectionHelper.class); + public static final String CURRENT_TRACK = "currentTrack"; private static final String FILE = "file"; private static final String BACKUP = "backup"; @@ -61,15 +67,18 @@ public class GpxSelectionHelper { private OsmandApplication app; @NonNull - private List selectedGPXFiles = new java.util.ArrayList<>(); - private Map selectedGpxFilesBackUp = new java.util.HashMap<>(); + private List selectedGPXFiles = new ArrayList<>(); + private Map selectedGpxFilesBackUp = new HashMap<>(); private SavingTrackHelper savingTrackHelper; - private final static Log LOG = PlatformUtil.getLog(GpxSelectionHelper.class); private SelectGpxTask selectGpxTask; + private SelectedGpxFile trackToFollow; + private StateChangedListener followTrackListener; + private boolean shouldHideTrackToFollow; - public GpxSelectionHelper(OsmandApplication osmandApplication, SavingTrackHelper trackHelper) { - this.app = osmandApplication; + public GpxSelectionHelper(OsmandApplication app, SavingTrackHelper trackHelper) { + this.app = app; savingTrackHelper = trackHelper; + app.getSettings().FOLLOW_THE_GPX_ROUTE.addListener(getFollowTrackListener()); } public void clearAllGpxFilesToShow(boolean backupSelection) { @@ -86,10 +95,18 @@ public class GpxSelectionHelper { public void restoreSelectedGpxFiles() { for (Entry gpxEntry : selectedGpxFilesBackUp.entrySet()) { if (!Algorithms.isEmpty(gpxEntry.getKey().path)) { - final File file = new File(gpxEntry.getKey().path); + File file = new File(gpxEntry.getKey().path); if (file.exists() && !file.isDirectory()) { if (file.lastModified() > gpxEntry.getValue()) { - new GpxFileLoaderTask(file, app).execute(); + new GpxFileLoaderTask(file, new CallbackWithObject() { + @Override + public boolean processResult(GPXFile result) { + if (result != null) { + selectGpxFile(result, true, false); + } + return true; + } + }).execute(); } else { selectGpxFile(gpxEntry.getKey(), true, false); } @@ -99,14 +116,52 @@ public class GpxSelectionHelper { } } + public boolean shouldHideTrackToFollow() { + return shouldHideTrackToFollow; + } + + private StateChangedListener getFollowTrackListener() { + if (followTrackListener == null) { + followTrackListener = new StateChangedListener() { + @Override + public void stateChanged(String gpxRoutePath) { + if (trackToFollow != null) { + if (shouldHideTrackToFollow) { + selectGpxFile(trackToFollow.getGpxFile(), false, false); + shouldHideTrackToFollow = false; + } + trackToFollow = null; + } + if (!Algorithms.isEmpty(gpxRoutePath)) { + trackToFollow = getSelectedFileByPath(gpxRoutePath); + if (trackToFollow == null) { + shouldHideTrackToFollow = true; + File file = new File(gpxRoutePath); + if (file.exists() && !file.isDirectory()) { + new GpxFileLoaderTask(file, new CallbackWithObject() { + @Override + public boolean processResult(GPXFile result) { + trackToFollow = selectGpxFile(result, true, false); + return true; + } + }).execute(); + } + } + } + } + }; + } + return followTrackListener; + } + private static class GpxFileLoaderTask extends AsyncTask { - File fileToLoad; - GpxSelectionHelper helper; + private File fileToLoad; + private CallbackWithObject callback; - GpxFileLoaderTask(File fileToLoad, OsmandApplication app) { + GpxFileLoaderTask(File fileToLoad, CallbackWithObject callback) { this.fileToLoad = fileToLoad; - this.helper = app.getSelectedGpxHelper(); + this.callback = callback; } @Override @@ -116,8 +171,8 @@ public class GpxSelectionHelper { @Override protected void onPostExecute(GPXFile gpxFile) { - if (gpxFile != null) { - helper.selectGpxFile(gpxFile, true, false); + if (callback != null) { + callback.processResult(gpxFile); } } } @@ -875,7 +930,13 @@ public class GpxSelectionHelper { this.displayGroups = displayGroups; } - + public boolean isFollowTrack(OsmandApplication app) { + RouteProvider.GPXRouteParamsBuilder routeParams = app.getRoutingHelper().getCurrentGPXRoute(); + if (routeParams != null) { + return gpxFile.path.equals(routeParams.getFile().path); + } + return false; + } } public enum GpxDisplayItemType { diff --git a/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java b/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java index d47eb92724..d898505b76 100644 --- a/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java +++ b/OsmAnd/src/net/osmand/plus/base/FailSafeFuntions.java @@ -14,13 +14,13 @@ import net.osmand.GPXUtilities.GPXFile; import net.osmand.PlatformUtil; import net.osmand.data.LatLon; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.settings.backend.OsmandSettings; import org.apache.commons.logging.Log; @@ -161,9 +161,8 @@ public class FailSafeFuntions { OsmandApplication app = ma.getMyApplication(); ma.getMapViewTrackingUtilities().backToLocationImpl(); RoutingHelper routingHelper = app.getRoutingHelper(); - if(gpxRoute == null) { - app.getSettings().FOLLOW_THE_GPX_ROUTE.set(null); - } + app.getSettings().FOLLOW_THE_GPX_ROUTE.set(gpxRoute != null ? gpxRoute.getFile().path : null); + routingHelper.setGpxParams(gpxRoute); if (app.getTargetPointsHelper().getPointToStart() == null) { app.getTargetPointsHelper().setStartPoint(null, false, null); diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java index b138bee19f..afb6319e41 100644 --- a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/BottomSheetItemWithDescription.java @@ -53,6 +53,7 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { public void setDescription(CharSequence description) { this.description = description; descriptionTv.setText(description); + changeDescriptionVisibility(); } public void setDescriptionMaxLines(int maxLines) { @@ -76,11 +77,7 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { super.inflate(context, container, nightMode); descriptionTv = view.findViewById(R.id.description); if (descriptionTv != null) { - if (Algorithms.isEmpty(description)) { - descriptionTv.setVisibility(View.GONE); - } else { - descriptionTv.setVisibility(View.VISIBLE); - } + changeDescriptionVisibility(); descriptionTv.setText(description); if (descriptionColorId != INVALID_ID) { descriptionTv.setTextColor(ContextCompat.getColor(context, descriptionColorId)); @@ -94,6 +91,14 @@ public class BottomSheetItemWithDescription extends SimpleBottomSheetItem { } } + private void changeDescriptionVisibility() { + if (Algorithms.isEmpty(description)) { + descriptionTv.setVisibility(View.GONE); + } else { + descriptionTv.setVisibility(View.VISIBLE); + } + } + public static class Builder extends SimpleBottomSheetItem.Builder { protected CharSequence description; diff --git a/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java b/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java index 791f131de1..523fdb6416 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/WhatsNewDialogFragment.java @@ -30,7 +30,7 @@ public class WhatsNewDialogFragment extends DialogFragment { final OsmandApplication osmandApplication = (OsmandApplication) getActivity().getApplication(); final String appVersion = Version.getAppVersion(osmandApplication); builder.setTitle(getString(R.string.whats_new) + " " + appVersion) - .setMessage(getString(R.string.release_3_7)) + .setMessage(getString(R.string.release_3_8)) .setNegativeButton(R.string.shared_string_close, null); if (AppInitializer.LATEST_CHANGES_URL != null) { builder.setPositiveButton(R.string.read_more, new DialogInterface.OnClickListener() { diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 3bbc3214d1..1a15477e06 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -4,20 +4,16 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; -import android.text.Editable; -import android.text.TextWatcher; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; @@ -27,8 +23,6 @@ import android.widget.Toast; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.SwitchCompat; import androidx.core.content.ContextCompat; import androidx.core.widget.TextViewCompat; import androidx.fragment.app.Fragment; @@ -40,13 +34,11 @@ import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.snackbar.Snackbar; import net.osmand.AndroidUtils; -import net.osmand.FileUtils; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.Track; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.GPXUtilities.WptPt; -import net.osmand.IndexConstants; import net.osmand.LocationsHolder; import net.osmand.data.LatLon; import net.osmand.data.QuadRect; @@ -100,6 +92,7 @@ import java.util.List; import java.util.Locale; import static net.osmand.IndexConstants.GPX_FILE_EXT; +import static net.osmand.IndexConstants.GPX_INDEX_DIR; import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode; import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener; import static net.osmand.plus.measurementtool.SaveAsNewTrackBottomSheetDialogFragment.SaveAsNewTrackFragmentListener; @@ -156,7 +149,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route LINE } - private enum SaveAction { + private enum FinalSaveAction { SHOW_SNACK_BAR_AND_CLOSE, SHOW_TOAST, SHOW_IS_SAVED_FRAGMENT @@ -419,7 +412,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route toolBarController.setOnSaveViewClickListener(new OnClickListener() { @Override public void onClick(View v) { - saveChanges(SaveAction.SHOW_SNACK_BAR_AND_CLOSE); + saveChanges(FinalSaveAction.SHOW_SNACK_BAR_AND_CLOSE, false); } }); updateToolbar(); @@ -623,17 +616,19 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - public void saveChanges(SaveAction saveAction) { + public void saveChanges(FinalSaveAction finalSaveAction, boolean showDialog) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { if (editingCtx.getPointsCount() > 0) { GpxData gpxData = editingCtx.getGpxData(); - if (editingCtx.isNewData()) { - saveAsGpx(SaveType.ROUTE_POINT, saveAction); - } else if (isInEditMode() && gpxData.getActionType() == ActionType.EDIT_SEGMENT) { - openSaveAsNewTrackMenu(mapActivity); + if (editingCtx.isNewData() || (isInEditMode() && gpxData.getActionType() == ActionType.EDIT_SEGMENT)) { + if (showDialog) { + openSaveAsNewTrackMenu(mapActivity); + } else { + saveNewGpx(null, getSuggestedFileName(), true, false, finalSaveAction); + } } else { - addToGpx(mapActivity, saveAction); + addToGpx(mapActivity, finalSaveAction); } } else { Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show(); @@ -748,7 +743,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void saveChangesOnClick() { - saveChanges(SaveAction.SHOW_TOAST); + saveChanges(FinalSaveAction.SHOW_TOAST, true); } @Override @@ -912,7 +907,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onChangeApplicationMode(ApplicationMode mode, RouteBetweenPointsDialogType dialogType, - RouteBetweenPointsDialogMode dialogMode) { + RouteBetweenPointsDialogMode dialogMode) { MeasurementToolLayer measurementLayer = getMeasurementLayer(); if (measurementLayer != null) { ChangeRouteType changeRouteType = ChangeRouteType.NEXT_SEGMENT; @@ -988,8 +983,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (selectedGpxFile != null) { gpxFile = selectedGpxFile.getGpxFile(); } else { - gpxFile = GPXUtilities.loadGPXFile(new File( - getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR), gpxFileName)); + gpxFile = GPXUtilities.loadGPXFile(new File(app.getAppPath(GPX_INDEX_DIR), gpxFileName)); } } @@ -1012,7 +1006,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route .getSelectedFileByPath(gpxFile.path); boolean showOnMap = selectedGpxFile != null; saveExistingGpx(gpxFile, showOnMap, ActionType.ADD_SEGMENT, - editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, SaveAction.SHOW_TOAST); + editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, FinalSaveAction.SHOW_TOAST); } } @@ -1050,13 +1044,21 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route @Override public void onSaveAsNewTrack(String folderName, String fileName, boolean showOnMap, boolean simplifiedTrack) { - File dir = getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR); - if (folderName != null) { - dir = new File(dir, folderName); + saveNewGpx(folderName, fileName, showOnMap, simplifiedTrack, FinalSaveAction.SHOW_IS_SAVED_FRAGMENT); + } + + private void saveNewGpx(String folderName, String fileName, boolean showOnMap, boolean simplifiedTrack, + FinalSaveAction finalSaveAction) { + OsmandApplication app = getMyApplication(); + if (app != null) { + File dir = getMyApplication().getAppPath(GPX_INDEX_DIR); + if (folderName != null) { + dir = new File(dir, folderName); + } + fileName += GPX_FILE_EXT; + SaveType saveType = simplifiedTrack ? SaveType.LINE : SaveType.ROUTE_POINT; + saveNewGpx(dir, fileName, showOnMap, saveType, finalSaveAction); } - fileName = fileName + GPX_FILE_EXT; - SaveType saveType = simplifiedTrack ? SaveType.LINE : SaveType.ROUTE_POINT; - saveNewGpx(dir, fileName, showOnMap, saveType, SaveAction.SHOW_IS_SAVED_FRAGMENT); } private MeasurementAdapterListener createMeasurementAdapterListener(final ItemTouchHelper touchHelper) { @@ -1183,7 +1185,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (mapActivity != null) { if (editingCtx.getPointsCount() > 0) { SaveAsNewTrackBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), - this, getSuggestedFileName()); + this, "", getSuggestedFileName(), true, true); } else { Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show(); } @@ -1450,7 +1452,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route } } - private void addToGpx(MapActivity mapActivity, SaveAction saveAction) { + private void addToGpx(MapActivity mapActivity, FinalSaveAction finalSaveAction) { GpxData gpxData = editingCtx.getGpxData(); GPXFile gpx = gpxData != null ? gpxData.getGpxFile() : null; if (gpx != null) { @@ -1458,84 +1460,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedFileByPath(gpx.path); boolean showOnMap = selectedGpxFile != null; saveExistingGpx(gpx, showOnMap, gpxData.getActionType(), - editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, saveAction); - } - } - - private void saveAsGpx(final SaveType saveType, final SaveAction saveAction) { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR); - final View view = UiUtilities.getInflater(mapActivity, nightMode).inflate(R.layout.save_gpx_dialog, null); - final EditText nameEt = (EditText) view.findViewById(R.id.gpx_name_et); - final TextView warningTextView = (TextView) view.findViewById(R.id.file_exists_text_view); - final View buttonView = view.findViewById(R.id.button_view); - final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map); - UiUtilities.setupCompoundButton(showOnMapToggle, nightMode, UiUtilities.CompoundButtonType.GLOBAL); - buttonView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - showOnMapToggle.setChecked(!showOnMapToggle.isChecked()); - } - }); - showOnMapToggle.setChecked(true); - - String displayedName = getSuggestedFileName(); - nameEt.setText(displayedName); - nameEt.setSelection(displayedName.length()); - final boolean[] textChanged = new boolean[1]; - - AlertDialog.Builder builder = new AlertDialog.Builder(UiUtilities.getThemedContext(mapActivity, nightMode)) - .setTitle(R.string.enter_gpx_name) - .setView(view) - .setPositiveButton(R.string.shared_string_save, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - final String name = nameEt.getText().toString(); - String fileName = name + GPX_FILE_EXT; - if (textChanged[0]) { - File fout = new File(dir, fileName); - int ind = 1; - while (fout.exists()) { - fileName = name + "_" + (++ind) + GPX_FILE_EXT; - fout = new File(dir, fileName); - } - } - saveNewGpx(dir, fileName, showOnMapToggle.isChecked(), saveType, saveAction); - } - }) - .setNegativeButton(R.string.shared_string_cancel, null); - final AlertDialog dialog = builder.create(); - dialog.show(); - - nameEt.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { - - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - - } - - @Override - public void afterTextChanged(Editable editable) { - if (new File(dir, editable.toString() + GPX_FILE_EXT).exists()) { - warningTextView.setVisibility(View.VISIBLE); - warningTextView.setText(R.string.file_with_name_already_exists); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); - } else if (editable.toString().trim().isEmpty()) { - warningTextView.setVisibility(View.VISIBLE); - warningTextView.setText(R.string.enter_the_file_name); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); - } else { - warningTextView.setVisibility(View.INVISIBLE); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); - } - textChanged[0] = true; - } - }); + editingCtx.hasRoute() ? SaveType.ROUTE_POINT : SaveType.LINE, finalSaveAction); } } @@ -1547,7 +1472,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route displayedName = suggestedName; OsmandApplication app = getMyApplication(); if (app != null) { - File dir = app.getAppPath(IndexConstants.GPX_INDEX_DIR); + File dir = app.getAppPath(GPX_INDEX_DIR); File fout = new File(dir, suggestedName + GPX_FILE_EXT); int ind = 0; while (fout.exists()) { @@ -1561,13 +1486,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route return displayedName; } - private void saveNewGpx(File dir, String fileName, boolean showOnMap, SaveType saveType, SaveAction saveAction) { - saveGpx(dir, fileName, showOnMap, null, null, saveType, saveAction); + private void saveNewGpx(File dir, String fileName, boolean showOnMap, SaveType saveType, FinalSaveAction finalSaveAction) { + saveGpx(dir, fileName, showOnMap, null, null, saveType, finalSaveAction); } private void saveExistingGpx(GPXFile gpx, boolean showOnMap, ActionType actionType, SaveType saveType, - SaveAction saveAction) { - saveGpx(null, null, showOnMap, gpx, actionType, saveType, saveAction); + FinalSaveAction finalSaveAction) { + saveGpx(null, null, showOnMap, gpx, actionType, saveType, finalSaveAction); } @SuppressLint("StaticFieldLeak") @@ -1577,7 +1502,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route final GPXFile gpxFile, final ActionType actionType, final SaveType saveType, - final SaveAction saveAction) { + final FinalSaveAction finalSaveAction) { new AsyncTask() { @@ -1748,25 +1673,13 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route if (isInEditMode()) { dismiss(mapActivity); } else { - switch (saveAction) { + switch (finalSaveAction) { case SHOW_SNACK_BAR_AND_CLOSE: final WeakReference mapActivityRef = new WeakReference<>(mapActivity); snackbar = Snackbar.make(mapActivity.getLayout(), MessageFormat.format(getString(R.string.gpx_saved_sucessfully), toSave.getName()), Snackbar.LENGTH_LONG) - .setAction(R.string.shared_string_rename, new OnClickListener() { - @Override - public void onClick(View view) { - MapActivity mapActivity = mapActivityRef.get(); - if (AndroidUtils.isActivityNotDestroyed(mapActivity)) { - FileUtils.renameFile(mapActivity, toSave, new FileUtils.RenameCallback() { - @Override - public void renamedTo(File file) { - } - }); - } - } - }); + .setAction(R.string.shared_string_rename, getRenameListener(mapActivityRef)); snackbar.getView().findViewById(com.google.android.material.R.id.snackbar_action) .setAllCaps(false); UiUtilities.setupSnackbar(snackbar, nightMode); @@ -1790,6 +1703,22 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route Toast.makeText(mapActivity, warning.getMessage(), Toast.LENGTH_LONG).show(); } } + + private OnClickListener getRenameListener(final WeakReference mapActivityRef) { + return new OnClickListener() { + @Override + public void onClick(View view) { + MapActivity mapActivity = mapActivityRef.get(); + String parentFolder = toSave.getParentFile().getName(); + if (GPX_INDEX_DIR.equals(parentFolder + File.separator)) { + parentFolder = null; + } + SaveAsNewTrackBottomSheetDialogFragment.showInstance( + mapActivity.getSupportFragmentManager(), null, parentFolder, + AndroidUtils.trimExtension(toSave.getName()), false, showOnMap); + } + }; + } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -2050,8 +1979,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route layoutParams.leftMargin = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_large); layoutParams.rightMargin = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_large); int paddingH = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_large); - int paddingV = ctx.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_small); - done.setPadding(paddingH, paddingV, paddingH, paddingV); + done.setPadding(paddingH, done.getPaddingTop(), paddingH, done.getPaddingBottom()); AndroidUtils.setBackground(ctx, done, nightMode, R.drawable.purchase_dialog_outline_btn_bg_light, R.drawable.purchase_dialog_outline_btn_bg_dark); } diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java index d786417301..0355bba809 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SaveAsNewTrackBottomSheetDialogFragment.java @@ -2,11 +2,13 @@ package net.osmand.plus.measurementtool; import android.content.res.ColorStateList; import android.graphics.Color; +import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -19,6 +21,8 @@ import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities; +import net.osmand.IndexConstants; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; @@ -33,6 +37,8 @@ import net.osmand.plus.measurementtool.adapter.FolderListAdapter; import org.apache.commons.logging.Log; +import java.io.File; + public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFragment { public static final String TAG = SaveAsNewTrackBottomSheetDialogFragment.class.getSimpleName(); @@ -41,12 +47,18 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial public static final String SIMPLIFIED_TRACK_KEY = "simplified_track_key"; public static final String FOLDER_NAME_KEY = "folder_name_key"; public static final String FILE_NAME_KEY = "file_name_key"; + public static final String SOURCE_FILE_NAME_KEY = "source_file_name_key"; + public static final String SOURCE_FOLDER_NAME_KEY = "source_folder_name_key"; + public static final String SHOW_SIMPLIFIED_BUTTON_KEY = "show_simplified_button_key"; private boolean showOnMap; private boolean simplifiedTrack; private String fileName; + private String sourceFileName; + private String sourceFolderName; private String folderName; private boolean rightButtonEnabled = true; + private boolean showSimplifiedButton = true; @Override public void createMenuItems(Bundle savedInstanceState) { @@ -59,9 +71,12 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial simplifiedTrack = savedInstanceState.getBoolean(SIMPLIFIED_TRACK_KEY); folderName = savedInstanceState.getString(FOLDER_NAME_KEY); fileName = savedInstanceState.getString(FILE_NAME_KEY); + sourceFileName = savedInstanceState.getString(SOURCE_FILE_NAME_KEY); + sourceFolderName = savedInstanceState.getString(SOURCE_FOLDER_NAME_KEY); + showSimplifiedButton = savedInstanceState.getBoolean(SHOW_SIMPLIFIED_BUTTON_KEY); } - items.add(new TitleItem(getString(R.string.shared_string_save_as_gpx))); + items.add(new TitleItem(getString(R.string.save_as_new_track))); View editNameView = View.inflate(UiUtilities.getThemedContext(app, nightMode), R.layout.track_name_edit_text, null); @@ -113,46 +128,38 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial items.add(new DividerSpaceItem(app, app.getResources().getDimensionPixelSize(R.dimen.dialog_content_margin))); } + int activeColorRes = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light; - int backgroundColor = AndroidUtils.getColorFromAttr(UiUtilities.getThemedContext(app, nightMode), - R.attr.activity_background_color); - GradientDrawable background = (GradientDrawable) AppCompatResources.getDrawable(app, - R.drawable.bg_select_group_button_outline); - if (background != null) { - background = (GradientDrawable) background.mutate(); - background.setStroke(0, Color.TRANSPARENT); - background.setColor(backgroundColor); - } - final BottomSheetItemWithCompoundButton[] simplifiedTrackItem = new BottomSheetItemWithCompoundButton[1]; - simplifiedTrackItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() - .setChecked(simplifiedTrack) - .setCompoundButtonColorId(activeColorRes) - .setDescription(getString(R.string.simplified_track_description)) - .setBackground(background) - .setTitle(getString(R.string.simplified_track)) - .setLayoutId(R.layout.bottom_sheet_item_with_switch_and_descr) - .setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - simplifiedTrack = !simplifiedTrack; - simplifiedTrackItem[0].setChecked(simplifiedTrack); - } - }) - .create(); - items.add(simplifiedTrackItem[0]); - items.add(new DividerSpaceItem(app, app.getResources().getDimensionPixelSize(R.dimen.content_padding))); + if (showSimplifiedButton) { + final BottomSheetItemWithCompoundButton[] simplifiedTrackItem = new BottomSheetItemWithCompoundButton[1]; + simplifiedTrackItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() + .setChecked(simplifiedTrack) + .setCompoundButtonColorId(activeColorRes) + .setDescription(getSimplifiedTrackDescription()) + .setBackground(getBackground(simplifiedTrack)) + .setTitle(getString(R.string.simplified_track)) + .setLayoutId(R.layout.bottom_sheet_item_with_switch_and_descr) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + simplifiedTrack = !simplifiedTrack; + simplifiedTrackItem[0].setChecked(simplifiedTrack); + AndroidUtils.setBackground(simplifiedTrackItem[0].getView(), getBackground(simplifiedTrack)); + simplifiedTrackItem[0].setDescription(getSimplifiedTrackDescription()); + } + }) + .create(); + items.add(simplifiedTrackItem[0]); - background = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline); - if (background != null) { - background = (GradientDrawable) background.mutate(); - background.setStroke(app.getResources().getDimensionPixelSize(R.dimen.map_button_stroke), backgroundColor); + items.add(new DividerSpaceItem(app, app.getResources().getDimensionPixelSize(R.dimen.content_padding))); } + final BottomSheetItemWithCompoundButton[] showOnMapItem = new BottomSheetItemWithCompoundButton[1]; showOnMapItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder() .setCompoundButtonColorId(activeColorRes) .setChecked(showOnMap) - .setBackground(background) + .setBackground(getBackground(showOnMap)) .setTitle(getString(R.string.shared_string_show_on_map)) .setLayoutId(R.layout.bottom_sheet_item_with_switch_and_descr) .setOnClickListener(new View.OnClickListener() { @@ -160,6 +167,7 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial public void onClick(View v) { showOnMap = !showOnMap; showOnMapItem[0].setChecked(showOnMap); + AndroidUtils.setBackground(showOnMapItem[0].getView(), getBackground(showOnMap)); } }) .create(); @@ -168,6 +176,31 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial items.add(new DividerSpaceItem(app, contentPaddingSmall)); } + private String getSimplifiedTrackDescription() { + return simplifiedTrack ? getString(R.string.simplified_track_description) : ""; + } + + private Drawable getBackground(boolean checked) { + OsmandApplication app = getMyApplication(); + if (app != null) { + GradientDrawable background = (GradientDrawable) AppCompatResources.getDrawable(app, + R.drawable.bg_select_group_button_outline); + if (background != null) { + int backgroundColor = AndroidUtils.getColorFromAttr(UiUtilities.getThemedContext(app, nightMode), + R.attr.activity_background_color); + background = (GradientDrawable) background.mutate(); + if (checked) { + background.setStroke(0, Color.TRANSPARENT); + background.setColor(backgroundColor); + } else { + background.setStroke(app.getResources().getDimensionPixelSize(R.dimen.map_button_stroke), backgroundColor); + } + } + return background; + } + return null; + } + private FolderListAdapter.FolderListAdapterListener createFolderSelectListener() { return new FolderListAdapter.FolderListAdapterListener() { @Override @@ -183,15 +216,23 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial outState.putBoolean(SIMPLIFIED_TRACK_KEY, simplifiedTrack); outState.putString(FOLDER_NAME_KEY, folderName); outState.putString(FILE_NAME_KEY, fileName); + outState.putString(SOURCE_FILE_NAME_KEY, sourceFileName); + outState.putString(SOURCE_FOLDER_NAME_KEY, sourceFolderName); + outState.putBoolean(SHOW_SIMPLIFIED_BUTTON_KEY, showSimplifiedButton); super.onSaveInstanceState(outState); } - public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, String fileName) { + public static void showInstance(@NonNull FragmentManager fm, @Nullable Fragment targetFragment, String folderName, + String fileName, boolean showSimplifiedButton, boolean showOnMap) { try { if (!fm.isStateSaved()) { SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment(); fragment.setTargetFragment(targetFragment, 0); fragment.fileName = fileName; + fragment.sourceFileName = fileName; + fragment.sourceFolderName = folderName; + fragment.showSimplifiedButton = showSimplifiedButton; + fragment.showOnMap = showOnMap; fragment.show(fm, TAG); } } catch (RuntimeException e) { @@ -210,10 +251,45 @@ public class SaveAsNewTrackBottomSheetDialogFragment extends MenuBottomSheetDial if (targetFragment instanceof SaveAsNewTrackFragmentListener) { ((SaveAsNewTrackFragmentListener) targetFragment).onSaveAsNewTrack(folderName, fileName, showOnMap, simplifiedTrack); + } else { + renameFile(); } dismiss(); } + private void renameFile() { + OsmandApplication app = getMyApplication(); + if (app != null) { + File dir = getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR); + File source = dir; + if (sourceFolderName != null) { + source = new File(dir, sourceFolderName); + } + source = new File(source, sourceFileName + IndexConstants.GPX_FILE_EXT); + File dest = dir; + if (folderName != null) { + dest = new File(dir, folderName); + } + dest = new File(dest, fileName + IndexConstants.GPX_FILE_EXT); + if (!source.equals(dest)) { + if (dest.exists()) { + Toast.makeText(app, R.string.file_with_name_already_exists, Toast.LENGTH_LONG).show(); + } else { + if (source.renameTo(dest)) { + app.getGpxDbHelper().rename(source, dest); + } else { + Toast.makeText(app, R.string.file_can_not_be_moved, Toast.LENGTH_LONG).show(); + } + } + } + GPXUtilities.GPXFile gpxFile = GPXUtilities.loadGPXFile(dest); + if (gpxFile.error != null) { + return; + } + app.getSelectedGpxHelper().selectGpxFile(gpxFile, showOnMap, false); + } + } + @Override protected boolean isRightBottomButtonEnabled() { return rightButtonEnabled; diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java index 0f1920c7e6..d20dfa8a52 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SelectFileBottomSheet.java @@ -120,12 +120,13 @@ public class SelectFileBottomSheet extends BottomSheetBehaviourDialogFragment { adapter.setAdapterListener(new OnItemClickListener() { @Override public void onItemClick(int position) { - if (position != RecyclerView.NO_POSITION && position < allGpxList.size()) { + List gpxList = adapter.getGpxInfoList(); + if (position != RecyclerView.NO_POSITION && position < gpxList.size()) { String fileName; if (isShowCurrentGpx() && position == 0) { fileName = null; } else { - fileName = allGpxList.get(position).getFileName(); + fileName = gpxList.get(position).getFileName(); } if (listener != null) { listener.selectFileOnCLick(fileName); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java index 54747b068e..12346bcf12 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/FollowTrackFragment.java @@ -27,7 +27,9 @@ import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.TrkSegment; import net.osmand.IndexConstants; import net.osmand.PlatformUtil; +import net.osmand.ValueHolder; import net.osmand.data.QuadRect; +import net.osmand.data.RotatedTileBox; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; @@ -55,6 +57,7 @@ import net.osmand.plus.routepreparationmenu.cards.ReverseTrackCard; import net.osmand.plus.routepreparationmenu.cards.SelectTrackCard; import net.osmand.plus.routepreparationmenu.cards.TrackEditCard; import net.osmand.plus.routepreparationmenu.cards.TracksToFollowCard; +import net.osmand.plus.routing.IRouteInformationListener; import net.osmand.plus.routing.RouteProvider; import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder; import net.osmand.plus.routing.RoutingHelper; @@ -66,7 +69,7 @@ import java.io.File; import java.util.List; -public class FollowTrackFragment extends ContextMenuScrollFragment implements CardListener { +public class FollowTrackFragment extends ContextMenuScrollFragment implements CardListener, IRouteInformationListener { public static final String TAG = FollowTrackFragment.class.getName(); @@ -264,12 +267,14 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca @Override public void onResume() { super.onResume(); + app.getRoutingHelper().addListener(this); MapRouteInfoMenu.followTrackVisible = true; } @Override public void onPause() { super.onPause(); + app.getRoutingHelper().removeListener(this); MapRouteInfoMenu.followTrackVisible = false; } @@ -293,10 +298,56 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca updateStatusBarColor(); } + @Override + protected int applyPosY(int currentY, boolean needCloseMenu, boolean needMapAdjust, int previousMenuState, int newMenuState, int dZoom, boolean animated) { + int y = super.applyPosY(currentY, needCloseMenu, needMapAdjust, previousMenuState, newMenuState, dZoom, animated); + if (needMapAdjust) { + adjustMapPosition(y); + } + return y; + } + + private void adjustMapPosition(int y) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity == null) { + return; + } + + RoutingHelper rh = app.getRoutingHelper(); + if (rh.isRoutePlanningMode() && mapActivity.getMapView() != null) { + QuadRect rect = mapActivity.getMapRouteInfoMenu().getRouteRect(mapActivity); + + if (gpxFile != null) { + QuadRect gpxRect = gpxFile.getRect(); + + rect.left = Math.min(rect.left, gpxRect.left); + rect.right = Math.max(rect.right, gpxRect.right); + rect.top = Math.max(rect.top, gpxRect.top); + rect.bottom = Math.min(rect.bottom, gpxRect.bottom); + } + + RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy(); + int tileBoxWidthPx = 0; + int tileBoxHeightPx = 0; + + if (!isPortrait()) { + tileBoxWidthPx = tb.getPixWidth() - getWidth(); + } else { + int fHeight = getViewHeight() - y - AndroidUtils.getStatusBarHeight(app); + tileBoxHeightPx = tb.getPixHeight() - fHeight; + } + if (rect.left != 0 && rect.right != 0) { + mapActivity.getMapView().fitRectToMap(rect.left, rect.right, rect.top, rect.bottom, + tileBoxWidthPx, tileBoxHeightPx, 0); + } + } + } + @Override public void onDestroyView() { super.onDestroyView(); exitTrackAppearanceMode(); + onDismiss(); } @Override @@ -554,4 +605,36 @@ public class FollowTrackFragment extends ContextMenuScrollFragment implements Ca log.error(e); } } + + private void onDismiss() { + try { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + if (!mapActivity.isChangingConfigurations()) { + mapActivity.getMapRouteInfoMenu().cancelSelectionFromTracks(); + } + mapActivity.getMapLayers().getMapControlsLayer().showRouteInfoControlDialog(); + } + } catch (Exception e) { + log.error(e); + } + } + + @Override + public void newRouteIsCalculated(boolean newRoute, ValueHolder showToast) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null && newRoute && app.getRoutingHelper().isRoutePlanningMode()) { + adjustMapPosition(getHeight()); + } + } + + @Override + public void routeWasCancelled() { + + } + + @Override + public void routeWasFinished() { + + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index e6ad1b1728..876804b945 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -43,6 +43,7 @@ import net.osmand.ValueHolder; import net.osmand.data.FavouritePoint; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; +import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.FavouritesDbHelper.FavoritesListener; @@ -95,6 +96,7 @@ import net.osmand.plus.routepreparationmenu.cards.PublicTransportNotFoundWarning import net.osmand.plus.routepreparationmenu.cards.SimpleRouteCard; import net.osmand.plus.routepreparationmenu.cards.TracksCard; import net.osmand.plus.routing.IRouteInformationListener; +import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.TransportRoutingHelper; @@ -147,6 +149,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener private PointType selectFromMapPointType; private int selectFromMapMenuState = MenuState.HEADER_ONLY; private boolean selectFromMapWaypoints; + private boolean selectFromTracks; private boolean showMenu = false; private int showMenuState = DEFAULT_MENU_STATE; @@ -1563,8 +1566,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener if (mapActivity != null) { GPXRouteParamsBuilder routeParams = mapActivity.getRoutingHelper().getCurrentGPXRoute(); if (routeParams != null) { - FollowTrackFragment trackOptionsFragment = new FollowTrackFragment(); - FollowTrackFragment.showInstance(mapActivity, trackOptionsFragment); + selectTrack(); } } } @@ -1577,6 +1579,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener FrameLayout viaButton = mainView.findViewById(R.id.via_button); AndroidUiHelper.updateVisibility(viaButton, routeParams == null || isFinishPointFromTrack()); + viaButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -1949,6 +1952,19 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener } } + public void selectTrack() { + selectFromTracks = true; + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + FollowTrackFragment trackOptionsFragment = new FollowTrackFragment(); + FollowTrackFragment.showInstance(mapActivity, trackOptionsFragment); + } + } + + public void cancelSelectionFromTracks() { + selectFromTracks = false; + } + public void setupFields(PointType pointType) { View mainView = getMainView(); if (mainView != null) { @@ -2248,7 +2264,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener if (switched) { mapActivity.getMapLayers().getMapControlsLayer().switchToRouteFollowingLayout(); } - if (mapActivity.getPointToNavigate() == null && !selectFromMapTouch) { + if (mapActivity.getPointToNavigate() == null && !selectFromMapTouch && !selectFromTracks) { mapActivity.getMapActions().stopNavigationWithoutConfirm(); } mapActivity.updateStatusBarColor(); @@ -2363,6 +2379,32 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener updateMenu(); } + @NonNull + public QuadRect getRouteRect(@NonNull MapActivity mapActivity) { + OsmandApplication app = mapActivity.getMyApplication(); + RoutingHelper routingHelper = app.getRoutingHelper(); + MapRouteInfoMenu menu = mapActivity.getMapRouteInfoMenu(); + + QuadRect rect = new QuadRect(0, 0, 0, 0); + if (menu.isTransportRouteCalculated()) { + TransportRoutingHelper transportRoutingHelper = app.getTransportRoutingHelper(); + TransportRouteResult result = transportRoutingHelper.getCurrentRouteResult(); + if (result != null) { + QuadRect transportRouteRect = transportRoutingHelper.getTransportRouteRect(result); + if (transportRouteRect != null) { + rect = transportRouteRect; + } + } + } else if (routingHelper.isRouteCalculated()) { + RouteCalculationResult result = routingHelper.getRoute(); + QuadRect routeRect = routingHelper.getRouteRect(result); + if (routeRect != null) { + rect = routeRect; + } + } + return rect; + } + public enum MapRouteMenuType { ROUTE_INFO, ROUTE_DETAILS diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenuFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenuFragment.java index 537901f6f2..bd1d382677 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenuFragment.java @@ -16,23 +16,16 @@ import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import net.osmand.AndroidUtils; -import net.osmand.Location; import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; -import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.ContextMenuFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.routing.TransportRoutingHelper; +import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.widgets.TextViewExProgress; -import net.osmand.router.TransportRouteResult; -import net.osmand.util.MapUtils; - -import java.util.List; public class MapRouteInfoMenuFragment extends ContextMenuFragment { public static final String TAG = MapRouteInfoMenuFragment.class.getName(); @@ -289,36 +282,7 @@ public class MapRouteInfoMenuFragment extends ContextMenuFragment { RoutingHelper rh = app.getRoutingHelper(); if (rh.isRoutePlanningMode() && mapActivity.getMapView() != null) { - QuadRect r = new QuadRect(0, 0, 0, 0); - if (menu.isTransportRouteCalculated()) { - TransportRoutingHelper transportRoutingHelper = app.getTransportRoutingHelper(); - TransportRouteResult result = transportRoutingHelper.getCurrentRouteResult(); - if (result != null) { - QuadRect transportRouteRect = transportRoutingHelper.getTransportRouteRect(result); - if (transportRouteRect != null) { - r = transportRouteRect; - } - } - } else if (rh.isRouteCalculated()) { - Location lt = rh.getLastProjection(); - if (lt == null) { - lt = app.getTargetPointsHelper().getPointToStartLocation(); - } - if (lt == null) { - lt = app.getLocationProvider().getLastKnownLocation(); - } - if (lt != null) { - MapUtils.insetLatLonRect(r, lt.getLatitude(), lt.getLongitude()); - } - List list = rh.getCurrentCalculatedRoute(); - for (Location l : list) { - MapUtils.insetLatLonRect(r, l.getLatitude(), l.getLongitude()); - } - List targetPoints = app.getTargetPointsHelper().getIntermediatePointsWithTarget(); - for (TargetPoint l : targetPoints) { - MapUtils.insetLatLonRect(r, l.getLatitude(), l.getLongitude()); - } - } + QuadRect r = menu.getRouteRect(mapActivity); RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy(); int tileBoxWidthPx = 0; int tileBoxHeightPx = 0; diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java index c6d3df05ca..0d23e78673 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java @@ -5,7 +5,6 @@ import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.view.MenuItem; import android.view.View; import android.widget.CompoundButton; import android.widget.ImageView; @@ -13,14 +12,10 @@ import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.ColorRes; -import androidx.appcompat.view.ContextThemeWrapper; -import androidx.appcompat.widget.PopupMenu; import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentManager; import net.osmand.AndroidUtils; -import net.osmand.CallbackWithObject; -import net.osmand.GPXUtilities; import net.osmand.StateChangedListener; import net.osmand.plus.OsmAndLocationSimulation; import net.osmand.plus.OsmandApplication; @@ -35,7 +30,6 @@ import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerStartItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; -import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidPTTypesRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.DividerItem; @@ -367,8 +361,9 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { .setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - FollowTrackFragment trackOptionsFragment = new FollowTrackFragment(); - FollowTrackFragment.showInstance(mapActivity, trackOptionsFragment); + MapRouteInfoMenu mapRouteInfoMenu = mapActivity.getMapRouteInfoMenu(); + mapRouteInfoMenu.hide(); + mapRouteInfoMenu.selectTrack(); dismiss(); } }) @@ -500,58 +495,6 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { f.show(fragmentManager, RouteOptionsBottomSheet.TAG); } - protected void openGPXFileSelection() { - GpxUiHelper.selectGPXFile(mapActivity, false, false, new CallbackWithObject() { - - @Override - public boolean processResult(GPXUtilities.GPXFile[] result) { - mapActivity.getMapActions().setGPXRouteParams(result[0]); - app.getTargetPointsHelper().updateRouteAndRefresh(true); - updateParameters(); - routingHelper.recalculateRouteDueToSettingsChange(); - return true; - } - }, nightMode); - } - - private void showOptionsMenu(View view) { - RouteProvider.GPXRouteParamsBuilder rp = mapActivity.getRoutingHelper().getCurrentGPXRoute(); - final PopupMenu optionsMenu = new PopupMenu(new ContextThemeWrapper(view.getContext(), themeRes), view); - MenuItem item = optionsMenu.getMenu().add( - mapActivity.getString(R.string.shared_string_none)); - item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - if (mapActivity.getRoutingHelper().getCurrentGPXRoute() != null) { - mapActivity.getRoutingHelper().setGpxParams(null); - settings.FOLLOW_THE_GPX_ROUTE.set(null); - mapActivity.getRoutingHelper().recalculateRouteDueToSettingsChange(); - } - updateParameters(); - return true; - } - }); - item = optionsMenu.getMenu().add(mapActivity.getString(R.string.select_gpx)); - item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - openGPXFileSelection(); - return true; - } - }); - if (rp != null) { - item = optionsMenu.getMenu().add(new File(rp.getFile().path).getName()); - item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - // nothing to change - return true; - } - }); - } - optionsMenu.show(); - } - public void updateParameters() { Activity activity = getActivity(); View mainView = getView(); diff --git a/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java b/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java index a3fb41c2f2..7e6b089620 100644 --- a/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java +++ b/OsmAnd/src/net/osmand/plus/routing/GpxApproximator.java @@ -140,13 +140,13 @@ public class GpxApproximator { public void cancelApproximation() { if (gctx != null) { - gctx.calculationCancelled = true; + gctx.ctx.calculationProgress.isCancelled = true; } } public void calculateGpxApproximation(@NonNull final ResultMatcher resultMatcher) { if (gctx != null) { - gctx.calculationCancelled = true; + gctx.ctx.calculationProgress.isCancelled = true; } final GpxRouteApproximation gctx = getNewGpxApproximationContext(this.gctx); this.gctx = gctx; @@ -187,10 +187,10 @@ public class GpxApproximator { @Override public void run() { RouteCalculationProgress calculationProgress = gctx.ctx.calculationProgress; - if (gctx.isCalculationDone() && GpxApproximator.this.gctx == gctx) { + if (!gctx.result.isEmpty() && GpxApproximator.this.gctx == gctx) { finishProgress(); } - if (!gctx.isCalculationDone() && calculationProgress != null && !calculationProgress.isCancelled) { + if (gctx.result.isEmpty() && calculationProgress != null && !calculationProgress.isCancelled) { float pr = calculationProgress.getLinearProgress(); approximationProgress.updateProgress((int) pr); if (GpxApproximator.this.gctx != gctx) { diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index 57becfe9a6..4fd5b1dd65 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -1,9 +1,10 @@ package net.osmand.plus.routing; -import net.osmand.GPXUtilities; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import net.osmand.GPXUtilities.GPXFile; -import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; import net.osmand.LocationsHolder; import net.osmand.PlatformUtil; @@ -12,14 +13,11 @@ import net.osmand.ValueHolder; import net.osmand.binary.RouteDataObject; import net.osmand.data.LatLon; import net.osmand.data.QuadPoint; -import net.osmand.plus.routing.RouteProvider.RoutingEnvironment; -import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.data.QuadRect; import net.osmand.plus.NavigationService; -import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener; 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.TargetPointsHelper; import net.osmand.plus.TargetPointsHelper.TargetPoint; @@ -27,9 +25,12 @@ import net.osmand.plus.notifications.OsmandNotification.NotificationType; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder; import net.osmand.plus.routing.RouteProvider.RouteService; +import net.osmand.plus.routing.RouteProvider.RoutingEnvironment; +import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener; +import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.router.RouteCalculationProgress; import net.osmand.router.RouteExporter; -import net.osmand.router.RoutePlannerFrontEnd; import net.osmand.router.RoutePlannerFrontEnd.GpxPoint; import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation; import net.osmand.router.RouteSegmentResult; @@ -1041,7 +1042,30 @@ public class RoutingHelper { return route.getRouteDirections(); } + @Nullable + public QuadRect getRouteRect(@NonNull RouteCalculationResult result) { + QuadRect rect = new QuadRect(0, 0, 0, 0); + Location lt = getLastProjection(); + if (lt == null) { + lt = app.getTargetPointsHelper().getPointToStartLocation(); + } + if (lt == null) { + lt = app.getLocationProvider().getLastKnownLocation(); + } + if (lt != null) { + MapUtils.insetLatLonRect(rect, lt.getLatitude(), lt.getLongitude()); + } + List list = result.getImmutableAllLocations(); + for (Location l : list) { + MapUtils.insetLatLonRect(rect, l.getLatitude(), l.getLongitude()); + } + List targetPoints = app.getTargetPointsHelper().getIntermediatePointsWithTarget(); + for (TargetPoint l : targetPoints) { + MapUtils.insetLatLonRect(rect, l.getLatitude(), l.getLongitude()); + } + return rect.left == 0 && rect.right == 0 ? null : rect; + } private class RouteRecalculationThread extends Thread { @@ -1344,6 +1368,7 @@ public class RoutingHelper { // NEVER returns null + @NonNull public RouteCalculationResult getRoute() { return route; } diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java index 6b306003d0..0e34a4ca35 100644 --- a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java @@ -1491,7 +1491,9 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC limit--; } } - addressSearchFragment.updateListAdapter(rows, false); + if (addressSearchFragment != null) { + addressSearchFragment.updateListAdapter(rows, false); + } } public void reloadHistory() { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java index 2f7cf6cb5f..4752e180f7 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/GPXLayer.java @@ -43,11 +43,13 @@ 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.activities.MapActivity; import net.osmand.plus.base.PointImageDrawable; import net.osmand.plus.mapcontextmenu.controllers.SelectedGpxMenuController.SelectedGpxPoint; import net.osmand.plus.mapcontextmenu.other.TrackChartPoints; import net.osmand.plus.render.OsmandRenderer; import net.osmand.plus.render.OsmandRenderer.RenderingContext; +import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; import net.osmand.plus.settings.backend.OsmandSettings.CommonPreference; import net.osmand.plus.track.SaveGpxAsyncTask; import net.osmand.plus.track.TrackDrawInfo; @@ -70,6 +72,7 @@ import org.apache.commons.logging.Log; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -234,7 +237,15 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM @Override public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { - List selectedGPXFiles = selectedGpxHelper.getSelectedGPXFiles(); + List selectedGPXFiles = new ArrayList<>(selectedGpxHelper.getSelectedGPXFiles()); + + Iterator iterator = selectedGPXFiles.iterator(); + while (iterator.hasNext()) { + SelectedGpxFile selectedGpxFile = iterator.next(); + if (selectedGpxFile.isFollowTrack(view.getApplication()) && !showTrackToFollow()) { + iterator.remove(); + } + } cache.clear(); if (!selectedGPXFiles.isEmpty()) { drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings); @@ -710,6 +721,21 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM || gpxFile.path.equals(trackDrawInfo.getFilePath())); } + private boolean showTrackToFollow() { + if (view.getContext() instanceof MapActivity) { + MapActivity mapActivity = (MapActivity) view.getContext(); + OsmandApplication app = mapActivity.getMyApplication(); + MapRouteInfoMenu routeInfoMenu = mapActivity.getMapRouteInfoMenu(); + return !app.getSelectedGpxHelper().shouldHideTrackToFollow() + || routeInfoMenu.isVisible() + || app.getRoutingHelper().isFollowingMode() + || MapRouteInfoMenu.followTrackVisible + || MapRouteInfoMenu.chooseRoutesVisible + || MapRouteInfoMenu.waypointsVisible; + } + return false; + } + private boolean isPointVisited(WptPt o) { boolean visit = false; String visited = o.getExtensionsToRead().get("VISITED_KEY"); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java index cd6bf62ced..6f4708e381 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java @@ -58,7 +58,6 @@ import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu.PointType; import net.osmand.plus.routing.RoutingHelper; -import net.osmand.plus.routing.TransportRoutingHelper; import net.osmand.plus.search.QuickSearchDialogFragment.QuickSearchType; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmAndAppCustomization; @@ -847,7 +846,6 @@ public class MapControlsLayer extends OsmandMapLayer { // default buttons boolean routePlanningMode = false; RoutingHelper rh = mapActivity.getRoutingHelper(); - TransportRoutingHelper trh = mapActivity.getRoutingHelper().getTransportRoutingHelper(); if (rh.isRoutePlanningMode()) { routePlanningMode = true; } else if ((rh.isRouteCalculated() || rh.isRouteBeingCalculated()) && !rh.isFollowingMode()) { @@ -860,33 +858,25 @@ public class MapControlsLayer extends OsmandMapLayer { ((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode); boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu()); updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || contextMenuOpened); - boolean showButtons = (showRouteCalculationControls || !routeFollowingMode) + //routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_info_dark : R.drawable.ic_action_gdirections_dark); + + updateRoutePlaningButton(rh, routePlanningMode); + + boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode) && !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() && !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode() - && !isInWaypointsChoosingMode() && !isInTrackAppearanceMode(); - //routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_info_dark : R.drawable.ic_action_gdirections_dark); - int routePlanningBtnImage = mapRouteInfoMenu.getRoutePlanningBtnImage(); - if (routePlanningBtnImage != 0) { - routePlanningBtn.setIconResId(routePlanningBtnImage); - routePlanningBtn.setIconColorId(R.color.color_myloc_distance); - } else if (rh.isFollowingMode()) { - routePlanningBtn.setIconResId(R.drawable.ic_action_start_navigation); - routePlanningBtn.setIconColorId(R.color.color_myloc_distance); - } else if (routePlanningMode) { - routePlanningBtn.setIconResId(R.drawable.ic_action_gdirections_dark); - routePlanningBtn.setIconColorId(R.color.color_myloc_distance); - } else { - routePlanningBtn.setIconResId(R.drawable.ic_action_gdirections_dark); - routePlanningBtn.resetIconColors(); - } - routePlanningBtn.updateVisibility(showButtons); - menuControl.updateVisibility(showButtons); + && !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode(); + routePlanningBtn.updateVisibility(showBottomMenuButtons); + menuControl.updateVisibility(showBottomMenuButtons); + boolean showZoomButtons = !routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode() + && !isInFollowTrackMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait); + mapZoomIn.updateVisibility(showZoomButtons); + mapZoomOut.updateVisibility(showZoomButtons); - mapZoomIn.updateVisibility(!routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait)); - mapZoomOut.updateVisibility(!routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait)); - boolean forceHideCompass = routeDialogOpened || trackDialogOpened - || isInMeasurementToolMode() || isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode() || isInTrackAppearanceMode() || isInWaypointsChoosingMode(); + boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode() + || isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode() + || isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode(); compassHud.forceHideCompass = forceHideCompass; compassHud.updateVisibility(!forceHideCompass && shouldShowCompass()); @@ -895,10 +885,11 @@ public class MapControlsLayer extends OsmandMapLayer { if (layersHud.setIconResId(appMode.getIconRes())) { layersHud.update(app, isNight); } - layersHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && !isInMeasurementToolMode() && !isInPlanRouteMode() - && !contextMenuOpened && !isInChoosingRoutesMode() && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode()); - quickSearchHud.updateVisibility(!routeDialogOpened && !trackDialogOpened && !isInMeasurementToolMode() && !isInPlanRouteMode() - && !contextMenuOpened && !isInChoosingRoutesMode() && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode()); + boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !contextMenuOpened + && !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode() + && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode(); + layersHud.updateVisibility(showTopButtons); + quickSearchHud.updateVisibility(showTopButtons); if (mapView.isZooming()) { lastZoom = System.currentTimeMillis(); @@ -948,6 +939,23 @@ public class MapControlsLayer extends OsmandMapLayer { } } + private void updateRoutePlaningButton(RoutingHelper routingHelper, boolean routePlanningMode) { + int routePlanningBtnImage = mapRouteInfoMenu.getRoutePlanningBtnImage(); + if (routePlanningBtnImage != 0) { + routePlanningBtn.setIconResId(routePlanningBtnImage); + routePlanningBtn.setIconColorId(R.color.color_myloc_distance); + } else if (routingHelper.isFollowingMode()) { + routePlanningBtn.setIconResId(R.drawable.ic_action_start_navigation); + routePlanningBtn.setIconColorId(R.color.color_myloc_distance); + } else if (routePlanningMode) { + routePlanningBtn.setIconResId(R.drawable.ic_action_gdirections_dark); + routePlanningBtn.setIconColorId(R.color.color_myloc_distance); + } else { + routePlanningBtn.setIconResId(R.drawable.ic_action_gdirections_dark); + routePlanningBtn.resetIconColors(); + } + } + private boolean shouldShowCompass() { float mapRotate = mapActivity.getMapView().getRotate(); return forceShowCompass || mapRotate != 0 @@ -987,7 +995,7 @@ public class MapControlsLayer extends OsmandMapLayer { boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); boolean visible = !(tracked && rh.isFollowingMode()); backToLocationControl.updateVisibility(visible && !dialogOpened && !isInPlanRouteMode() - && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !isPotrait())); + && !isInTrackAppearanceMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !isInFollowTrackMode() || !isPotrait())); } public boolean onSingleTap(PointF point, RotatedTileBox tileBox) { @@ -1303,6 +1311,10 @@ public class MapControlsLayer extends OsmandMapLayer { return MapRouteInfoMenu.waypointsVisible; } + private boolean isInFollowTrackMode() { + return MapRouteInfoMenu.followTrackVisible; + } + public static View.OnLongClickListener getOnClickMagnifierListener(final OsmandMapTileView view) { return new View.OnLongClickListener() { diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java index 722b5133c6..0353776edb 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java @@ -426,6 +426,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe mapRouteInfoMenu.isVisible() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible || + MapRouteInfoMenu.followTrackVisible || contextMenu.isVisible() && contextMenuMenuFragment != null && !contextMenuMenuFragment.isRemoving() || contextMenu.isVisible() && contextMenuMenuFragment != null && contextMenuMenuFragment.isAdded() || multiSelectionMenu.isVisible() && multiMenuFragment != null && multiMenuFragment.isAdded() || diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java index 05f7a7586c..45ba996045 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/LanesControl.java @@ -18,7 +18,7 @@ import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.views.OsmandMapLayer; +import net.osmand.plus.views.OsmandMapLayer.DrawSettings; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.mapwidgets.widgets.TextInfoWidget; import net.osmand.router.RouteResultPreparation; @@ -61,7 +61,7 @@ public class LanesControl { TextInfoWidget.updateTextColor(lanesText, lanesShadowText, textColor, textShadowColor, textBold, shadowRadius); } - public boolean updateInfo(OsmandMapLayer.DrawSettings drawSettings) { + public boolean updateInfo(DrawSettings drawSettings) { boolean visible = false; int locimminent = -1; int[] loclanes = null; @@ -105,7 +105,8 @@ public class LanesControl { } } } - visible = loclanes != null && loclanes.length > 0 && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible; + visible = loclanes != null && loclanes.length > 0 && !MapRouteInfoMenu.chooseRoutesVisible + && !MapRouteInfoMenu.waypointsVisible && !MapRouteInfoMenu.followTrackVisible; if (visible) { if (!Arrays.equals(lanesDrawable.lanes, loclanes) || (locimminent == 0) != lanesDrawable.imminent) { diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java index d01f042bd8..9979b3820b 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java @@ -1232,7 +1232,8 @@ public class MapInfoWidgetsFactory { boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && map.getContextMenu().shouldShowTopControls() && map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive() && !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode() - && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible; + && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible + && !MapRouteInfoMenu.followTrackVisible; updateVisibility(visible); if (visible) {