Merge branch 'master' into plan_route_point_menu

# Conflicts:
#	OsmAnd/res/values/strings.xml
#	OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java
This commit is contained in:
Dima-1 2020-08-17 23:28:01 +03:00
commit 022ffb5813
131 changed files with 1757 additions and 961 deletions

View file

@ -1,7 +1,7 @@
### Credits to all major contributors/developers:
Major contributors /developers listed here https://github.com/osmandapp/osmandapp.github.io/blob/master/website/help/about.html#L8
### Credits to all major contributors / developers:
Major contributors / developers listed here https://github.com/osmandapp/osmandapp.github.io/blob/master/website/help/about.html#L8
### Other Pull requests
Copyright © All authors of translations and pull requests could be found in commits history:
Copyright © All authors of translations and pull requests can be found in the commit history:
- Translations are under special “contributor” name weblate
- Pull requests have two committers, first is original contributor and second is project maintainer
- Pull requests have two committers: first is original contributor, and second is project maintainer

View file

@ -1,26 +1,32 @@
Before entering an issue, please read the information below.
```GitHub is a main development tool for developers. There are hundreds requests a month and there are only few developers. So by opening an issue, please know that your issue will be sent out to all developers and acknowledge that it could be closed without explanation or with a brief message. Comments on the closed issues are also sent to all developers, so you will definitely will be heard. However, there is no guarantee that a developer will pick up the issue to work on it.```
```GitHub is our main development tool for our developers. There are hundreds of requests a month and there are relatively few developers.
So by opening an issue, please know that your issue will be sent out to all developers and acknowledge that it could be closed without explanation or with just a brief message.
Comments on the closed issues are also sent to all developers, so you will definitely will be heard.
However, there is no guarantee that a developer will pick up the issue to work on it.```
In case you are not sure to open issue or not, please send your request to support support@osmand.net. For **general questions** about OsmAnd, please use the [Google group](https://groups.google.com/forum/#!forum/osmand).
In case you aren't sure whether to open an issue or not, please send your request to support@osmand.net.
For **general questions** about OsmAnd, please use the [Google group](https://groups.google.com/forum/#!forum/osmand).
Please be sure to have read our [FAQ](http://osmand.net/help-online) before creating an issue here. (Also, tell us in Google Groups when the FAQ is wrong or outdated.)
Please be sure to read our [FAQ](https://osmand.net/help-online) before creating an issue here.
(Also, tell us in Google Groups when the FAQ is wrong or outdated.)
The best way to get help about an OsmAnd issue is to create a valid and detailed issue content.
The best way to get help about an OsmAnd issue is to create a valid and detailed issue.
Please give us the following information so that we can try to **reproduce** your issue:
What version of OsmAnd are you using, on what device and Android/iOS version?
What version of OsmAnd are you using, and on what device and Android/iOS version?
Do you use the offline maps offered within the OsmAnd app for download, or online (tile / raster) maps?
Do you use the offline maps offered within the OsmAnd app for download, or the online (tile / raster) maps?
If you have an issue related to offline maps, tell us the exact name of the map file where the issue occurs, and its edition date.
If you have an issue related to offline maps, tell us the exact name of the map file where the issue occurs and its edition date.
__*In case of wrong routing:*__
Tell us whether you have used OsmAnd's in-app offline routing, or any online routing provider like YOURS, OpenRouteService or OSRM.
Tell us whether you have used OsmAnd's in-app offline routing or any online routing provider like YOURS, OpenRouteService, OSRM, etc.
What routing profile is chosen in OsmAnd app? (car, bike, pedestrian, fastest or shortest)
What routing profile is chosen in the OsmAnd app? (car, bike, pedestrian, fastest or shortest, etc.)
Please specify as exactly as possible the start and end point of your route by telling us city name and street name so that we can find it via in-app address search easily. Also, a permalink from openstreetmap.org can be helpful.
Please specify (as exact as possible) the start and end point of your route by telling us the city and street name so that we can find it via the in-app address search easily.
Also, a permalink from [openstreetmap.org](https://www.openstreetmap.org/) can be helpful.
Tell us your expected routing, and how OsmAnd routes, or add screenshots here.
Tell us your expected routing and how OsmAnd routes, or add screenshots here.

70
LICENSE
View file

@ -1,11 +1,11 @@
OsmAnd OSM Automated Navigation Directions navigation software based on OpenStreetMap.
Copyright © 20102018 OsmAnd BV (Amstelveen, Netherlands - KvK 62066714, BTW 854627704B01).
Copyright © 20102020 OsmAnd BV (Amstelveen, Netherlands - KvK 62066714, BTW 854627704B01).
The code in this repository is covered by *GPLv3* (for code) and the artwork is covered by [ CC-BY-NC-ND 4.0 ](https://creativecommons.org/licenses/by-nc-nd/4.0/) (for artwork), except some 3rd party libs and resources.
ATTENTION: please be aware that some artwork has proprietary license.
The code in this repository is covered by *GPLv3* (for code) and the artwork is covered by [CC-BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/) (for artwork), except for some third-party libraries and resources.
ATTENTION: Please be aware that some artwork uses a proprietary license.
Main AUTHORS (more detailed list in AUTHORS):
Main AUTHORS (more detailed list in AUTHORS.md):
Victor Shcherb all parts of the project, originator
Alexey Pelykh rendering and core parts
Hardy Mueller main parts of the project, mostly rendering, UI interaction design
@ -30,33 +30,33 @@
* Source code in main repositories is covered by GPLv3 (license exceptions below):
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java
- https://github.com/osmandapp/Osmand-core/tree/legacy_core
- https://github.com/osmandapp/Osmand-core/
- https://github.com/osmandapp/OsmAnd-core/tree/legacy_core
- https://github.com/osmandapp/OsmAnd-core
- https://github.com/osmandapp/OsmAnd-misc
- https://github.com/osmandapp/OsmAnd-tools
- https://github.com/osmandapp/OsmAnd-resources
* UI Design and UX work, such as layout, icons is covered by CC-BY-NC-ND
* UI Design and UX work, such as layout and icons, are covered by [CC-BY-NC-ND 4.0](https://creativecommons.org/licenses/by-nc-nd/4.0/)
- https://github.com/osmandapp/Osmand/tree/master/OsmAnd/res and others
Restriction to UI/UX CC-BY-NC-ND:
* Publishing applications using the OsmAnd UI/UX code to Google Play, Amazon Market or Apple Store must be done with written permission*
* Publishing applications using the OsmAnd UI/UX code to Google Play, Amazon Market, or Apple Store must be done with written permission.*
* Map icons are taken from sjjb and some are drawn and distributed under Public Domain (except icons8)
- https://github.com/osmandapp/OsmAnd-resources/tree/master/icons/svg
- some icons are from http://osm-icons.org/wiki/Icons (CC-0 by Markus59, CC BY-SA 2.0)
* Integration with Qt library in (https://github.com/osmandapp/Osmand-core/) - dynamic linking
- LGPL (http://www.qt.io/qt-licensing-terms/)
* Integration with Qt library in (https://github.com/osmandapp/OsmAnd-core) - dynamic linking
- LGPL (https://www.qt.io/terms-conditions/)
* Map icons and their derived primitives are covered by proprietary license:
* Map icons and their derived primitives are covered by a proprietary license:
- © icons8.com (https://github.com/osmandapp/OsmAnd-resources/tree/master/icons/svg/icons8)
* Generated voice files from TTS files are covered by proprietary license:
* Generated voice files from TTS files are covered by a proprietary license:
- Voice files (https://github.com/osmandapp/OsmAnd-resources/tree/master/voice)
* Fonts (https://github.com/osmandapp/OsmAnd-resources/tree/master/rendering_styles/fonts)
- Google Fonts (Apache License 2)
- Google Fonts (Apache License 2.0)
* Map icons (Mapnik):
- Open-SVG-Map-Icons - Public Domain
@ -65,49 +65,27 @@
- SherlockBar - Apache License - https://github.com/osmandapp/Osmand/tree/master/SherlockBar (https://github.com/JakeWharton/ActionBarSherlock/blob/master/LICENSE.txt)
* Patched libraries:
- Protobuf - New BSD License (patches - https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/protobuf-src, https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/protobuf)
- Expat - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/expat)
- Freetype - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/freetype)
- Giflib - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/giflib)
- Protobuf - New BSD License (patches - https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/src/main/java/com/google/protobuf, https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/protobuf)
- Jpeg - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/jpeg)
- Libpng - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/libpng)
- Skia - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/skia)
- ZLib - (https://github.com/osmandapp/OsmAnd-core/tree/legacy_core/externals/zlib)
- android-openmap-framework - (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/src/main/java/com/jwetherell/openmap/common)
- mapbox-vector-tile - (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/src/main/java/com/wdtinc/mapbox_vector_tile)
* 3rd party libraries present in the libs folder (https://github.com/osmandapp/Osmand/tree/master/OsmAnd-java/libs):
- bzip2-20090327.jar Bzip2 - Apache License
- commons-logging-1.1.1.jar - Apache License
- gnu-trove-osmand.jar GNU trove - LGPL
- icu4j-49_1.jar - ICU license (http://source.icu-project.org/repos/icu/icu/trunk/license.html)
- json-20090211.jar - BSD alike (http://www.json.org/license.html)
- junidecode-0.1.jar - BSD-4-Clause-UC (http://sourceforge.net/projects/junidecode/)
- kxml2-2.3.0.jar - BSD license (http://www.kxml.org/)
- tuprolog.jar - LGPL (http://apice.unibo.it/xwiki/bin/view/Tuprolog/)
- OpenMap framework - Apache License (https://code.google.com/p/android-openmap-framework/)
- icu4j-49_1_patched.jar - ICU license (https://home.unicode.org/basic-info/projects/#/icu/icu/trunk/license.html)
* Pull-requests and translations:
- All pull requests are accepted under MIT License (most honorable contributors are mentioned in AUTHORS list)
* Libraries not used in final product (https://github.com/osmandapp/OsmAnd-tools/tree/master/OsmAndMapCreator/libi)
- Ant libraries - (tools) https://github.com/osmandapp/Osmand/tree/master/OsmAnd/ant-lib
- jleveldb-v01.jar
- jsch-20120101.jar
- junit-4.10.jar
- mysql-connector-java-5.1.18-bin.jar
- sqlite-jdbc-3.7.6.3-20110609.081603-3.jar
- h2-latest.jar
- All pull requests are accepted under MIT License (most honorable contributors are mentioned in AUTHORS list).
* Special tools for new rendering (GPLv3)
- https://github.com/osmandapp/OsmAnd-tools/tree/master/obf-inspector
- https://github.com/osmandapp/OsmAnd-tools/tree/master/obf-verifier
- https://github.com/osmandapp/OsmAnd-tools/tree/master/route-tester
- https://github.com/osmandapp/OsmAnd-tools
* OSM data 2014
- Extracts - https://github.com/osmandapp/OsmAnd-misc/blob/master/osm-planet/osm-data/
* OSM data
- Extracts - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/osm-data
* Data files
- Country boundaries - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/geo-polygons © by Geofabrik - data free to use
- Country boundaries - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/gislab-polygons © by http://be.gis-lab.info - data free to use
- Country boundaries - https://github.com/osmandapp/OsmAnd-misc/tree/master/osm-planet/polygons © by Geofabrik - data free to use
* Subway icons
- Moscow: Art Lebedev Studio (http://www.artlebedev.ru/everything/metro/logo/) [Public domain], undefined
@ -119,7 +97,7 @@
- Kazan: «Kazan-metro-Logo» (Россиянин) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Kazan-metro-Logo.svg#/media/File:Kazan-metro-Logo.svg
- Tbilisi: «Metro Tbilisi logo» (Carnby) - own work. Under CC BY-SA 3.0 license from site - https://commons.wikimedia.org/wiki/File:Metro_Tbilisi_logo.svg#/media/File:Metro_Tbilisi_logo.svg
- Minsk: «Minsk metro logo» (Skip405) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Minsk_metro_logo.svg#/media/File:Minsk_metro_logo.svg
- Nizhny Novgorod: «NNMetro» (AlexTref871) - own work. This vector image includes elements borrowed from another image:  Coat of arms of Nizhny Novgorod Region.svg.. Under Public domain Commons licensefrom the site - https://commons.wikimedia.org/wiki/File:NNMetro.svg#/media/File:NNMetro.svg
- Nizhny Novgorod: «NNMetro» (AlexTref871) - own work. This vector image includes elements borrowed from another image: Coat of arms of Nizhny Novgorod Region.svg.. Under Public domain Commons licensefrom the site - https://commons.wikimedia.org/wiki/File:NNMetro.svg#/media/File:NNMetro.svg
- Novosibirsk: «Logo-Nsk-Metro» (AlexTref871) - own work. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:Logo-Nsk-Metro.svg#/media/File:Logo-Nsk-Metro.svg
- Yekaterinburg: «Ekt-metro-logo-01» (AlexTref871) - own work. Under CC BY-SA 4.0 license from site - https://commons.wikimedia.org/wiki/File:Ekt-metro-logo-01.svg#/media/File:Ekt-metro-logo-01.svg
- New York: «MTA New York City Subway logo» (Metropolitan Transportation Authority) - http://mta.info/. Under Public domain Commons license from the site - https://commons.wikimedia.org/wiki/File:MTA_New_York_City_Subway_logo.svg#/media/File:MTA_New_York_City_Subway_logo.svg
@ -152,7 +130,7 @@
- Los Angeles: "Lametro" by Los Angeles County Metropolitan Transportation Authority. Original uploader was Cheeselouise at en.wikipedia - Metro materials at http://www.metro.net/riding_metro/pocket_guide_cambodian_printers.pdf. Licensed under Public Domain via Commons - https://commons.wikimedia.org/wiki/File:Lametro.svg#/media/File:Lametro.svg
* Depth maps
- The GEBCO_2014 Grid, version 20150318, www.gebco.net
- The GEBCO_2020 Grid, www.gebco.net
- U.S. Bureau of Ocean Energy Management (24 may 2017,12m per pixel)
- South_Padre_Island_DEM_4133: Grothe, P.G., L.A. Taylor, B.W. Eakins, K.S. Carignan, D.Z. Friday, and M. Love, 2012. Digital Elevation Models of South Padre Island, Texas: Procedures, Data Sources and Analysis, NOAA National Geophysical Data Center technical report, Boulder, CO, 15 pp.
- Corpus_Christi_DEM_1035: Taylor, L.A., B.W. Eakins, K.S. Carignan, R.R. Warnken, T. Sazonova, and D.C. Schoolcraft, 2008. Digital Elevation Model of Corpus Christi, Texas: Procedures, Data Sources and Analysis, NOAA Technical Memorandum NESDIS NGDC-11, National Geophysical Data Center, Boulder, CO, 19 pp.

View file

@ -2,6 +2,9 @@
package net.osmand;
import net.osmand.binary.StringBundle;
import net.osmand.binary.StringBundleWriter;
import net.osmand.binary.StringBundleXmlWriter;
import net.osmand.data.QuadRect;
import net.osmand.util.Algorithms;
@ -13,7 +16,6 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@ -315,10 +317,14 @@ public class GPXUtilities {
getExtensionsToWrite().put(PROFILE_TYPE_EXTENSION, profileType);
}
public void removeProfileType() {
getExtensionsToWrite().remove(PROFILE_TYPE_EXTENSION);
}
public int getTrkPtIndex() {
try {
return Integer.parseInt(getExtensionsToRead().get(TRKPT_INDEX_EXTENSION));
}catch(NumberFormatException e){
} catch (NumberFormatException e) {
return -1;
}
}
@ -437,6 +443,44 @@ public class GPXUtilities {
public double maxlon;
}
public static class RouteSegment {
public String id;
public String length;
public String segmentTime;
public String speed;
public String turnType;
public String turnAngle;
public String types;
public String pointTypes;
public String names;
public StringBundle getStringBundle() {
StringBundle bundle = new StringBundle();
bundle.putString("id", id);
bundle.putString("length", length);
bundle.putString("segmentTime", segmentTime);
bundle.putString("speed", speed);
bundle.putString("turnType", turnType);
bundle.putString("turnAngle", turnAngle);
bundle.putString("types", types);
bundle.putString("pointTypes", pointTypes);
bundle.putString("names", names);
return bundle;
}
}
public static class RouteType {
public String tag;
public String value;
public StringBundle getStringBundle() {
StringBundle bundle = new StringBundle();
bundle.putString("t", tag);
bundle.putString("v", value);
return bundle;
}
}
public static class GPXTrackAnalysis {
public float totalDistance = 0;
public float totalDistanceWithoutGaps = 0;
@ -1006,6 +1050,9 @@ public class GPXUtilities {
private List<WptPt> points = new ArrayList<>();
public List<Route> routes = new ArrayList<>();
public List<RouteSegment> routeSegments = new ArrayList<>();
public List<RouteType> routeTypes = new ArrayList<>();
public Exception error = null;
public String path = "";
public boolean showCurrentTrack;
@ -1032,6 +1079,10 @@ public class GPXUtilities {
}
}
public boolean hasRoute() {
return !routeSegments.isEmpty() && !routeTypes.isEmpty();
}
public List<WptPt> getPoints() {
return Collections.unmodifiableList(points);
}
@ -1744,6 +1795,7 @@ public class GPXUtilities {
serializer.endTag(null, "wpt"); //$NON-NLS-1$
}
assignRouteExtensionWriter(file);
writeExtensions(serializer, file);
serializer.endTag(null, "gpx"); //$NON-NLS-1$
@ -1756,6 +1808,29 @@ public class GPXUtilities {
return null;
}
private static void assignRouteExtensionWriter(final GPXFile gpxFile) {
if (gpxFile.hasRoute() && gpxFile.getExtensionsWriter() == null) {
gpxFile.setExtensionsWriter(new GPXExtensionsWriter() {
@Override
public void writeExtensions(XmlSerializer serializer) {
StringBundle bundle = new StringBundle();
List<StringBundle> segmentsBundle = new ArrayList<>();
for (RouteSegment segment : gpxFile.routeSegments) {
segmentsBundle.add(segment.getStringBundle());
}
bundle.putBundleList("route", "segment", segmentsBundle);
List<StringBundle> typesBundle = new ArrayList<>();
for (RouteType routeType : gpxFile.routeTypes) {
typesBundle.add(routeType.getStringBundle());
}
bundle.putBundleList("types", "type", typesBundle);
StringBundleWriter bundleWriter = new StringBundleXmlWriter(bundle, serializer);
bundleWriter.writeBundle();
}
});
}
}
private static String getFilename(String path) {
if(path != null) {
int i = path.lastIndexOf('/');
@ -1973,23 +2048,7 @@ public class GPXUtilities {
}
public static GPXFile loadGPXFile(InputStream f) {
return loadGPXFile(f, null, null);
}
public static GPXFile loadGPXFile(InputStream f, GPXFile gpxFile, GPXExtensionsReader extensionsReader) {
boolean readExtensionsOnly = false;
if (gpxFile == null) {
gpxFile = new GPXFile(null);
} else {
if (f == null) {
try {
f = new FileInputStream(new File(gpxFile.path));
} catch (FileNotFoundException e) {
return gpxFile;
}
}
readExtensionsOnly = extensionsReader != null;
}
GPXFile gpxFile = new GPXFile(null);
SimpleDateFormat format = new SimpleDateFormat(GPX_TIME_FORMAT, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat formatMillis = new SimpleDateFormat(GPX_TIME_FORMAT_MILLIS, Locale.US);
@ -2003,6 +2062,10 @@ public class GPXUtilities {
Stack<GPXExtensions> parserState = new Stack<>();
boolean extensionReadMode = false;
boolean routePointExtension = false;
List<RouteSegment> routeSegments = gpxFile.routeSegments;
List<RouteType> routeTypes = gpxFile.routeTypes;
boolean routeExtension = false;
boolean typesExtension = false;
parserState.push(gpxFile);
int tok;
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
@ -2011,37 +2074,50 @@ public class GPXUtilities {
String tag = parser.getName();
if (extensionReadMode && parse != null && !routePointExtension) {
String tagName = tag.toLowerCase();
boolean extensionsRead = false;
if (extensionsReader != null) {
extensionsRead = extensionsReader.readExtensions(gpxFile, parser);
if (routeExtension) {
if (tagName.equals("segment")) {
RouteSegment segment = parseRouteSegmentAttributes(parser);
routeSegments.add(segment);
}
} else if (typesExtension) {
if (tagName.equals("type")) {
RouteType type = parseRouteTypeAttributes(parser);
routeTypes.add(type);
}
}
if (!readExtensionsOnly && !extensionsRead) {
switch (tagName) {
case "routepointextension":
routePointExtension = true;
if (parse instanceof WptPt) {
parse.getExtensionsToWrite().put("offset", routeTrackSegment.points.size() + "");
}
break;
switch (tagName) {
case "routepointextension":
routePointExtension = true;
if (parse instanceof WptPt) {
parse.getExtensionsToWrite().put("offset", routeTrackSegment.points.size() + "");
}
break;
default:
Map<String, String> values = readTextMap(parser, tag);
if (values.size() > 0) {
for (Entry<String, String> entry : values.entrySet()) {
String t = entry.getKey().toLowerCase();
String value = entry.getValue();
parse.getExtensionsToWrite().put(t, value);
if (tag.equals("speed") && parse instanceof WptPt) {
try {
((WptPt) parse).speed = Float.parseFloat(value);
} catch (NumberFormatException e) {
log.debug(e.getMessage(), e);
}
case "route":
routeExtension = true;
break;
case "types":
typesExtension = true;
break;
default:
Map<String, String> values = readTextMap(parser, tag);
if (values.size() > 0) {
for (Entry<String, String> entry : values.entrySet()) {
String t = entry.getKey().toLowerCase();
String value = entry.getValue();
parse.getExtensionsToWrite().put(t, value);
if (tag.equals("speed") && parse instanceof WptPt) {
try {
((WptPt) parse).speed = Float.parseFloat(value);
} catch (NumberFormatException e) {
log.debug(e.getMessage(), e);
}
}
}
break;
}
}
break;
}
} else if (parse != null && tag.equals("extensions")) {
extensionReadMode = true;
@ -2051,7 +2127,7 @@ public class GPXUtilities {
routeTrackSegment.points.add(wptPt);
parserState.push(wptPt);
}
} else if (!readExtensionsOnly) {
} else {
if (parse instanceof GPXFile) {
if (tag.equals("gpx")) {
((GPXFile) parse).author = parser.getAttributeValue("", "creator");
@ -2247,7 +2323,12 @@ public class GPXUtilities {
if (parse != null && tag.equals("extensions")) {
extensionReadMode = false;
}
if (readExtensionsOnly) {
if (extensionReadMode && tag.equals("route")) {
routeExtension = false;
continue;
}
if (extensionReadMode && tag.equals("types")) {
typesExtension = false;
continue;
}
@ -2327,6 +2408,27 @@ public class GPXUtilities {
return wpt;
}
private static RouteSegment parseRouteSegmentAttributes(XmlPullParser parser) {
RouteSegment segment = new RouteSegment();
segment.id = parser.getAttributeValue("", "id");
segment.length = parser.getAttributeValue("", "length");
segment.segmentTime = parser.getAttributeValue("", "segmentTime");
segment.speed = parser.getAttributeValue("", "speed");
segment.turnType = parser.getAttributeValue("", "turnType");
segment.turnAngle = parser.getAttributeValue("", "turnAngle");
segment.types = parser.getAttributeValue("", "types");
segment.pointTypes = parser.getAttributeValue("", "pointTypes");
segment.names = parser.getAttributeValue("", "names");
return segment;
}
private static RouteType parseRouteTypeAttributes(XmlPullParser parser) {
RouteType type = new RouteType();
type.tag = parser.getAttributeValue("", "t");
type.value = parser.getAttributeValue("", "v");
return type;
}
private static Bounds parseBoundsAttributes(XmlPullParser parser) {
Bounds bounds = new Bounds();
try {

View file

@ -21,7 +21,7 @@ public class StringBundle {
private static final DecimalFormat FIVE_DIGITS_FORMATTER = new DecimalFormat("#.#####");
private static final DecimalFormat SIX_DIGITS_FORMATTER = new DecimalFormat("#.######");
private Map<String, Item> map = new LinkedHashMap<>();
private Map<String, Item<?>> map = new LinkedHashMap<>();
public enum ItemType {
STRING,
@ -32,7 +32,7 @@ public class StringBundle {
public StringBundle() {
}
protected StringBundle(Map<String, Item> map) {
protected StringBundle(Map<String, Item<?>> map) {
this.map = map;
}
@ -156,16 +156,16 @@ public class StringBundle {
}
}
public static class StringListItem extends Item<List<Item>> {
public static class StringListItem extends Item<List<Item<?>>> {
private StringListItem(String name, List<Item> list) {
private StringListItem(String name, List<Item<?>> list) {
super(name, ItemType.LIST, list);
}
}
public static class StringMapItem extends Item<Map<String, Item>> {
public static class StringMapItem extends Item<Map<String, Item<?>>> {
private StringMapItem(String name, Map<String, Item> map) {
private StringMapItem(String name, Map<String, Item<?>> map) {
super(name, ItemType.MAP, map);
}
}
@ -177,11 +177,11 @@ public class StringBundle {
}
}
public Map<String, Item> getMap() {
public Map<String, Item<?>> getMap() {
return Collections.unmodifiableMap(map);
}
public Item getItem(String key) {
public Item<?> getItem(String key) {
return map.get(key);
}
@ -190,7 +190,7 @@ public class StringBundle {
}
public int getInt(String key, int defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).asInt(defaultValue) : defaultValue;
}
@ -199,7 +199,7 @@ public class StringBundle {
}
public long getLong(String key, long defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).asLong(defaultValue) : defaultValue;
}
@ -212,7 +212,7 @@ public class StringBundle {
}
public float getFloat(String key, float defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).asFloat(defaultValue) : defaultValue;
}
@ -221,7 +221,7 @@ public class StringBundle {
}
public boolean getBoolean(String key, boolean defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).asBoolean(defaultValue) : defaultValue;
}
@ -232,35 +232,13 @@ public class StringBundle {
}
public String getString(String key, String defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).getValue() : defaultValue;
}
public void putObject(String key, StringExternalizable object) {
if (object != null) {
StringBundle bundle = newInstance();
object.writeToBundle(bundle);
map.put(key, new StringBundleItem(key, bundle));
}
}
public void putList(String key, String itemName, List<? extends StringExternalizable> list) {
if (list != null) {
List<Item> itemList = new ArrayList<>();
for (StringExternalizable ex : list) {
if (ex != null) {
StringBundle bundle = newInstance();
ex.writeToBundle(bundle);
itemList.add(new StringBundleItem(itemName, bundle));
}
}
map.put(key, new StringListItem(key, itemList));
}
}
public void putBundleList(String key, String itemName, List<StringBundle> list) {
if (list != null) {
List<Item> itemList = new ArrayList<>();
List<Item<?>> itemList = new ArrayList<>();
for (StringBundle bundle : list) {
itemList.add(new StringBundleItem(itemName, bundle));
}
@ -279,7 +257,7 @@ public class StringBundle {
}
public int[] getIntArray(String key, int[] defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).asIntArray(defaultValue) : defaultValue;
}
@ -290,7 +268,7 @@ public class StringBundle {
}
public int[][] getIntIntArray(String key, int[][] defaultValue) {
Item item = map.get(key);
Item<?> item = map.get(key);
return item instanceof StringItem ? ((StringItem) item).asIntIntArray(defaultValue) : defaultValue;
}

View file

@ -16,10 +16,10 @@ public abstract class StringBundleWriter {
return bundle;
}
protected abstract void writeItem(String name, Item item);
protected abstract void writeItem(String name, Item<?> item);
public void writeBundle() {
for (Entry<String, Item> entry : bundle.getMap().entrySet()) {
for (Entry<String, Item<?>> entry : bundle.getMap().entrySet()) {
writeItem(entry.getKey(), entry.getValue());
}
}

View file

@ -25,7 +25,7 @@ public class StringBundleXmlWriter extends StringBundleWriter {
}
@Override
protected void writeItem(String name, Item item) {
protected void writeItem(String name, Item<?> item) {
if (serializer != null) {
try {
writeItemImpl(name, item);
@ -47,7 +47,7 @@ public class StringBundleXmlWriter extends StringBundleWriter {
}
}
private void writeItemImpl(String name, Item item) throws IOException {
private void writeItemImpl(String name, Item<?> item) throws IOException {
if (serializer != null && item != null) {
switch (item.getType()) {
case STRING: {
@ -58,13 +58,13 @@ public class StringBundleXmlWriter extends StringBundleWriter {
case LIST: {
StringListItem listItem = (StringListItem) item;
serializer.startTag(null, name);
List<Item> list = listItem.getValue();
for (Item i : list) {
List<Item<?>> list = listItem.getValue();
for (Item<?> i : list) {
if (i.getType() == StringBundle.ItemType.STRING) {
writeItemImpl(i.getName(), i);
}
}
for (Item i : list) {
for (Item<?> i : list) {
if (i.getType() != StringBundle.ItemType.STRING) {
writeItemImpl(i.getName(), i);
}
@ -75,14 +75,14 @@ public class StringBundleXmlWriter extends StringBundleWriter {
case MAP: {
StringMapItem mapItem = (StringMapItem) item;
serializer.startTag(null, name);
for (Entry<String, Item> entry : mapItem.getValue().entrySet()) {
Item i = entry.getValue();
for (Entry<String, Item<?>> entry : mapItem.getValue().entrySet()) {
Item<?> i = entry.getValue();
if (i.getType() == StringBundle.ItemType.STRING) {
writeItemImpl(entry.getKey(), i);
}
}
for (Entry<String, Item> entry : mapItem.getValue().entrySet()) {
Item i = entry.getValue();
for (Entry<String, Item<?>> entry : mapItem.getValue().entrySet()) {
Item<?> i = entry.getValue();
if (i.getType() != StringBundle.ItemType.STRING) {
writeItemImpl(entry.getKey(), i);
}

View file

@ -556,6 +556,9 @@ public class OsmMapUtils {
// take centroid as the first best guess
Cell bestCell = getCentroidCell(rings);
if(bestCell == null) {
return new LatLon(minX, minY);
}
// special case for rectangular polygons
Cell bboxCell = new Cell(minX + width / 2, minY + height / 2, 0, rings);
@ -606,10 +609,13 @@ public class OsmMapUtils {
area += f * 3;
}
if (area == 0) {
LatLon p = points.get(0);
return new Cell(p.getLatitude(), p.getLongitude(), 0, rings);
}
if (area == 0) {
if (points.size() == 0) {
return null;
}
LatLon p = points.get(0);
return new Cell(p.getLatitude(), p.getLongitude(), 0, rings);
}
return new Cell(x / area, y / area, 0, rings);
}

View file

@ -1,8 +1,9 @@
package net.osmand.router;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXExtensionsReader;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.RouteSegment;
import net.osmand.GPXUtilities.RouteType;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.Location;
import net.osmand.PlatformUtil;
@ -10,11 +11,8 @@ import net.osmand.binary.BinaryMapRouteReaderAdapter.RouteRegion;
import net.osmand.binary.RouteDataBundle;
import net.osmand.binary.RouteDataObject;
import net.osmand.binary.StringBundle;
import net.osmand.binary.StringBundleReader;
import net.osmand.binary.StringBundleXmlReader;
import org.apache.commons.logging.Log;
import org.xmlpull.v1.XmlPullParser;
import java.io.File;
import java.io.FileInputStream;
@ -31,6 +29,10 @@ public class RouteImporter {
private File file;
private GPXFile gpxFile;
private List<RouteSegmentResult> route = new ArrayList<>();
private RouteRegion region = new RouteRegion();
private RouteDataResources resources = new RouteDataResources();
public RouteImporter(File file) {
this.file = file;
}
@ -40,90 +42,14 @@ public class RouteImporter {
}
public List<RouteSegmentResult> importRoute() {
final List<RouteSegmentResult> route = new ArrayList<>();
final RouteRegion region = new RouteRegion();
final RouteDataResources resources = new RouteDataResources();
GPXExtensionsReader extensionsReader = new GPXExtensionsReader() {
@Override
public boolean readExtensions(GPXFile res, XmlPullParser parser) throws Exception {
if (!resources.hasLocations()) {
List<Location> locations = resources.getLocations();
double lastElevation = HEIGHT_UNDEFINED;
if (res.tracks.size() > 0 && res.tracks.get(0).segments.size() > 0 && res.tracks.get(0).segments.get(0).points.size() > 0) {
for (WptPt point : res.tracks.get(0).segments.get(0).points) {
Location loc = new Location("", point.getLatitude(), point.getLongitude());
if (!Double.isNaN(point.ele)) {
loc.setAltitude(point.ele);
lastElevation = point.ele;
} else if (lastElevation != HEIGHT_UNDEFINED) {
loc.setAltitude(lastElevation);
}
locations.add(loc);
}
}
}
String tag = parser.getName();
if ("route".equals(tag)) {
int tok;
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (tok == XmlPullParser.START_TAG) {
tag = parser.getName();
if ("segment".equals(tag)) {
StringBundleReader bundleReader = new StringBundleXmlReader(parser);
RouteDataObject object = new RouteDataObject(region);
RouteSegmentResult segment = new RouteSegmentResult(object);
bundleReader.readBundle();
segment.readFromBundle(new RouteDataBundle(resources, bundleReader.getBundle()));
route.add(segment);
}
} else if (tok == XmlPullParser.END_TAG) {
tag = parser.getName();
if ("route".equals(tag)) {
return true;
}
}
}
} else if ("types".equals(tag)) {
int tok;
int i = 0;
while ((tok = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (tok == XmlPullParser.START_TAG) {
tag = parser.getName();
if ("type".equals(tag)) {
StringBundleReader bundleReader = new StringBundleXmlReader(parser);
bundleReader.readBundle();
StringBundle bundle = bundleReader.getBundle();
String t = bundle.getString("t", null);
String v = bundle.getString("v", null);
region.initRouteEncodingRule(i++, t, v);
}
} else if (tok == XmlPullParser.END_TAG) {
tag = parser.getName();
if ("types".equals(tag)) {
return true;
}
}
}
}
return false;
}
};
if (gpxFile != null) {
GPXUtilities.loadGPXFile(null, gpxFile, extensionsReader);
for (RouteSegmentResult segment : route) {
segment.fillNames(resources);
}
parseRoute();
} else if (file != null) {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
GPXFile gpxFile = GPXUtilities.loadGPXFile(fis, null, extensionsReader);
for (RouteSegmentResult segment : route) {
segment.fillNames(resources);
}
gpxFile = GPXUtilities.loadGPXFile(fis);
parseRoute();
gpxFile.path = file.getAbsolutePath();
gpxFile.modifiedTime = file.lastModified();
} catch (IOException e) {
@ -139,7 +65,51 @@ public class RouteImporter {
}
}
}
return route;
}
private void parseRoute() {
collectLocations();
collectSegments();
collectTypes();
for (RouteSegmentResult segment : route) {
segment.fillNames(resources);
}
}
private void collectLocations() {
List<Location> locations = resources.getLocations();
double lastElevation = HEIGHT_UNDEFINED;
if (gpxFile.tracks.size() > 0 && gpxFile.tracks.get(0).segments.size() > 0 && gpxFile.tracks.get(0).segments.get(0).points.size() > 0) {
for (WptPt point : gpxFile.tracks.get(0).segments.get(0).points) {
Location loc = new Location("", point.getLatitude(), point.getLongitude());
if (!Double.isNaN(point.ele)) {
loc.setAltitude(point.ele);
lastElevation = point.ele;
} else if (lastElevation != HEIGHT_UNDEFINED) {
loc.setAltitude(lastElevation);
}
locations.add(loc);
}
}
}
private void collectSegments() {
for (RouteSegment segment : gpxFile.routeSegments) {
RouteDataObject object = new RouteDataObject(region);
RouteSegmentResult segmentResult = new RouteSegmentResult(object);
segmentResult.readFromBundle(new RouteDataBundle(resources, segment.getStringBundle()));
route.add(segmentResult);
}
}
private void collectTypes() {
int i = 0;
for (RouteType routeType : gpxFile.routeTypes) {
StringBundle bundle = routeType.getStringBundle();
String t = bundle.getString("t", null);
String v = bundle.getString("v", null);
region.initRouteEncodingRule(i++, t, v);
}
}
}

View file

@ -310,7 +310,7 @@ public class RoutePlannerFrontEnd {
System.out.println(gctx);
}
if (resultMatcher != null) {
resultMatcher.publish(gctx);
resultMatcher.publish(gctx.calculationCancelled ? null : gctx);
}
gctx.calculationDone = true;
return gctx;

View file

@ -67,7 +67,7 @@
<string name="shared_string_apply">تطبيق</string>
<string name="shared_string_enabled">مفعل</string>
<string name="units_and_formats">الوحدات والأشكال</string>
<string name="unit_of_length_descr">اختيار الوحدات: كم، ميل، ميل بحري.. إلخ.</string>
<string name="unit_of_length_descr">اختيار الوحدات: كم، ميل، ميلٌ بحري.. إلخ.</string>
<string name="unit_of_length">وحدات الطول</string>
<string name="last_update_from_telegram_date">آخر تحديث من تيليجرام: %1$s</string>
<string name="last_response_date">الرد الأخير:٪ 1 $ s</string>

View file

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M13,3H3V5H13V3Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M13,7H3V9H13V7Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M13,13H7V11H13V13Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M3,13H5V11H3V13Z"
android:fillColor="#ffffff"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,15C8,15 13,9.5714 13,6C13,3.1429 10.7614,1 8,1C5.2386,1 3,3.1429 3,6C3,9.5714 8,15 8,15ZM8,8C9.1046,8 10,7.1046 10,6C10,4.8954 9.1046,4 8,4C6.8954,4 6,4.8954 6,6C6,7.1046 6.8954,8 8,8Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M8,15C8,15 13,9.5714 13,6C13,3.1429 10.7614,1 8,1C5.2386,1 3,3.1429 3,6C3,9.5714 8,15 8,15ZM8,8C9.1046,8 10,7.1046 10,6C10,4.8954 9.1046,4 8,4C6.8954,4 6,4.8954 6,6C6,7.1046 6.8954,8 8,8Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
</vector>

View file

@ -4,17 +4,17 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M10.5646,1.0929C11.0348,1.0316 11.514,1 12,1C12.486,1 12.9652,1.0316 13.4354,1.0929L13.1767,3.0761C12.7921,3.0259 12.3993,3 12,3C11.6007,3 11.2079,3.0259 10.8233,3.0761L10.5646,1.0929ZM16.2109,1.8351C17.1057,2.2061 17.9406,2.6917 18.6972,3.2731L17.4785,4.8589C16.8589,4.3828 16.176,3.9857 15.4448,3.6825L16.2109,1.8351ZM5.3028,3.2731C6.0595,2.6917 6.8942,2.2062 7.7891,1.8351L8.5552,3.6825C7.824,3.9857 7.1411,4.3828 6.5215,4.8589L5.3028,3.2731ZM20.7269,5.3028C21.3083,6.0595 21.7939,6.8942 22.1649,7.7891L20.3175,8.5552C20.0143,7.824 19.6172,7.1411 19.1411,6.5215L20.7269,5.3028ZM1.8351,7.7891C2.2061,6.8942 2.6917,6.0595 3.2731,5.3028L4.8589,6.5215C4.3828,7.1411 3.9857,7.824 3.6825,8.5552L1.8351,7.7891ZM22.9071,10.5646C22.9684,11.0348 23,11.514 23,12C23,12.486 22.9684,12.9652 22.9071,13.4354L20.9239,13.1767C20.9741,12.7921 21,12.3993 21,12C21,11.6007 20.9741,11.2079 20.9239,10.8233L22.9071,10.5646ZM1,12C1,11.514 1.0316,11.0348 1.0929,10.5646L3.0761,10.8233C3.0259,11.2079 3,11.6007 3,12C3,12.3993 3.0259,12.7921 3.0761,13.1767L1.0929,13.4354C1.0316,12.9652 1,12.486 1,12ZM22.1649,16.2109C21.7939,17.1057 21.3083,17.9406 20.7269,18.6972L19.1411,17.4785C19.6172,16.8589 20.0143,16.176 20.3175,15.4448L22.1649,16.2109ZM3.2731,18.6972C2.6917,17.9406 2.2062,17.1058 1.8351,16.2109L3.6825,15.4448C3.9857,16.176 4.3828,16.8589 4.8589,17.4785L3.2731,18.6972ZM7.7891,22.1649C6.8942,21.7939 6.0595,21.3083 5.3028,20.7269L6.5215,19.1411C7.1411,19.6172 7.824,20.0143 8.5552,20.3175L7.7891,22.1649ZM18.6972,20.7269C17.9406,21.3083 17.1058,21.7939 16.2109,22.1649L15.4448,20.3175C16.176,20.0143 16.8589,19.6172 17.4785,19.1411L18.6972,20.7269ZM12,23C11.514,23 11.0348,22.9684 10.5646,22.9071L10.8233,20.9239C11.2079,20.9741 11.6007,21 12,21C12.3993,21 12.7921,20.9741 13.1767,20.9239L13.4354,22.9071C12.9652,22.9684 12.486,23 12,23Z"
android:pathData="M10.5646,1.0929C11.0348,1.0316 11.514,1 12,1C12.486,1 12.9652,1.0316 13.4354,1.0929C13.9831,1.1644 14.3691,1.6662 14.2977,2.2139C14.2263,2.7615 13.7244,3.1476 13.1767,3.0761C12.7921,3.0259 12.3993,3 12,3C11.6007,3 11.2079,3.0259 10.8233,3.0761C10.2756,3.1476 9.7737,2.7615 9.7023,2.2139C9.6309,1.6662 10.0169,1.1644 10.5646,1.0929ZM17.2949,3.4567C17.6314,3.0188 18.2593,2.9366 18.6972,3.2731C19.4588,3.8584 20.1416,4.5412 20.7269,5.3028C21.0634,5.7407 20.9812,6.3686 20.5433,6.7051C20.1054,7.0416 19.4776,6.9594 19.1411,6.5215C18.6617,5.8976 18.1024,5.3383 17.4785,4.8589C17.0406,4.5224 16.9584,3.8946 17.2949,3.4567ZM6.7051,3.4567C7.0416,3.8946 6.9594,4.5224 6.5215,4.8589C5.8976,5.3383 5.3383,5.8976 4.8589,6.5215C4.5224,6.9594 3.8946,7.0416 3.4567,6.7051C3.0188,6.3686 2.9366,5.7407 3.2731,5.3028C3.8584,4.5412 4.5412,3.8584 5.3028,3.2731C5.7407,2.9366 6.3686,3.0188 6.7051,3.4567ZM21.7861,9.7023C22.3338,9.6309 22.8356,10.0169 22.9071,10.5646C22.9684,11.0348 23,11.514 23,12C23,12.486 22.9684,12.9652 22.9071,13.4354C22.8356,13.9831 22.3338,14.3691 21.7861,14.2977C21.2385,14.2263 20.8524,13.7244 20.9239,13.1767C20.9741,12.7921 21,12.3993 21,12C21,11.6007 20.9741,11.2079 20.9239,10.8233C20.8524,10.2756 21.2385,9.7737 21.7861,9.7023ZM2.2139,9.7023C2.7615,9.7737 3.1476,10.2756 3.0761,10.8233C3.0259,11.2079 3,11.6007 3,12C3,12.3993 3.0259,12.7921 3.0761,13.1767C3.1476,13.7244 2.7615,14.2263 2.2139,14.2977C1.6662,14.3691 1.1644,13.9831 1.0929,13.4354C1.0316,12.9652 1,12.486 1,12C1,11.514 1.0316,11.0348 1.0929,10.5646C1.1644,10.0169 1.6662,9.6309 2.2139,9.7023ZM20.5433,17.2949C20.9812,17.6314 21.0634,18.2593 20.7269,18.6972C20.1416,19.4588 19.4588,20.1416 18.6972,20.7269C18.2593,21.0634 17.6314,20.9812 17.2949,20.5433C16.9584,20.1054 17.0406,19.4776 17.4785,19.1411C18.1024,18.6617 18.6617,18.1024 19.1411,17.4785C19.4776,17.0406 20.1054,16.9584 20.5433,17.2949ZM3.4567,17.2949C3.8946,16.9584 4.5224,17.0406 4.8589,17.4785C5.3383,18.1024 5.8976,18.6617 6.5215,19.1411C6.9594,19.4776 7.0416,20.1054 6.7051,20.5433C6.3686,20.9812 5.7407,21.0634 5.3028,20.7269C4.5412,20.1416 3.8584,19.4588 3.2731,18.6972C2.9366,18.2593 3.0188,17.6314 3.4567,17.2949ZM9.7023,21.7861C9.7737,21.2385 10.2756,20.8524 10.8233,20.9239C11.2079,20.9741 11.6007,21 12,21C12.3993,21 12.7921,20.9741 13.1767,20.9239C13.7244,20.8524 14.2263,21.2385 14.2977,21.7861C14.3691,22.3338 13.9831,22.8356 13.4354,22.9071C12.9652,22.9684 12.486,23 12,23C11.514,23 11.0348,22.9684 10.5646,22.9071C10.0169,22.8356 9.6309,22.3338 9.7023,21.7861Z"
android:strokeAlpha="0.3"
android:fillColor="#000000"
android:fillColor="#ffffff"
android:fillType="evenOdd"
android:fillAlpha="0.3"/>
<path
android:pathData="M12,6L7,17L12,15V6Z"
android:fillColor="#727272"/>
android:pathData="M12,15L9.1325,15.9559C9.0447,15.9851 8.9529,16 8.8604,16H8.809C8.3622,16 8,15.6378 8,15.191C8,15.0654 8.0292,14.9415 8.0854,14.8292L11.2764,8.4472C11.4134,8.1731 11.6936,8 12,8C12.3064,8 12.5866,8.1732 12.7236,8.4472L15.9146,14.8292C15.9708,14.9415 16,15.0654 16,15.191C16,15.6378 15.6378,16 15.191,16H15.1396C15.0471,16 14.9553,15.9851 14.8675,15.9559L12,15Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M12,6V15L17,17L12,6Z"
android:strokeAlpha="0.7"
android:fillColor="#727272"
android:fillAlpha="0.7"/>
android:pathData="M9,2C9,0.8954 9.8954,0 11,0H13C14.1046,0 15,0.8954 15,2V22C15,23.1046 14.1046,24 13,24H11C9.8954,24 9,23.1046 9,22V2Z"
android:strokeAlpha="0.2"
android:fillColor="#ffffff"
android:fillAlpha="0.2"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M15.5,6L13,6C12.4477,6 12,5.5523 12,5C12,4.4477 12.4477,4 13,4L15.5001,4C17.9853,4.0001 20,6.0148 20,8.5C20,10.9853 17.9853,13 15.5,13H8.5C7.1193,13 6,14.1193 6,15.5C6,16.8807 7.1193,18 8.5,18H16.2676C16.6134,17.4022 17.2597,17 18,17C19.1046,17 20,17.8954 20,19C20,20.1046 19.1046,21 18,21C17.2597,21 16.6134,20.5978 16.2676,20H8.5C6.0147,20 4,17.9853 4,15.5C4,13.0147 6.0147,11 8.5,11H15.5C16.8807,11 18,9.8807 18,8.5C18,7.1193 16.8807,6 15.5,6Z"
android:strokeAlpha="0.7"
android:fillColor="#ffffff"
android:fillAlpha="0.7"/>
<path
android:pathData="M9.9999,5L10.9146,6.8292C10.9708,6.9415 11,7.0654 11,7.191C11,7.6378 10.6378,8 10.191,8H10.1666C10.0566,8 9.9476,7.9782 9.8461,7.9359L4.4622,5.6926C4.1823,5.576 3.9999,5.3025 3.9999,4.9992C3.9999,4.6967 4.1813,4.4238 4.4602,4.3066L9.7876,2.0682C9.8948,2.0232 10.0099,2 10.1261,2L10.191,2C10.6378,2 11,2.3622 11,2.8091C10.9999,2.9346 10.9707,3.0585 10.9145,3.1708L9.9999,5Z"
android:fillColor="#ffffff"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8.8957,10.31C8.202,10.7471 7.3805,11 6.5,11C4.0147,11 2,8.9853 2,6.5C2,4.0147 4.0147,2 6.5,2C8.9853,2 11,4.0147 11,6.5C11,7.3805 10.7471,8.202 10.31,8.8957L13.7071,12.2929L12.2929,13.7071L8.8957,10.31ZM9,6.5C9,7.8807 7.8807,9 6.5,9C5.1193,9 4,7.8807 4,6.5C4,5.1193 5.1193,4 6.5,4C7.8807,4 9,5.1193 9,6.5Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M6,1H10V3H13V5H3V3H6V1Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M12,7H4V14C4,14.5523 4.4477,15 5,15H11C11.5523,15 12,14.5523 12,14V7Z"
android:fillColor="#ffffff"/>
</vector>

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
android:id="@+id/button"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding">
<LinearLayout
android:id="@+id/button_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:duplicateParentState="true"
tools:ignore="UselessParent">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/button_text"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small"
android:gravity="center"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
android:duplicateParentState="true"
tools:text="Button"
android:paddingStart="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding_small" />
</LinearLayout>
</LinearLayout>

View file

@ -455,9 +455,8 @@
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/context_menu_directions_button"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:gravity="end|center_vertical"
android:paddingLeft="@dimen/context_menu_padding_margin_default"

View file

@ -764,7 +764,7 @@
<string name="incomplete_locale">ناقص</string>
<string name="shared_string_next">التالي</string>
<string name="shared_string_previous">السابق</string>
<string name="unit_of_length_descr">اختيار الوحدات: كم، ميل، ميل بحري.. إلخ.</string>
<string name="unit_of_length_descr">اختيار الوحدات: كم، ميل، ميلٌ بحري.. إلخ.</string>
<string name="unit_of_length">وحدات الطول</string>
<string name="si_mi_feet">ميل ، قدم</string>
<string name="si_mi_yard">ميل ، ياردة</string>
@ -1964,8 +1964,8 @@
<string name="show_poi_over_map_description">عرض POI على الخريطة (استخدم آخر تصفية مستخدمة).</string>
<string name="navigate_point_top_text">أدخل خط العرض وخط الطول في النمط المحدد (د - درجات، د - دقائق، ث - ثواني)</string>
<string name="navigate_point_format_D">DDD.DD</string>
<string name="navigate_point_format_DM">DDD MM.MM</string>
<string name="navigate_point_format_DMS">DDD MM SS.SS</string>
<string name="navigate_point_format_DM">DDD MM.MMM</string>
<string name="navigate_point_format_DMS">DDD MM SS.S</string>
<string name="plugin_touringview_descr">تفعيل هذه الرؤية يغير نمط خريطة أوسماند إلى \'نمط التجوال\'، هذا النمط يوفر رؤية غنية بالتفاصيل للمسافرين والسائقين المحترفين.
\n
\nتوفر هذه الرؤية في أي تكبير معين للخريطة أكبر قدر ممكن من تفاصيل السفر المتاحة في بيانات الخريطة (خاصة الطرق، المسارات، المعابر وعلامات التوجيه).
@ -2288,7 +2288,7 @@
<string name="mapillary_widget">ويدجت مابيلاري</string>
<string name="mapillary_widget_descr">يسمح لك بالمساهمة بسرعة لمابيلاري.</string>
<string name="mapillary_descr">صور شوارع متاحة على الإنترنت للجميع. اكتشف أماكن، تعاون، والتقط صورا للعالم.</string>
<string name="mapillary">Mapillary مابيلاري</string>
<string name="mapillary">صور للشارع</string>
<string name="plugin_mapillary_descr">صور شوارع متاحة للجميع. اكتشف أماكن، تعاون، والتقط صورا للعالم.</string>
<string name="private_access_routing_req">الوجهة الخاص بك تقع في منطقة ذات ولوج خاص. هل تسمح بالدخول إلى الطرق الخاصة لهذه الرحلة؟</string>
<string name="quick_action_showhide_osmbugs_descr">زر يظهر أو يخفي ملاحظات OSM على الخريطة.</string>
@ -3842,4 +3842,7 @@
\n
\nفي الخطوة التالية ، ستحتاج إلى تحديد ملف تعريف الملاحة لاكتشاف الطرق المسموح بها وبداية المسافة لتقريب تتبعك بالطرق.</string>
<string name="threshold_distance">بداية المسافة</string>
<string name="street_level_imagery">صور للشارع</string>
<string name="plan_route_exit_dialog_descr">هل أنت متأكد أنك تريد إغلاق مسار الخطة دون حفظ؟ سوف تفقد كل التغييرات.</string>
<string name="in_case_of_reverse_direction">في حالة الاتجاه المعاكس</string>
</resources>

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="poi_shop">ⵜⴰⵃⴰⵏⵓⵜ</string>
<string name="poi_video_telephone">ⴰⴼⵉⴷⵢⵓ</string>
<string name="poi_climbing_crag">ⵢⴰⵀ</string>
<string name="poi_books_type">ⵉⴷⵍⵉⵙⵏ</string>
<string name="poi_glacier_type">ⴰⵙⵔⵜⵓ ⴰⴳⵔⵙⴰⵏ</string>
<string name="poi_dish">ⴰⵟⴱⵙⵉⵍ</string>
<string name="poi_tents">ⴰⵅⵅⴰⵎ</string>
<string name="poi_shelter_type">ⴰⵙⵔⵜⵓ</string>
<string name="poi_recycling_type">ⴰⵙⵔⵜⵓ</string>
<string name="poi_covered">ⵉⵜⵜⵡⴰⴷⵍ</string>
<string name="poi_traffic_signals_sound">ⴰⵎⵙⵍⴰⵢ</string>
<string name="poi_fire_hydrant_water_source">ⴰⵖⴱⴰⵍⵓ ⵡⴰⵎⴰⵏ</string>
<string name="poi_fire_hydrant_position">ⴰⵏⵙⴰ</string>
</resources>

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View file

@ -3789,4 +3789,5 @@ Abasta l\'àrea: %1$s x %2$s</string>
\nUn dia equival a 1.440 minuts.
\nUna setmana té 10.080 minuts.
\nUn mes dura 43.829 minuts.</string>
<string name="in_case_of_reverse_direction">Cas de sentit invers</string>
</resources>

View file

@ -1711,7 +1711,7 @@
<string name="poi_automated_no">Μη αυτόματο</string>
<string name="poi_full_service_yes">Πλήρης εξυπηρέτηση</string>
<string name="poi_brushless_yes">Ναι</string>
<string name="poi_car_wash_no">Πλύσιμο αυτοκινήτου: όχι</string>
<string name="poi_car_wash_no">Όχι</string>
<string name="poi_public_bath">Δημόσια λουτρά</string>
<string name="poi_male_yes">Άνδρες</string>
<string name="poi_male_no">Απαγορευμένο για άνδρες</string>
@ -3692,4 +3692,123 @@
<string name="poi_video_telephone">Βίντεο</string>
<string name="poi_sms">SMS</string>
<string name="poi_bath_open_air">Σε ανοιχτό χώρο</string>
<string name="poi_piste_ref">Αριθμός αναφοράς πίστας</string>
<string name="poi_bowling_alley">Κέντρο μπόουλινγκ</string>
<string name="poi_shop_security">Είδη ασφαλείας</string>
<string name="poi_mountain_rescue">Διάσωση βουνού</string>
<string name="poi_paintball">Χρωματοσφαίριση</string>
<string name="poi_memorial_ghost_bike">Ποδήλατο φάντασμα</string>
<string name="poi_volcano_number_of_eruptions">Αριθμός εκρήξεων</string>
<string name="poi_volcano_status_active">Ενεργό</string>
<string name="poi_volcano_status_extinct">Εσβεσμένο</string>
<string name="poi_volcano_type_mud">Λάσπη</string>
<string name="poi_volcano_type_caldera">Κρατήρας</string>
<string name="poi_volcano_type_shield">Ασπίδα</string>
<string name="poi_url">URL</string>
<string name="poi_monastery_type_canonry">Τύπος μονής: κανονική</string>
<string name="poi_community_gender_female">Είδος κοινοβίου: γυναικείο</string>
<string name="poi_community_gender_male">Είδος κοινοβίου: ανδρικό</string>
<string name="poi_bath_open_air_no">Όχι</string>
<string name="poi_cash_withdrawal_foreign_cards">Ανάληψη μετρητών: ξένες κάρτες</string>
<string name="poi_cash_withdrawal_purchase_required_no">Ανάληψη μετρητών: δεν απαιτείται αγορά</string>
<string name="poi_cash_withdrawal_type_self_checkout">Τύπος ανάληψης μετρητών: αυτόματη ολοκλήρωση</string>
<string name="poi_craft_floorer">Πατωματζής</string>
<string name="poi_goods_yes">Ναι</string>
<string name="poi_volcano_status_inactive">Ανενεργό</string>
<string name="poi_volcano_status_dormant">Ανενεργό</string>
<string name="poi_volcano_last_eruption">Τελευταία έκρηξη</string>
<string name="poi_volcano_type_lava_dome">Ηφαιστειακός θόλος</string>
<string name="poi_volcano_type_maar">Ηφαιστειακή λίμνη</string>
<string name="poi_volcano_type_stratovolcano">Στρωματοηφαίστειο</string>
<string name="poi_grave">Τάφος</string>
<string name="poi_tourist_camp">Τουριστικό κατάλυμα</string>
<string name="poi_monastery_type_convent">Τύπος μονής: γυναικεία</string>
<string name="poi_cash_withdrawal_migros_bank">Τράπεζα Migros</string>
<string name="poi_cash_withdrawal_fee_no">Τέλος ανάληψης μετρητών: όχι</string>
<string name="poi_cash_withdrawal_currency">Νόμισμα ανάληψης μετρητών</string>
<string name="poi_cash_withdrawal_operator">Χειριστής ανάληψης μετρητών</string>
<string name="poi_disabled_yes">Ναι</string>
<string name="poi_hgv_permissive">Ανεκτή</string>
<string name="poi_volcano_type_scoria">Σκουριά</string>
<string name="poi_parking_space">Χώρος στάθμευσης</string>
<string name="poi_community_gender_mixed">Είδος κοινότητας: μικτή</string>
<string name="poi_monastery_type_clerks_regular">Τύπος μονής: κανονικοί κληρικοί</string>
<string name="poi_monastery_type_hermitage">Τύπος μονής: ερημητήριο</string>
<string name="poi_monastery_type_monastics">Τύπος μονής: μοναστική</string>
<string name="poi_bath_open_air_yes">Ναι</string>
<string name="poi_bath_type_foot_bath">Ποδόλουτρο</string>
<string name="poi_bath_type_lake">Λίμνη</string>
<string name="poi_bath_type_river">Ποταμός</string>
<string name="poi_bath_type_thermal">Θερμικό</string>
<string name="poi_bath_type_hammam">Χαμάμ</string>
<string name="poi_bath_type_onsen">Όνσεν</string>
<string name="poi_bath_type_hot_spring">Θερμή πηγή</string>
<string name="poi_cash_withdrawal_postbank">Postbank</string>
<string name="poi_cash_withdrawal_girocard">Girocard</string>
<string name="poi_cash_withdrawal_postfinance_card">Κάρτα Postfinance</string>
<string name="poi_cash_withdrawal_purchase_minimum">Ανάληψη μετρητών: ελάχιστη αγορά</string>
<string name="poi_cash_withdrawal_fee_yes">Τέλος ανάληψης μετρητών: ναι</string>
<string name="poi_cash_withdrawal_purchase_required_yes">Ανάληψη μετρητών: απαιτείται αγορά</string>
<string name="poi_cash_withdrawal_limit">Όριο ανάληψης μετρητών</string>
<string name="poi_cash_withdrawal_type_checkout">Τύπος ανάληψης μετρητών: ταμείο</string>
<string name="poi_cash_withdrawal">Ανάληψη μετρητών</string>
<string name="poi_cash_withdrawal_yes">Ανάληψη μετρητών: ναι</string>
<string name="poi_pet_grooming">Καλλωπισμός κατοικίδιων</string>
<string name="poi_charge">Χρέωση</string>
<string name="poi_craft_cabinet_maker">Επιπλοποιός</string>
<string name="poi_craft_bakery">Φούρνος</string>
<string name="poi_craft_joiner">Ξυλουργός</string>
<string name="poi_craft_distillery">Αποστακτήριο</string>
<string name="poi_craft_builder">Κατασκευαστής</string>
<string name="poi_health_food">Υγιεινά τρόφιμα</string>
<string name="poi_cellar_entrance">Είσοδος κάβας</string>
<string name="poi_disabled_designated">Δηλωμένη</string>
<string name="poi_goods_designated">Δηλωμένη</string>
<string name="poi_hgv_delivery">Διανομή</string>
<string name="poi_hgv_designated">Δηλωμένη</string>
<string name="poi_hgv_destination">Προορισμός</string>
<string name="poi_hgv_yes">Ναι</string>
<string name="poi_mofa_designated">Δηλωμένη</string>
<string name="poi_snowmobile_private">Πρόσβαση χιονοοχήματος: ιδιωτική</string>
<string name="poi_ski_yes">Χιονοδρομική σύμβαση: ναι</string>
<string name="poi_rtsa_scale_3b"></string>
<string name="poi_rtsa_scale_3a">3А</string>
<string name="poi_rtsa_scale_2b"></string>
<string name="poi_rtsa_scale_2a">2А</string>
<string name="poi_rtsa_scale_1b"></string>
<string name="poi_rtsa_scale_1a">1А</string>
<string name="poi_rtsa_scale_nc">н/к</string>
<string name="poi_borough">Διαμέρισμα</string>
<string name="poi_traffic_signals_arrow_yes">Ναι</string>
<string name="poi_traffic_signals_vibration_yes">Ναι</string>
<string name="poi_traffic_signals_vibration_no">Δόνηση: όχι</string>
<string name="poi_pump_status_missing_beam">Κατάσταση αντλίας: ελλείπων βραχίονας</string>
<string name="poi_osmand_fire_hydrant_pressure_suction">Αναρρόφηση</string>
<string name="poi_osmand_fire_hydrant_pressure_pressurized">Πιεσμένο</string>
<string name="poi_fire_hydrant_style_water_source_groundwater">Υπόγεια ύδατα</string>
<string name="poi_fire_hydrant_type_pipe">Σωλήνας</string>
<string name="poi_drinking_water_refill_network">Δίκτυο ξαναγεμίσματος πόσιμου νερού</string>
<string name="poi_drinking_water_refill_no">Ξαναγέμισμα πόσιμου νερού: όχι</string>
<string name="poi_drinking_water_refill_yes">Ξαναγέμισμα πόσιμου νερού: ναι</string>
<string name="poi_seamark_obstruction">Εμπόδιο</string>
<string name="poi_seamark_water_level_below_mwl">Επίπεδο νερού: Κάτω από το διάμεσο επίπεδο νερού</string>
<string name="poi_seamark_water_level_above_mwl">Επίπεδο νερού: πάνω από το διάμεσο επίπεδο νερού</string>
<string name="poi_seamark_water_level_floating">Επίπεδο νερού: επιπλέον</string>
<string name="poi_seamark_water_level_floods">Επίπεδο νερού: κατακλυσμένο</string>
<string name="poi_seamark_water_level_awash">Επίπεδο νερού: πλημμυρισμένο</string>
<string name="poi_seamark_water_level_covers">Επίπεδο νερού: καλυμμένο</string>
<string name="poi_seamark_water_level_dry">Επίπεδο νερού: ξηρό</string>
<string name="poi_seamark_water_level_submerged">Επίπεδο νερού: βυθισμένο</string>
<string name="poi_seamark_water_level_part_submerged">Επίπεδο νερού: μερικώς βυθισμένο</string>
<string name="poi_tactile_paving_incorrect">Εσφαλμένο</string>
<string name="poi_tactile_paving_primitive">Πρωτογενές</string>
<string name="poi_tactile_paving_contrasted">Αντίθετο</string>
<string name="poi_traffic_signals_sound_locate">Μόνο όταν επιτρέπεται το περπάτημα</string>
<string name="poi_internet_access_fee_customers">Σήμα για την εύρεση του πόλου</string>
<string name="poi_video_no">Όχι</string>
<string name="poi_booth">Τύπος θαλάμου</string>
<string name="poi_covered_booth">Θάλαμος</string>
<string name="poi_sms_yes">Ναι</string>
<string name="poi_dive_centre">Κέντρο αυτόνομης κατάδυσης</string>
<string name="poi_resort_hunting">Βάση κυνηγιού</string>
</resources>

View file

@ -1782,7 +1782,7 @@
<string name="mapillary_widget">Γραφικό στοιχείο Mapillary</string>
<string name="mapillary_widget_descr">Επιτρέπει γρήγορες συνεισφορές στο Mapillary.</string>
<string name="mapillary_descr">Διαδικτυακές φωτογραφίες δρόμου για όλους. Ανακαλύψτε θέσεις, συνεργαστείτε, αποτυπώστε τον κόσμο.</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Εικόνες επιπέδου οδού</string>
<string name="plugin_mapillary_descr">Φωτογραφίες δρόμου για όλους. Ανακαλύψτε θέσεις, συνεργαστείτε, αποτυπώστε τον κόσμο.</string>
<string name="private_access_routing_req">Ο προορισμός σας βρίσκεται σε ιδιωτική περιοχή. Να επιτραπεί η πρόσβαση σε ιδιωτικούς δρόμους για αυτό το ταξίδι;</string>
<string name="restart_search">Επανεκκίνηση αναζήτησης</string>

View file

@ -2419,7 +2419,7 @@
<string name="nothing_found">Trovis nenion</string>
<string name="nothing_found_descr">Ŝanĝu serĉpeton aŭ pliigu radiuson de serĉo.</string>
<string name="private_access_routing_req">Via celo troviĝas en privata tereno. Ĉu permesi aliron al privataj vojoj por tiu ĉi kurso\?</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Strat-nivela fotaro</string>
<string name="mapillary_widget">Mapillary-fenestraĵo</string>
<string name="mapillary_widget_descr">Ebligas rapide kontribui al Mapillary.</string>
<string name="mapillary_descr">Enretaj strat-nivelaj fotoj por ĉiuj. Esplori lokojn, kunlabori kaj foti la mondon.</string>
@ -3852,4 +3852,7 @@
<string name="threshold_distance">Sojla distanco</string>
<string name="navigation_profile">Profilo de navigo</string>
<string name="rourte_between_points_add_track_desc">Elektu dosieron de spuro al kiu nova segmento estos aldonita.</string>
<string name="street_level_imagery">Strat-nivela fotaro</string>
<string name="plan_route_exit_dialog_descr">Ĉu vi certe volas fermi planadon de kurso sen konservi\? Ĉiuj viaj ŝanĝoj perdiĝos.</string>
<string name="in_case_of_reverse_direction">Kiam en inversa direkto</string>
</resources>

View file

@ -2424,7 +2424,7 @@
<string name="nothing_found">Nada encontrado</string>
<string name="nothing_found_descr">Cambiar la búsqueda o aumentar su radio.</string>
<string name="private_access_routing_req">El destino se ubica en un área de acceso privado. ¿Permitir el uso de caminos privados para este viaje\?</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Imágenes a nivel de calle</string>
<string name="mapillary_widget">Widget de Mapillary</string>
<string name="mapillary_widget_descr">Permite realizar contribuciones rápidas a Mapillary.</string>
<string name="mapillary_descr">Fotos a nivel de calle en línea para todos. Descubre sitios, colabora, captura el mundo.</string>
@ -3857,4 +3857,7 @@
<string name="threshold_distance">Distancia de umbral</string>
<string name="navigation_profile">Perfil de navegación</string>
<string name="rourte_between_points_add_track_desc">Elige un archivo de traza al que se añadirá un nuevo segmento.</string>
<string name="street_level_imagery">Imágenes a nivel de calle</string>
<string name="plan_route_exit_dialog_descr">¿Cerrar el plan de ruta sin guardar\? Se perderán todos los cambios.</string>
<string name="in_case_of_reverse_direction">En caso de dirección inversa</string>
</resources>

View file

@ -722,7 +722,7 @@
<string name="poi_landuse_railway">Zone ferroviaire</string>
<string name="poi_village_green">Village green (GB)</string>
<string name="poi_sailing">Navigation à voile</string>
<string name="poi_charity">Magasin caritatif</string>
<string name="poi_charity">Boutique caritative</string>
<string name="poi_tomb">Sépulture</string>
<string name="poi_wilderness_hut">Refuge de bivouac non gardé</string>
<string name="poi_payment_terminal">Terminal de paiement</string>

View file

@ -87,7 +87,7 @@
<string name="old_poi_file_should_be_deleted">Le fichier de points d\'intérêt \'%1$s\' est obsolète et peut être supprimé.</string>
<string name="update_poi_file_not_found">Fichier local de gestion des modifications de points d\'intérêt introuvable, et ne peut être créé.</string>
<string name="button_upgrade_osmandplus">Mettre à jour OsmAnd+</string>
<string name="map_version_changed_info">Téléchargez la nouvelle version de l\'application pour utiliser les nouvelle cartes.</string>
<string name="map_version_changed_info">Téléchargez la nouvelle version de l\'application pour utiliser les nouvelles cartes.</string>
<string name="shared_string_rename">Renommer</string>
<string name="poi_filter_nominatim">Recherche OSM en ligne</string>
<string name="search_position_current_location_search">Recherche de la position…</string>
@ -1121,7 +1121,7 @@
<string name="shared_string_favorite">Favori</string>
<string name="route_preferences">Préférences d\'itinéraire</string>
<string name="route_info">Informations sur l\'itinéraire</string>
<string name="keep_and_add_destination_point">Ajouter comme destination suivante</string>
<string name="keep_and_add_destination_point">Ajouter comme destination</string>
<string name="use_displayed_track_for_navigation">Souhaitez-vous suivre la trace affichée à l\'écran ?</string>
<string name="gpx_option_calculate_first_last_segment">Calculer un itinéraire OsmAnd pour le début et la fin de l\'itinéraire</string>
<string name="calculate_osmand_route_without_internet">Calcul de l\'itinéraire hors-ligne</string>
@ -1340,7 +1340,7 @@
\n- Synchroniser les groupes et les appareils avec le serveur;
\n- Gérer les groupes et les appareils depuis un espace privé sur le site Web.</string>
<string name="anonymous_user">Utilisateur anonyme</string>
<string name="logged_as">Connecté entant que %1$s</string>
<string name="logged_as">Connecté en tant que %1$s</string>
<string name="rendering_category_details">Détails</string>
<string name="rendering_category_transport">Transports en commun</string>
<string name="rendering_category_others">Autres caractéristiques de la carte</string>
@ -2372,7 +2372,7 @@
<string name="online_photos">Photos en ligne</string>
<string name="no_photos_descr">Aucune photo pour ce lieu.</string>
<string name="shared_string_install">Installer</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Photos des rues</string>
<string name="open_mapillary">Ouvrir Mapillary</string>
<string name="improve_coverage_mapillary">Améliorez la couverture photo avec Mapillary</string>
<string name="improve_coverage_install_mapillary_desc">Installez Mapillary pour ajouter des photos à cet emplacement de la carte.</string>
@ -2527,7 +2527,7 @@
<string name="add_location_as_first_point_descr">Ajoutez votre position comme point de départ pour calculer l\'itinéraire.</string>
<string name="my_location">Ma position</string>
<string name="shared_string_finish">Terminer</string>
<string name="plan_route">Itinéraire planifié</string>
<string name="plan_route">Planifier un itinéraire</string>
<string name="shared_string_sort">Trier</string>
<string name="coordinate_input">Saisie des coordonnées</string>
<string name="marker_save_as_track_descr">Exporter vos marques dans le fichier GPX suivant :</string>
@ -2660,9 +2660,9 @@
<string name="tunnel_warning">En approche d\'un tunnel</string>
<string name="show_tunnels">Tunnels</string>
<string name="shared_string_current">Actuelle</string>
<string name="last_intermediate_dest_description">Ajoute une étape</string>
<string name="first_intermediate_dest_description">Ajoute comme première étape</string>
<string name="subsequent_dest_description">Monter et définir comme Arrivée</string>
<string name="last_intermediate_dest_description">Ajouter comme dernière étape</string>
<string name="first_intermediate_dest_description">Ajouter comme première étape</string>
<string name="subsequent_dest_description">Ajouter comme arrivée (l\'arrivée précédente devient la dernière étape)</string>
<string name="make_as_start_point">Utiliser ce point comme départ</string>
<string name="map_import_error">Erreur d\'import de la carte</string>
<string name="map_imported_successfully">Carte importée</string>
@ -2911,7 +2911,7 @@
<string name="sit_on_the_stop">Panneau d\'affichage à l\'arrêt</string>
<string name="quick_action_show_hide_gpx_tracks_descr">Bouton affichant ou masquant les traces GPX sélectionnées sur la carte.</string>
<string name="transfers_size">%1$d transferts</string>
<string name="add_start_and_end_points">Ajouter un point de départ et d\'arrivée</string>
<string name="add_start_and_end_points">Ajoutez un point de départ et d\'arrivée</string>
<string name="route_add_start_point">Ajouter un point de départ</string>
<string name="route_descr_select_start_point">Sélectionnez un point de départ</string>
<string name="rendering_attr_surface_unpaved_name">Non revêtu</string>
@ -3102,7 +3102,7 @@
<string name="rendering_attr_tracktype_grade4_name">Principalement non-compact</string>
<string name="rendering_attr_tracktype_grade5_name">Non-compact</string>
<string name="routeInfo_tracktype_name">Dureté de la surface</string>
<string name="shared_string_file_is_saved">Gain de %s</string>
<string name="shared_string_file_is_saved">%s enregistré</string>
<string name="shared_string_open_track">Ouvrir la trace</string>
<string name="shared_string_track_is_saved">Trace %s enregistrée</string>
<string name="shared_string_crash">Oups</string>
@ -3446,7 +3446,7 @@
<string name="multimedia_photo_play_sound">Son de la prise de vue</string>
<string name="osm_authorization_success">L\'autorisation a été accordée</string>
<string name="search_offline_geo_error">Impossible d\'analyser le geo intent \'%s\'.</string>
<string name="monitoring_min_speed_descr">Filtre interrompant l\'enregistrement en dessous d\'une certaines vitesse. Rend les traces enregistrées plus régulières lorsqu\'elles sont affichées sur la carte.</string>
<string name="monitoring_min_speed_descr">Filtre interrompant l\'enregistrement en dessous d\'une certaine vitesse. Rend les traces enregistrées plus régulières lorsqu\'elles sont affichées sur la carte.</string>
<string name="live_monitoring_time_buffer">Durée de la mémoire tampon</string>
<string name="live_monitoring_adress_descr">Indiquez l\'adresse web avec la syntaxe suivante pour les paramètres : lat = {0}, lon = {1}, horodatage = {2}, hdop = {3}, altitude = {4}, vitesse = {5}, direction = {6}.</string>
<string name="monitoring_min_accuracy_descr_recommendation">Recommandation : il est difficile de prédire ce qui sera enregistré et ce qui ne le sera pas, il peut être préférable de désactiver ce filtre.</string>
@ -3834,4 +3834,7 @@
<string name="next_segment">Segment suivant</string>
<string name="threshold_distance">Seuil de distance</string>
<string name="navigation_profile">Profil de navigation</string>
<string name="street_level_imagery">Photos des rues</string>
<string name="plan_route_exit_dialog_descr">Voulez-vous vraiment fermer l\'itinéraire planifié sans enregistrer \? Vous perdrez toutes les modifications.</string>
<string name="in_case_of_reverse_direction">Si inversion du sens</string>
</resources>

View file

@ -1127,7 +1127,7 @@
<string name="mapillary_widget">וידג׳ט Mapillary</string>
<string name="mapillary_widget_descr">מאפשר תרומה במהירות ל־Mapillary.</string>
<string name="mapillary_descr">תמונות מקוונות ברמת רחוב לכולם. היכרות עם מקומות חדשים, שיתוף פעולה וצילום העולם.</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">תמונות ברמת רחוב</string>
<string name="plugin_mapillary_descr">תמונות ברמת הרחוב לכולם. להכיר מקומות, לשתף פעולה ולצלם את העולם.</string>
<string name="private_access_routing_req">היעד שלך ממוקם באיזור עם גישה פרטית. לאשר שימוש בכבישים פרטיים לצורך טיול זה\?</string>
<string name="restart_search">חיפוש מחדש</string>
@ -3854,4 +3854,13 @@
<string name="threshold_distance">סף מרחק</string>
<string name="navigation_profile">פרופיל ניווט</string>
<string name="rourte_between_points_add_track_desc">נא לבחור קובץ מסלול שבו יתווסף המקטע החדש.</string>
<string name="rourte_between_points_whole_track_button_desc">כל המסלול יחושב מחדש באמצעות הפרופיל הנבחר.</string>
<string name="rourte_between_points_next_segment_button_desc">רק המקטע הבא יחושב מחודש באמצעות הפרופיל הנבחר.</string>
<string name="rourte_between_points_desc">נא לבחור כיצד לחבר נקודות, בקו ישר, או לחבר מסלול ביניהן עם הפרופיל הנבחר.</string>
<string name="rourte_between_points_warning_desc">כדי להשתמש באפשרות זו על OsmAnd להצמיד את המסלול שלך לדרכים שעל המפה.
\n
\n בשלב הבא יהיה עליך לבחור בפרופיל ניווט כדי לזהות את הדרכים המורשות ואת סף המרחק כדי להעריך את המסלול שלך ביחס לדרכים.</string>
<string name="street_level_imagery">תמונות ברמת רחוב</string>
<string name="plan_route_exit_dialog_descr">לסגור את תכנון המסלול בלי לשמור\? כל השינויים שלך יאבדו.</string>
<string name="in_case_of_reverse_direction">במקרה של כיוון הפוך</string>
</resources>

View file

@ -1355,7 +1355,7 @@ POIの更新は利用できません</string>
<string name="fav_point_dublicate_message">そのお気に入りは、重複を避けるために%1$sという名前に変更されました。</string>
<string name="text_size_descr">マップ上の文字サイズを設定します。</string>
<string name="text_size">文字サイズ</string>
<string name="rendering_attr_tramTrainRoutes_name">路面電車と鉄道の路線</string>
<string name="rendering_attr_tramTrainRoutes_name">路面電車&鉄道路線</string>
<string name="lock_screen_request_explanation">省電力機能で画面をオフにするには%1$s の権限が必要です。</string>
<string name="wake_on_voice">画面の電源オン設定</string>
<string name="wake_on_voice_descr">方向転換地点に近づいたらデバイスの画面を(オフの場合指定時間)オンにします</string>
@ -3683,7 +3683,7 @@ POIの更新は利用できません</string>
<string name="hillshade_download_description">マップ上で起伏の陰影表示をするには、追加マップが必要です。</string>
<string name="shared_string_drawer">ドロワーメニュー</string>
<string name="shared_string_octagon">八角形</string>
<string name="context_menu_actions">コンテキストメニューアクション</string>
<string name="context_menu_actions">コンテキストメニュー</string>
<string name="reorder_or_hide_from">項目の並べ替えや非表示するものを指定できます。</string>
<string name="shared_string_divider">分割</string>
<string name="divider_descr">分割線で区切られた部分より下にある項目が適用されます。</string>
@ -3724,4 +3724,17 @@ POIの更新は利用できません</string>
<string name="lang_gu">グジャラート語</string>
<string name="lang_cv">チュヴァシ語</string>
<string name="gpx_parse_error">OsmAnd GPXの形式が正しくありません。サポートチームに連絡しての調査をおすすめします</string>
<string name="screen_timeout">画面のタイムアウト</string>
<string name="turn_screen_on_descr">画面復帰オプションを選択します(端末設定でロックされる場合は、OsmAndがバックグラウンド動作でないことを確認してください):</string>
<string name="system_screen_timeout_descr">端末側の画面オフ(省電力)設定に従って画面を消灯します。</string>
<string name="system_screen_timeout">端末側の画面オフ設定を使用</string>
<string name="turn_screen_on_wake_time_descr">画面がオンになった後からオフまでの時間を指定します。(\"%1$s\"有効時は適用されません)</string>
<string name="keep_screen_on">画面を常に表示</string>
<string name="turn_screen_on_proximity_sensor">近接センサー</string>
<string name="turn_screen_on_navigation_instructions_descr">ナビゲーション指示がある時だけ画面がオンになります。</string>
<string name="turn_screen_on_navigation_instructions">ナビゲーション指示</string>
<string name="turn_screen_on_power_button_descr">端末の電源ボタンを押すと、画面がオンになり、ロック画面上にOsmAndが表示されます。</string>
<string name="turn_screen_on_power_button">電源ボタン</string>
<string name="use_volume_buttons_as_zoom_descr">端末の音量ボタンでマップのズームレベルを変更できるようにします。</string>
<string name="use_volume_buttons_as_zoom">音量ボタンでズーム</string>
</resources>

View file

@ -2063,7 +2063,7 @@
<string name="mapillary_widget">Ferramenta Mapillary</string>
<string name="mapillary_widget_descr">Permite contribuições rápidas ao Mapillary.</string>
<string name="mapillary_descr">Fotos ao nível da rua, online, para todos. Descobrir lugares, colaborar, capturar o mundo.</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Imagens de rua</string>
<string name="plugin_mapillary_descr">Fotos ao nível da rua para todos. Descubra lugares, colabore, capture o mundo.</string>
<string name="private_access_routing_req">Seu destino está localizado numa área de acesso privado. Permitir uso de vias privadas para esta viagem\?</string>
<string name="restart_search">Reiniciar pesquisa</string>
@ -3883,4 +3883,7 @@
<string name="threshold_distance">Distância limite</string>
<string name="navigation_profile">Perfil de navegação</string>
<string name="rourte_between_points_add_track_desc">Selecione um arquivo de trilha para o qual um novo segmento será adicionado.</string>
<string name="street_level_imagery">Imagens de rua</string>
<string name="plan_route_exit_dialog_descr">Tem certeza de que deseja fechar plano de rota sem salvar\? Você perderá todas as alterações.</string>
<string name="in_case_of_reverse_direction">Em caso de direção reversa</string>
</resources>

View file

@ -917,8 +917,7 @@
<string name="index_srtm_ele">Curvas de nível</string>
<string name="recording_photo_description">Foto %1$s de %2$s</string>
<string name="av_def_action_picture">Capture uma foto</string>
<string name="osmand_srtm_long_description_1000_chars">Este suplemento disponibiliza \'Curvas de Nível\' e \'Sombras de relevo\', que podem ser aplicadas nos mapas padrão do OsmAnd.
\nEstas funcionalidades podem ser apreciadas por atletas, caminhantes e qualquer pessoa interessada na informação de relevo de uma paisagem.
<string name="osmand_srtm_long_description_1000_chars">Este suplemento disponibiliza \'Curvas de Nível\' e \'Sombras de relevo\', que podem ser aplicadas nos mapas padrão do OsmAnd. Estas funcionalidades podem ser apreciadas por atletas, caminhantes e qualquer pessoa interessada na informação de relevo de uma paisagem.
\n
\n Os dados globais (entre as latitudes 70° norte e 70° sul) são baseados nas medições do SRTM (Shuttle Radar Topography Mission) e do ASTER (Advanced Spaceborn Thermal Emission and Reflection Radiometer), um instrumento de imagens no \'Terra\', o satélite principal do Sistema de Observação da Terra da NASA. O ASTER é um esforço conjunto da NASA, do Ministério da Economia, Comércio e Indústria do Japão e do Sistema Espacial Japonês (J-spacesystems).</string>
<string name="srtm_plugin_description">Este suplemento disponibiliza \'Curvas de Nível\' e \'Sombras de relevo\', que podem ser aplicadas nos mapas padrão do OsmAnd. Estas funcionalidades podem ser apreciadas por atletas, caminhantes, e qualquer pessoa interessada na informação de relevo de uma paisagem.
@ -1052,26 +1051,25 @@
<string name="map_widget_fps_info">Depuração FPS</string>
<string name="map_magnifier">Lupa do mapa</string>
<string name="base_world_map">Mapa mundial</string>
<string name="osmand_plus_long_description_1000_chars">OsmAnd+ (Direções de Navegação Automatizada do OSM)
<string name="osmand_plus_long_description_1000_chars">OsmAnd+ (Direções de Navegação Automatizada do OSM)
\n
\n OsmAnd+ é uma aplicação de navegação livre, com acesso a uma ampla variedade de dados globais do OSM. Todos os dados dos mapas (mapas vetoriais ou imagens raster) podem ser armazenados no cartão de memória do telemóvel para usar desligado da Internet. O OsmAnd também permite roteamento, tanto ligado como desligado da Internet, incluindo a funcionalidade de roteamento curva a curva com orientação por voz.
\n OsmAnd+ é uma aplicação de navegação livre, com acesso a uma ampla variedade de dados globais do OSM. Todos os dados dos mapas (mapas vetoriais ou imagens raster) podem ser armazenados no cartão de memória do telemóvel para usar desligado da Internet. O OsmAnd também permite roteamento, tanto ligado como desligado da Internet, incluindo a funcionalidade de roteamento curva a curva com orientação por voz.
\n
\n OsmAnd+ é a versão paga da aplicação, ao comprá-lo está a apoiar o projeto, a financiar o desenvolvimento de novas funcionalidades e a receber as últimas atualizações.
\n OsmAnd+ é a versão paga da aplicação, ao comprá-lo está a apoiar o projeto, a financiar o desenvolvimento de novas funcionalidades e a receber as últimas atualizações.
\n
\n Algumas das características principais:
\n - Funcionalidade totalmente desligado da Internet (guarda os mapas obtidos, sejam eles vetoriais ou imagens, numa pasta selecionável).
\n - Mapas vetoriais compactados do mundo inteiro disponíveis.
\n - Descarregamento de mapas de países ou regiões diretamente na aplicação.
\n - Recurso Wikipédia desligado da Internet (descarregamento de POIs da Wikipédia), ótimo para passeios turísticos.
\n - Possibilidade de sobreposição de várias camadas de mapas, como trilhos GPX ou navegação, pontos de Interesse, favoritos, curvas de nível, paragens de transporte público, mapas adicionais com transparência personalizável.
\n
\n Algumas das características principais:
\n - Funcionalidade totalmente desligado da Internet (guarda os mapas obtidos, sejam eles vetoriais ou imagens, numa pasta selecionável).
\n - Mapas vetoriais compactados do mundo inteiro disponíveis.
\n - Descarregamento de mapas de países ou regiões diretamente na aplicação.
\n - Recurso Wikipédia desligado da Internet (descarregamento de POIs da Wikipédia), ótimo para passeios turísticos.
\n - Possibilidade de sobreposição de várias camadas de mapas, como trilhos GPX ou navegação, pontos de Interesse, favoritos, curvas de nível, paragens de transporte público, mapas adicionais com transparência personalizável.
\n
\n - Pesquisa desligado da Internet para endereços e locais (POIs).
\n - Encaminhamento desligado da Internet para distâncias médias.
\n - Modos de carro, bicicleta e pedestre com os opcionais:
\n - Mudança automática de visualização dia/noite
\n - Ampliação do mapa conforme a velocidade
\n - Orientação do mapa de acordo com a bússola ou a direção do movimento.
\n - Pesquisa desligado da Internet para endereços e locais (POIs).
\n - Encaminhamento desligado da Internet para distâncias médias.
\n - Modos de carro, bicicleta e pedestre com os opcionais:
\n - Mudança automática de visualização dia/noite
\n - Ampliação do mapa conforme a velocidade
\n - Orientação do mapa de acordo com a bússola ou a direção do movimento.
\n - Orientação por faixas de rodagem, indicação do limite de velocidade, vozes gravadas e vozes de conversão de texto em voz.
\n</string>
<string name="auto_zoom_none">Sem ampliação automático</string>
@ -1250,7 +1248,7 @@
<string name="traffic_warning_border_control">Posto alfandegário</string>
<string name="traffic_warning_payment">Portagem</string>
<string name="traffic_warning_stop">Sinal de stop</string>
<string name="traffic_warning_calming">Choque de velocidade</string>
<string name="traffic_warning_calming">Moderação de trafego</string>
<string name="traffic_warning_speed_camera">Radar de velocidade</string>
<string name="traffic_warning">Aviso de tráfego</string>
<string name="speak_favorites">Favoritos pertos</string>
@ -1921,7 +1919,7 @@
<string name="mapillary_widget">Widget Mapillary</string>
<string name="mapillary_widget_descr">Permite contribuir rapidamente para Mapillary.</string>
<string name="mapillary_descr">Fotos on-line ao nível da rua para todos. Descubra locais, colabore, capture o mundo.</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Imagens de nível de rua</string>
<string name="plugin_mapillary_descr">Fotos ao nível da rua para todos. Descubra locais, colabore, capture o mundo.</string>
<string name="private_access_routing_req">O seu destino está localizado numa área de acesso privado. Permitir uso de estradas privadas para esta viagem\?</string>
<string name="restart_search">Reiniciar pesquisa</string>
@ -3382,7 +3380,7 @@
<string name="edit_profiles_descr">Perfis padrão do OsmAnd não podem ser apagados, mas desativados (na tela anterior) ou classificados na parte inferior.</string>
<string name="edit_profiles">Editar perfis</string>
<string name="select_nav_profile_dialog_message">O \'Tipo de navegação\' controla como as rotas são calculadas.</string>
<string name="profile_appearance">Aspecto do perfil</string>
<string name="profile_appearance">Aspeto do perfil</string>
<string name="layer_osm_edits">Edições OSM</string>
<string name="quick_action_contour_lines_descr">Botão que mostra ou oculta curvas de nível no mapa.</string>
<string name="quick_action_contour_lines_show">Mostrar curvas de nível</string>
@ -3846,4 +3844,17 @@
<string name="plan_route_create_new_route">Criar rota</string>
<string name="shared_string_done">Pronto</string>
<string name="overwrite_track">Sobrescrever trilho</string>
<string name="save_as_new_track">Gravar como novo trilho</string>
<string name="reverse_route">Rota inversa</string>
<string name="rourte_between_points_whole_track_button_desc">O trilho inteiro será recalculado a usar o perfil selecionado.</string>
<string name="rourte_between_points_next_segment_button_desc">Somente o próximo segmento será recalculado a usar o perfil selecionado.</string>
<string name="rourte_between_points_desc">Selecione como ligar pontos, com uma linha reta ou calcule uma rota entre eles com o perfil selecionado.</string>
<string name="whole_track">Trilho inteiro</string>
<string name="next_segment">Próximo segmento</string>
<string name="rourte_between_points_warning_desc">Para usar esta opção o OsmAnd precisa de encaixar o seu trilho nas estradas do mapa.
\n
\n No passo seguinte, terá de selecionar o perfil de navegação para detetar estradas permitidas e a distância limiar para se aproximar do seu trilho com as estradas.</string>
<string name="threshold_distance">Distância limiar</string>
<string name="navigation_profile">Perfil de navegação</string>
<string name="rourte_between_points_add_track_desc">Selecione um ficheiro de faixa para o qual um novo segmento será adicionado.</string>
</resources>

View file

@ -3838,4 +3838,19 @@
<string name="plan_route_select_track_file_for_open">Выберите файл трека для открытия.</string>
<string name="shared_string_done">Готово</string>
<string name="overwrite_track">Перезаписать трек</string>
<string name="rourte_between_points_add_track_desc">Выбрать трек, к которому будет добавлен новый сегмент.</string>
<string name="navigation_profile">Профиль</string>
<string name="threshold_distance">Предельная дистанция</string>
<string name="save_as_new_track">Сохранить как новый трек</string>
<string name="reverse_route">Обратный маршрут</string>
<string name="rourte_between_points_whole_track_button_desc">Весь трек будет перестроен с использованием выбранного профиля.</string>
<string name="rourte_between_points_next_segment_button_desc">Только следующий сегмент будет перестроен с использованием выбранного профиля.</string>
<string name="next_segment">Следующий сегмент</string>
<string name="whole_track">Весь трек</string>
<string name="rourte_between_points_warning_desc">Для использования данной опции OsmAnd проложет ваш трек по дорогам.
\n
\nДалее вам следует выбрать профиль для построения маршрута с учётом ограничений этого профиля.</string>
<string name="rourte_between_points_desc">Выберите как соединять точки: по прямой линии или построением маршрута.</string>
<string name="in_case_of_reverse_direction">В случае обратного направления</string>
<string name="plan_route_exit_dialog_descr">Закрыть план маршрута без сохранения\? Все изменения будут потеряны.</string>
</resources>

View file

@ -2418,7 +2418,7 @@
<string name="increase_search_radius">Zväčšiť okruh hľadania</string>
<string name="nothing_found">Nič sa nenašlo</string>
<string name="nothing_found_descr">Zmeňte vyhľadávacie kritérium alebo zväčšite polomer hľadania.</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Snímky z úrovne ulice</string>
<string name="open_mapillary">Otvoriť Mapillary</string>
<string name="shared_string_install">Inštalovať</string>
<string name="improve_coverage_mapillary">Zlepšiť pokrytie fotografií s Mapillary</string>
@ -3852,4 +3852,7 @@
<string name="threshold_distance">Hraničná vzdialenosť</string>
<string name="navigation_profile">Navigačný profil</string>
<string name="rourte_between_points_add_track_desc">Zvoľte súbor stopy, pre ktorú bude pridaný nový úsek.</string>
<string name="street_level_imagery">Snímky z úrovne ulice</string>
<string name="plan_route_exit_dialog_descr">Naozaj chcete zatvoriť plánovanie trasy bez uloženia\? Všetky zmeny sa stratia.</string>
<string name="in_case_of_reverse_direction">V prípade opačného smeru</string>
</resources>

View file

@ -684,7 +684,7 @@
<string name="shared_string_not_selected">Није означено</string>
<string name="osmand_parking_hour">h</string>
<string name="osmand_parking_minute">min</string>
<string name="traffic_warning_calming">Лежећи полицајац</string>
<string name="traffic_warning_calming">Смиривање саобраћаја</string>
<string name="way_alarms">Упозорења о гужвама у саобраћају</string>
<string name="background_service_is_enabled_question">Позадинске услуге OsmAnd-а су и даље покренуте. Прекинути и њих?</string>
<string name="sleep_mode_stop_dialog">Прекинути позадински режим GPS-а?</string>
@ -1251,7 +1251,7 @@
<string name="mapillary_widget_descr">Омогућава брзи допринос Мапилару.</string>
<string name="open_mapillary">Отвори Мапилар</string>
<string name="mapillary_descr">Мрежне слике улица за све. Откријте места, сарађујте, освојите свет.</string>
<string name="mapillary">Мапилар</string>
<string name="mapillary">Слике на нивоу улице</string>
<string name="plugin_mapillary_descr">Мрежне слике улица за све. Откријте места, сарађујте, освојите свет.</string>
<string name="private_access_routing_req">Ваше одредиште се налази на приватном поседу. Дозволити коришћење приватних путева на овом путовању\?</string>
<string name="restart_search">Препокрени претрагу</string>
@ -3836,4 +3836,20 @@
<string name="plan_route_select_track_file_for_open">Изаберите фајл путање за отварање.</string>
<string name="shared_string_done">Завршено</string>
<string name="overwrite_track">Замени стазу</string>
<string name="save_as_new_track">Сачувај као нову стазу</string>
<string name="reverse_route">Обрнута рута</string>
<string name="rourte_between_points_whole_track_button_desc">Читава стаза ће се прерачунати користећи одабрани профил.</string>
<string name="rourte_between_points_next_segment_button_desc">Само ће се следећи сегмент прерачунати користећи одабрани профил.</string>
<string name="rourte_between_points_desc">Изаберите како повезати тачке, са правом линијом, или израчунајте руту између њих са одабраним профилом.</string>
<string name="whole_track">Цела стаза</string>
<string name="next_segment">Следећи сегмент</string>
<string name="rourte_between_points_warning_desc">Да бисте користили ову опцију, ОсмАнд мора да прилагоди вашу стазу путевима на мапи.
\n
\n На следећем кораку мора ћете одабрати навигацијски профил како бисте открили дозвољене путеве и праг удаљености и тиме приближили вашу стазу путевима.</string>
<string name="threshold_distance">Праг удаљености</string>
<string name="navigation_profile">Навигацијски профил</string>
<string name="rourte_between_points_add_track_desc">Изаберите датотеку записа којој ће се додати нови сегмент.</string>
<string name="street_level_imagery">Слике на нивоу улице</string>
<string name="plan_route_exit_dialog_descr">Јесте ли сигурни да желите затворити План руте без чувања\? Изгуби ћете све промене.</string>
<string name="in_case_of_reverse_direction">У случају обрнутог правца</string>
</resources>

View file

@ -2151,7 +2151,7 @@
<string name="modify_the_search_query">Arama sorgunuzu değiştirin.</string>
<string name="add_favourites_group_to_markers_descr">İşaretleyicilere eklemek için bir Sık Kullanılanlar kategorisi seçin.</string>
<string name="import_as_gpx">GPX dosyası olarak içe aktar</string>
<string name="plan_route">Rotayı planla</string>
<string name="plan_route">Güzergah planla</string>
<string name="shared_string_list">Liste</string>
<string name="shared_string_groups">Gruplar</string>
<string name="passed">Son kullanılan: %1$s</string>
@ -2255,7 +2255,7 @@
<string name="mapillary_widget">Mapillary widget\'ı</string>
<string name="mapillary_widget_descr">Mapillary\'ye hızlıca katkıda bulunmanıza imkan verir.</string>
<string name="mapillary_descr">Herkes için sokak seviyesinde fotoğraflar. Yerler keşfedin, katkıda bulunun, dünyayı yakalatın.</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">Sokak seviyesi görüntüleri</string>
<string name="plugin_mapillary_descr">Herkes için sokak seviyesinde fotoğraflar. Yerler keşfedin, katkıda bulunun, dünyayı yakalayın.</string>
<string name="parking_options">Park etme seçenekleri</string>
<string name="routing_attr_allow_motorway_name">Otoyolları kullan</string>
@ -3810,4 +3810,7 @@
<string name="threshold_distance">Eşik mesafesi</string>
<string name="navigation_profile">Navigasyon profili</string>
<string name="rourte_between_points_add_track_desc">Kendisine yeni bir bölümün ekleneceği bir yol dosyası seçin.</string>
<string name="street_level_imagery">Sokak seviyesi görüntüleri</string>
<string name="plan_route_exit_dialog_descr">Kaydetmeden güzergah planlamayı kapatmak istediğinize emin misiniz\? Tüm değişiklikleri kaybedeceksiniz.</string>
<string name="in_case_of_reverse_direction">Ters yön durumunda</string>
</resources>

View file

@ -2416,7 +2416,7 @@
<string name="increase_search_radius">增加搜尋半徑</string>
<string name="nothing_found">没有找到</string>
<string name="nothing_found_descr">變更搜尋或增加搜尋半徑。</string>
<string name="mapillary">Mapillary</string>
<string name="mapillary">街道級照片</string>
<string name="mapillary_widget">Mapillary 小工具</string>
<string name="mapillary_widget_descr">允許快速的提供給 Mapillary。</string>
<string name="mapillary_descr">把線上街道平面照片給每個人。發覺地點、協作、抓取世界。</string>
@ -3849,4 +3849,7 @@
<string name="threshold_distance">門檻距離</string>
<string name="navigation_profile">導航設定檔</string>
<string name="rourte_between_points_add_track_desc">選取要加入新片段的軌道檔案。</string>
<string name="street_level_imagery">街道級照片</string>
<string name="plan_route_exit_dialog_descr">您確定要不儲存就關閉計劃錄線嗎?您將會失去所有變更。</string>
<string name="in_case_of_reverse_direction">反向時</string>
</resources>

View file

@ -242,6 +242,7 @@
<dimen name="measurement_tool_select_radius">20dp</dimen>
<dimen name="bottom_sheet_content_margin">16dp</dimen>
<dimen name="bottom_sheet_exit_button_margin">18dp</dimen>
<dimen name="bottom_sheet_content_margin_small">8dp</dimen>
<dimen name="content_padding">16dp</dimen>
<dimen name="content_padding_small">12dp</dimen>

View file

@ -15,6 +15,9 @@
<string name="plan_route_change_route_type_before">Change route type before</string>
<string name="plan_route_trim_after">Trim after</string>
<string name="plan_route_trim_before">Trim before</string>
<string name="in_case_of_reverse_direction">In case of reverse direction</string>
<string name="plan_route_exit_dialog_descr">Are you sure you want to close Plan route without saving? You will lose all changes.</string>
<string name="street_level_imagery">Street-level imagery</string>
<string name="rourte_between_points_add_track_desc">Select a track file for which a new segment will be added.</string>
<string name="navigation_profile">Navigation profile</string>
<string name="threshold_distance">Threshold distance</string>

View file

@ -47,29 +47,6 @@
android:layout="@layout/simple_divider_item"
android:selectable="false" />
<PreferenceCategory
android:key="route_recalculation"
android:layout="@layout/preference_category_with_descr"
android:title="@string/route_recalculation" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="disable_offroute_recalc"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="@string/access_disable_offroute_recalc" />
<net.osmand.plus.settings.preferences.SwitchPreferenceEx
android:key="disable_wrong_direction_recalc"
android:layout="@layout/preference_with_descr_dialog_and_switch"
android:summaryOff="@string/shared_string_disabled"
android:summaryOn="@string/shared_string_enabled"
android:title="@string/access_disable_wrong_direction_recalc" />
<Preference
android:layout="@layout/simple_divider_item"
android:selectable="false" />
<net.osmand.plus.settings.preferences.ListPreferenceEx
android:key="direction_style"
android:layout="@layout/preference_with_descr"

View file

@ -43,7 +43,7 @@ public abstract class CacheFragmentStatePagerAdapter extends FragmentStatePagerA
private SparseArray<Fragment> mPages;
public CacheFragmentStatePagerAdapter(FragmentManager fm) {
super(fm);
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
mPages = new SparseArray<Fragment>();
mFm = fm;
}

View file

@ -97,20 +97,24 @@ public class AndroidUtils {
return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
}
public static void softKeyboardDelayed(final View view) {
public static void softKeyboardDelayed(final Activity activity, final View view) {
view.post(new Runnable() {
@Override
public void run() {
if (!isHardwareKeyboardAvailable(view.getContext())) {
showSoftKeyboard(view);
showSoftKeyboard(activity,view);
}
}
});
}
public static void showSoftKeyboard(final View view) {
public static void showSoftKeyboard(final Activity activity, final View view) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
KeyguardManager keyguardManager = (KeyguardManager) view.getContext().getSystemService(Context.KEYGUARD_SERVICE);
keyguardManager.requestDismissKeyguard(activity,null);
}
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
}
}

View file

@ -19,7 +19,6 @@ import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.core.view.MenuItemCompat;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
@ -102,7 +101,7 @@ public class EditPOIFilterActivity extends OsmandListActivity {
createMenuItem(menu, FILTER, R.string.filter_current_poiButton,
R.drawable.ic_action_done,
//R.drawable.a_1_navigation_accept_light, R.drawable.a_1_navigation_accept_dark,
MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT | MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
MenuItem.SHOW_AS_ACTION_WITH_TEXT | MenuItem.SHOW_AS_ACTION_ALWAYS);
return super.onCreateOptionsMenu(menu);
}

View file

@ -249,7 +249,7 @@ public class FavoritesSearchFragment extends DialogFragment {
private void openKeyboard() {
searchEditText.requestFocus();
AndroidUtils.softKeyboardDelayed(searchEditText);
AndroidUtils.softKeyboardDelayed(getActivity(), searchEditText);
}
public void hideKeyboard() {

View file

@ -32,7 +32,6 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.appcompat.view.ActionMode;
import androidx.core.content.ContextCompat;
import androidx.core.view.MenuItemCompat;
import net.osmand.AndroidUtils;
import net.osmand.Location;
@ -435,7 +434,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
MenuItem mi = createMenuItem(menu, SEARCH_ID, R.string.search_poi_filter, R.drawable.ic_action_search_dark, MenuItemCompat.SHOW_AS_ACTION_ALWAYS | MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
MenuItem mi = createMenuItem(menu, SEARCH_ID, R.string.search_poi_filter, R.drawable.ic_action_search_dark, MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
mi.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
@ -452,11 +451,11 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
((FavoritesActivity) getActivity()).updateListViewFooter(footerView);
if (!MenuItemCompat.isActionViewExpanded(mi)) {
createMenuItem(menu, IMPORT_FAVOURITES_ID, R.string.shared_string_add_to_favorites, R.drawable.ic_action_plus, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
createMenuItem(menu, SHARE_ID, R.string.shared_string_share, R.drawable.ic_action_gshare_dark, MenuItemCompat.SHOW_AS_ACTION_ALWAYS, true);
createMenuItem(menu, SELECT_MAP_MARKERS_ID, R.string.select_map_markers, R.drawable.ic_action_flag, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
createMenuItem(menu, DELETE_ID, R.string.shared_string_delete, R.drawable.ic_action_delete_dark, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
if (!mi.isActionViewExpanded()) {
createMenuItem(menu, IMPORT_FAVOURITES_ID, R.string.shared_string_add_to_favorites, R.drawable.ic_action_plus, MenuItem.SHOW_AS_ACTION_ALWAYS);
createMenuItem(menu, SHARE_ID, R.string.shared_string_share, R.drawable.ic_action_gshare_dark, MenuItem.SHOW_AS_ACTION_ALWAYS, true);
createMenuItem(menu, SELECT_MAP_MARKERS_ID, R.string.select_map_markers, R.drawable.ic_action_flag, MenuItem.SHOW_AS_ACTION_ALWAYS);
createMenuItem(menu, DELETE_ID, R.string.shared_string_delete, R.drawable.ic_action_delete_dark, MenuItem.SHOW_AS_ACTION_ALWAYS);
}
}
@ -483,7 +482,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
enableSelectionMode(true);
createMenuItem(menu, SELECT_MAP_MARKERS_ACTION_MODE_ID, R.string.select_map_markers,
R.drawable.ic_action_flag,
MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItem.SHOW_AS_ACTION_IF_ROOM);
favoritesSelected.clear();
groupsToDelete.clear();
favouritesAdapter.notifyDataSetInvalidated();
@ -546,7 +545,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
enableSelectionMode(true);
createMenuItem(menu, DELETE_ACTION_ID, R.string.shared_string_delete,
R.drawable.ic_action_delete_dark,
MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItem.SHOW_AS_ACTION_IF_ROOM);
favoritesSelected.clear();
groupsToDelete.clear();
favouritesAdapter.notifyDataSetInvalidated();

View file

@ -18,7 +18,6 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import com.jwetherell.openmap.common.LatLonPoint;
@ -106,7 +105,7 @@ public class NavigatePointFragment extends Fragment implements SearchActivityChi
light = false;
}
MenuItem menuItem = menu.add(0, SHOW_ON_MAP, 0, R.string.shared_string_show_on_map);
MenuItemCompat.setShowAsAction(menuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuItem = menuItem.setIcon(app.getUIUtilities().getIcon(R.drawable.ic_action_marker_dark, light));
menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {

View file

@ -10,8 +10,6 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import androidx.core.view.MenuItemCompat;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
@ -64,7 +62,7 @@ public abstract class OsmandExpandableListActivity extends
return onOptionsItemSelected(item);
}
});
MenuItemCompat.setShowAsAction(menuItem, menuItemType);
menuItem.setShowAsAction(menuItemType);
return menuItem;
}

View file

@ -10,8 +10,6 @@ import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import androidx.core.view.MenuItemCompat;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
@ -68,7 +66,7 @@ public abstract class OsmandListActivity extends
return onOptionsItemSelected(item);
}
});
MenuItemCompat.setShowAsAction(menuItem, menuItemType);
menuItem.setShowAsAction(menuItemType);
return menuItem;
}

View file

@ -39,7 +39,7 @@ public class TabActivity extends ActionBarProgressActivity {
private List<TabItem> mTabs;
public OsmandFragmentPagerAdapter(FragmentManager fm, List<TabItem> items) {
super(fm);
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
mTabs = items;
}

View file

@ -2,6 +2,7 @@ package net.osmand.plus.activities.actions;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -9,7 +10,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.text.ClipboardManager;
import android.text.Html;
import android.widget.Toast;

View file

@ -16,7 +16,6 @@ import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment;
import net.osmand.data.LatLon;
@ -82,7 +81,7 @@ public class SearchAddressFragment extends Fragment {
}
if(getActivity() instanceof SearchAddressActivity) {
MenuItem menuItem = menu.add(0, SELECT_POINT, 0, "");
MenuItemCompat.setShowAsAction(menuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
if (getApplication().accessibilityEnabled())
menuItem.setTitle(R.string.shared_string_ok);
menuItem = menuItem.setIcon(R.drawable.ic_action_done);
@ -95,7 +94,7 @@ public class SearchAddressFragment extends Fragment {
});
} else {
MenuItem menuItem = menu.add(0, SHOW_ON_MAP, 0, R.string.shared_string_show_on_map);
MenuItemCompat.setShowAsAction(menuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuItem = menuItem.setIcon(R.drawable.ic_action_marker_dark);
menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@ -107,7 +106,7 @@ public class SearchAddressFragment extends Fragment {
});
if (ENABLE_ONLINE_ADDRESS) {
menuItem = menu.add(0, ONLINE_SEARCH, 0, R.string.search_online_address);
MenuItemCompat.setShowAsAction(menuItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menuItem = menuItem.setIcon(R.drawable.ic_world_globe_dark);
menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override

View file

@ -34,7 +34,6 @@ import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuItemCompat;
import androidx.core.view.ViewCompat;
import net.osmand.Location;
@ -124,7 +123,7 @@ public class SearchPOIActivity extends OsmandListActivity implements OsmAndCompa
public boolean onCreateOptionsMenu(Menu omenu) {
Menu menu = getClearToolbar(true).getMenu();
searchPOILevel = menu.add(0, SEARCH_MORE, 0, R.string.search_POI_level_btn);
MenuItemCompat.setShowAsAction(searchPOILevel, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
searchPOILevel.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
searchPOILevel.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
@ -133,7 +132,7 @@ public class SearchPOIActivity extends OsmandListActivity implements OsmAndCompa
});
showFilterItem = menu.add(0, FILTER, 0, R.string.search_poi_filter);
MenuItemCompat.setShowAsAction(showFilterItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
showFilterItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
showFilterItem = showFilterItem.setIcon(getMyApplication().getUIUtilities().getIcon(
R.drawable.ic_action_filter_dark));
showFilterItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@ -156,7 +155,7 @@ public class SearchPOIActivity extends OsmandListActivity implements OsmAndCompa
});
showOnMapItem = menu.add(0, SHOW_ON_MAP, 0, R.string.shared_string_show_on_map);
MenuItemCompat.setShowAsAction(showOnMapItem, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
showOnMapItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
showOnMapItem = showOnMapItem.setIcon(getMyApplication().getUIUtilities().getIcon(
R.drawable.ic_show_on_map));
showOnMapItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@ -176,10 +175,10 @@ public class SearchPOIActivity extends OsmandListActivity implements OsmAndCompa
showOnMapItem.setEnabled(!isNameSearch() || amenityAdapter.getCount() > 0);
if (filter != null && !isNameSearch()) {
createMenuItem(omenu, SAVE_FILTER, R.string.edit_filter_save_as_menu_item, R.drawable.ic_action_favorite,
MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItem.SHOW_AS_ACTION_IF_ROOM);
if (!filter.isStandardFilter()) {
createMenuItem(omenu, DELETE_FILTER, R.string.shared_string_delete, R.drawable.ic_action_delete_dark,
MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
}
updateButtonState(false);

View file

@ -12,7 +12,6 @@ import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.ProgressBar;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import net.osmand.plus.R;
@ -129,7 +128,7 @@ public class AudioVideoNoteRecordingMenuFullScreen extends AudioVideoNoteRecordi
stopProgress();
progressBar.setProgress(0);
ViewCompat.setAlpha(progressBar, 1f);
progressBar.setAlpha(1f);
progressBar.setVisibility(View.VISIBLE);
animatorCompat = ValueAnimator.ofInt(0);

View file

@ -1036,11 +1036,11 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
try {
Method m = mr.getClass().getDeclaredMethod("setOrientationHint", Integer.TYPE);
Display display = ((WindowManager) mapActivity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getOrientation() == Surface.ROTATION_0) {
if (display.getRotation() == Surface.ROTATION_0) {
m.invoke(mr, 90);
} else if (display.getOrientation() == Surface.ROTATION_270) {
} else if (display.getRotation() == Surface.ROTATION_270) {
m.invoke(mr, 180);
} else if (display.getOrientation() == Surface.ROTATION_180) {
} else if (display.getRotation() == Surface.ROTATION_180) {
m.invoke(mr, 270);
}
} catch (Exception e) {

View file

@ -4,10 +4,10 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.text.ClipboardManager;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.LayoutInflater;

View file

@ -101,7 +101,7 @@ public class MapViewTrackingUtilities implements OsmAndLocationListener, IMapLoc
if (mapView != null) {
WindowManager wm = (WindowManager) app.getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
int orientation = wm.getDefaultDisplay().getOrientation();
int orientation = wm.getDefaultDisplay().getRotation();
app.getLocationProvider().updateScreenOrientation(orientation);
mapView.setMapLocationListener(this);
}

View file

@ -13,7 +13,6 @@ import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import androidx.annotation.NonNull;
import androidx.core.view.MenuItemCompat;
import net.osmand.AndroidUtils;
import net.osmand.plus.OsmandApplication;
@ -106,7 +105,7 @@ public abstract class OsmandExpandableListFragment extends BaseOsmAndFragment
return onOptionsItemSelected(item);
}
});
MenuItemCompat.setShowAsAction(menuItem, menuItemType);
menuItem.setShowAsAction(menuItemType);
return menuItem;
}

View file

@ -21,7 +21,7 @@ public class BaseBottomSheetItem {
protected int layoutId = INVALID_ID;
private Object tag;
private boolean disabled;
private View.OnClickListener onClickListener;
protected View.OnClickListener onClickListener;
protected int position = INVALID_POSITION;
public View getView() {

View file

@ -0,0 +1,76 @@
package net.osmand.plus.base.bottomsheetmenu;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.ColorRes;
import androidx.annotation.LayoutRes;
import net.osmand.plus.R;
import static net.osmand.plus.UiUtilities.*;
import static net.osmand.plus.UiUtilities.DialogButtonType.PRIMARY;
public class BottomSheetItemButton extends SimpleBottomSheetItem {
protected CharSequence description;
DialogButtonType buttonType;
LinearLayout buttonView;
public BottomSheetItemButton(View customView,
@LayoutRes int layoutId,
Object tag,
boolean disabled,
View.OnClickListener onClickListener,
int position,
Drawable icon,
Drawable background,
CharSequence title,
@ColorRes int titleColorId,
boolean iconHidden,
DialogButtonType buttonType) {
super(customView, layoutId, tag, disabled, onClickListener, position, icon, background, title,
titleColorId, iconHidden);
this.buttonType = buttonType;
}
@Override
public void inflate(Context context, ViewGroup container, boolean nightMode) {
super.inflate(context, container, nightMode);
buttonView = view.findViewById(R.id.button);
if (buttonView != null) {
setupDialogButton(nightMode, buttonView, buttonType, title);
buttonView.setOnClickListener(onClickListener);
}
}
public static class Builder extends SimpleBottomSheetItem.Builder {
protected DialogButtonType buttonType = PRIMARY;
public Builder setButtonType(DialogButtonType buttonType) {
this.buttonType = buttonType;
return this;
}
public BottomSheetItemButton create() {
return new BottomSheetItemButton(customView,
layoutId,
tag,
disabled,
onClickListener,
position,
icon,
background,
title,
titleColorId,
iconHidden,
buttonType);
}
}
}

View file

@ -1,6 +1,7 @@
package net.osmand.plus.dashboard;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
@ -9,8 +10,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;
import com.google.android.material.snackbar.Snackbar;
@ -37,10 +38,10 @@ public abstract class DashBaseFragment extends Fragment {
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof MapActivity) {
dashboard = ((MapActivity) activity).getDashboard();
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (context instanceof MapActivity) {
dashboard = ((MapActivity) context).getDashboard();
dashboard.onAttach(this);
}
}
@ -171,8 +172,8 @@ public abstract class DashBaseFragment extends Fragment {
@Override
public void onDismiss() {
dashboardOnMap.blacklistFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
fragmentView.setTranslationX(0);
fragmentView.setAlpha(1);
Snackbar.make(parentView, dashboardOnMap.getMyApplication().getResources()
.getString(R.string.shared_string_card_was_hidden), Snackbar.LENGTH_LONG)
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
@ -186,8 +187,8 @@ public abstract class DashBaseFragment extends Fragment {
public void onUndo() {
dashboardOnMap.unblacklistFragmentClass(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
fragmentView.setTranslationX(0);
fragmentView.setAlpha(1);
}
}
}

View file

@ -9,8 +9,6 @@ import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.core.view.ViewCompat;
import com.google.android.material.snackbar.Snackbar;
import net.osmand.plus.OsmandApplication;
@ -98,8 +96,8 @@ public class DashErrorFragment extends DashBaseFragment {
@Override
public void onDismiss() {
dashboardOnMap.hideFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
fragmentView.setTranslationX(0);
fragmentView.setAlpha(1);
Snackbar.make(parentView, dashboardOnMap.getMyApplication().getResources()
.getString(R.string.shared_string_card_was_hidden), Snackbar.LENGTH_LONG)
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
@ -113,8 +111,8 @@ public class DashErrorFragment extends DashBaseFragment {
public void onUndo() {
dashboardOnMap.unhideFragmentByTag(fragmentTag);
ViewCompat.setTranslationX(fragmentView, 0);
ViewCompat.setAlpha(fragmentView, 1);
fragmentView.setTranslationX(0);
fragmentView.setAlpha(1);
}
}
}

View file

@ -1217,7 +1217,7 @@ public class DashboardOnMap implements ObservableScrollViewCallbacks, IRouteInfo
}
private void setTranslationY(View v, int y) {
ViewCompat.setTranslationY(v, y);
v.setTranslationY(y);
}
@SuppressLint("NewApi")

View file

@ -1,6 +1,5 @@
package net.osmand.plus.dashboard.tools;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
@ -51,9 +50,9 @@ public class DashboardSettingsDialogFragment extends DialogFragment
private static final int DEFAULT_NUMBER_OF_ROWS = 5;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mapActivity = (MapActivity) activity;
public void onAttach(@NonNull Context context) {
super.onAttach(context);
mapActivity = (MapActivity) context;
mFragmentsData = new ArrayList<>();
for (DashFragmentData fragmentData : mapActivity.getDashboard().getFragmentsData()) {
if (fragmentData.canBeDisabled()) mFragmentsData.add(fragmentData);

View file

@ -65,12 +65,12 @@ public class TestVoiceActivity extends OsmandActionBarActivity {
tv.setPadding(0, 5, 0, 7);
ScrollView sv = new ScrollView(this);
gl.addView(sv, new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT,
android.view.ViewGroup.LayoutParams.FILL_PARENT));
gl.addView(sv, new LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT));
final LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(ll, new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT,
android.view.ViewGroup.LayoutParams.FILL_PARENT));
sv.addView(ll, new LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT,
android.view.ViewGroup.LayoutParams.MATCH_PARENT));
// add buttons
setContentView(gl);
@ -271,7 +271,7 @@ public class TestVoiceActivity extends OsmandActionBarActivity {
button.setGravity(Gravity.LEFT);
button.setTransformationMethod(null); //or else button text is all upper case
button.setText(description);
button.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
button.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
if (!description.startsWith("\u25BA (")) {
// Section headline buttons
button.setPadding(10, 20, 10, 5);

View file

@ -113,7 +113,7 @@ public class FavoriteDialogs {
editText.requestFocus();
final AutoCompleteTextView cat = (AutoCompleteTextView) dialog.findViewById(R.id.Category);
cat.setText(point.getCategory());
AndroidUtils.softKeyboardDelayed(editText);
AndroidUtils.softKeyboardDelayed(activity, editText);
}
public static Dialog createAddFavouriteDialog(final Activity activity, final Bundle args) {

View file

@ -6,7 +6,6 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@ -82,21 +81,7 @@ public class HelpArticleDialogFragment extends DialogFragment {
//Scale web view font size with system font size
float scale = getActivity().getResources().getConfiguration().fontScale;
if (android.os.Build.VERSION.SDK_INT >= 14) {
webView.getSettings().setTextZoom((int) (scale * 100f));
} else {
if (scale <= 0.7f) {
webView.getSettings().setTextSize(WebSettings.TextSize.SMALLEST);
} else if (scale <= 0.85f) {
webView.getSettings().setTextSize(WebSettings.TextSize.SMALLER);
} else if (scale <= 1.0f) {
webView.getSettings().setTextSize(WebSettings.TextSize.NORMAL);
} else if (scale <= 1.15f) {
webView.getSettings().setTextSize(WebSettings.TextSize.LARGER);
} else {
webView.getSettings().setTextSize(WebSettings.TextSize.LARGEST);
}
}
webView.getSettings().setTextZoom((int) (scale * 100f));
if (assetName != null) {
String fileContents = getAssetAsString(assetName, getActivity());

View file

@ -20,6 +20,7 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;
@ -32,7 +33,6 @@ import androidx.core.content.ContextCompat;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.legacy.widget.Space;
import androidx.viewpager.widget.ViewPager;
import net.osmand.AndroidUtils;

View file

@ -21,7 +21,6 @@ import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.DialogFragment;
import net.osmand.AndroidNetworkUtils;
@ -540,12 +539,12 @@ public class DownloadResourceGroupFragment extends DialogFragment implements Dow
MenuItem itemReload = menu.add(0, RELOAD_ID, 0, R.string.shared_string_refresh);
Drawable icReload = app.getUIUtilities().getIcon(R.drawable.ic_action_refresh_dark, colorResId);
itemReload.setIcon(icReload);
MenuItemCompat.setShowAsAction(itemReload, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
itemReload.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuItem itemSearch = menu.add(0, SEARCH_ID, 1, R.string.shared_string_search);
Drawable icSearch = app.getUIUtilities().getIcon(R.drawable.ic_action_search_dark, colorResId);
itemSearch.setIcon(icSearch);
MenuItemCompat.setShowAsAction(itemSearch, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
itemSearch.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
}

View file

@ -695,8 +695,8 @@ public class LocalIndexesFragment extends OsmandExpandableListFragment implement
Drawable icon = getMyApplication().getUIUtilities().getIcon(actionIconId, colorResId);
it.setIcon(icon);
}
MenuItemCompat.setShowAsAction(it, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM |
MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
it.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}

View file

@ -194,7 +194,7 @@ public class OsmLiveActivity extends AbstractDownloadActivity implements Downloa
private final boolean showSettingsOnly;
LiveUpdatesFragmentPagerAdapter(FragmentManager fm, Resources res, boolean showSettingsOnly) {
super(fm);
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
this.showSettingsOnly = showSettingsOnly;
titles = new String[titleIds.length];
for (int i = 0; i < titleIds.length; i++) {

View file

@ -1,6 +1,7 @@
package net.osmand.plus.mapcontextmenu;
import android.app.Activity;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@ -11,7 +12,6 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.text.ClipboardManager;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;

View file

@ -78,7 +78,7 @@ public class EditCategoryDialogFragment extends DialogFragment {
nameEdit = (EditText)v.findViewById(R.id.edit_name);
nameEdit.setText(name);
nameEdit.requestFocus();
AndroidUtils.softKeyboardDelayed(nameEdit);
AndroidUtils.softKeyboardDelayed(getActivity(), nameEdit);
colorSpinner = (Spinner)v.findViewById(R.id.edit_color);
final TIntArrayList colors = new TIntArrayList();
final int intColor = color;

View file

@ -207,7 +207,7 @@ public abstract class PointEditorFragment extends BaseOsmAndFragment {
if (editor != null && editor.isNew()) {
nameEdit.selectAll();
nameEdit.requestFocus();
AndroidUtils.softKeyboardDelayed(nameEdit);
AndroidUtils.softKeyboardDelayed(getActivity(), nameEdit);
}
}

View file

@ -235,7 +235,7 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment {
addDelDescription.setText(view.getResources().getString(R.string.delete_description));
View descriptionEdit = view.findViewById(R.id.description_edit);
descriptionEdit.requestFocus();
AndroidUtils.softKeyboardDelayed(descriptionEdit);
AndroidUtils.softKeyboardDelayed(getActivity(), descriptionEdit);
} else {
descriptionCaption.setVisibility(View.GONE);
addDelDescription.setText(view.getResources().getString(R.string.add_description));
@ -267,7 +267,7 @@ public abstract class PointEditorFragmentNew extends BaseOsmAndFragment {
deleteIcon.setVisibility(View.GONE);
nameEdit.selectAll();
nameEdit.requestFocus();
AndroidUtils.softKeyboardDelayed(nameEdit);
AndroidUtils.softKeyboardDelayed(getActivity(), nameEdit);
} else {
toolbarAction.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_delete_dark, activeColorResId));
deleteButton.setVisibility(View.VISIBLE);

View file

@ -150,7 +150,7 @@ public class MapillaryPlugin extends OsmandPlugin {
@Override
public boolean onRowItemClick(ArrayAdapter<ContextMenuItem> adapter, View view, int itemId, int position) {
if (itemId == R.string.mapillary) {
if (itemId == R.string.street_level_imagery) {
mapActivity.getDashboard().setDashboardVisibility(true, DashboardOnMap.DashboardType.MAPILLARY, AndroidUtils.getCenterViewCoordinates(view));
return false;
}
@ -160,7 +160,7 @@ public class MapillaryPlugin extends OsmandPlugin {
@Override
public boolean onContextMenuClick(final ArrayAdapter<ContextMenuItem> adapter, int itemId, final int pos, boolean isChecked, int[] viewCoordinates) {
final OsmandSettings settings = mapActivity.getMyApplication().getSettings();
if (itemId == R.string.mapillary) {
if (itemId == R.string.street_level_imagery) {
OsmandMapTileView mapView = mapActivity.getMapView();
MapActivityLayers mapLayers = mapActivity.getMapLayers();
settings.SHOW_MAPILLARY.set(!settings.SHOW_MAPILLARY.get());

View file

@ -391,7 +391,7 @@ public class CoordinateInputDialogFragment extends DialogFragment implements Osm
}
final View focusedView = getDialog().getCurrentFocus();
if (focusedView != null) {
AndroidUtils.softKeyboardDelayed(focusedView);
AndroidUtils.softKeyboardDelayed(getActivity(), focusedView);
}
}
});
@ -707,7 +707,7 @@ public class CoordinateInputDialogFragment extends DialogFragment implements Osm
final View focusedView = getDialog().getCurrentFocus();
if (focusedView != null) {
if (!isOsmandKeyboardOn()) {
AndroidUtils.softKeyboardDelayed(focusedView);
AndroidUtils.softKeyboardDelayed(getActivity(), focusedView);
}
}
}
@ -1039,7 +1039,7 @@ public class CoordinateInputDialogFragment extends DialogFragment implements Osm
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
AndroidUtils.showSoftKeyboard(focusedView);
AndroidUtils.showSoftKeyboard(getActivity(), focusedView);
}
}, 200);
}
@ -1271,7 +1271,7 @@ public class CoordinateInputDialogFragment extends DialogFragment implements Osm
changeOsmandKeyboardVisibility(true);
}
} else if (!softKeyboardShown && focusedView != null) {
AndroidUtils.softKeyboardDelayed(focusedView);
AndroidUtils.softKeyboardDelayed(getActivity(), focusedView);
}
}

View file

@ -551,7 +551,7 @@ public class MapMarkersDialogFragment extends DialogFragment implements OnGroupS
private final List<Fragment> fragments;
MapMarkersViewPagerAdapter(FragmentManager fm) {
super(fm);
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
fragments = Arrays.asList(activeFragment, groupsFragment, historyFragment);
}

View file

@ -8,7 +8,6 @@ import android.widget.ImageView;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.snackbar.Snackbar;
@ -122,7 +121,7 @@ public class MapMarkersActiveAdapter extends RecyclerView.Adapter<MapMarkerItemV
holder.iconReorder.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
listener.onDragStarted(holder);
}
return false;

View file

@ -9,7 +9,6 @@ import android.view.ViewGroup;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.ContextCompat;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.GPXUtilities.WptPt;
@ -183,7 +182,7 @@ public class MapMarkersListAdapter extends RecyclerView.Adapter<MapMarkerItemVie
holder.iconReorder.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
inDragAndDrop = true;
if (showRoundTripItem) {
int roundTripItemPos = finishPos;

View file

@ -0,0 +1,88 @@
package net.osmand.plus.measurementtool;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemButton;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.ShortDescriptionItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
public class ExitBottomSheetDialogFragment extends MenuBottomSheetDialogFragment {
public static final int REQUEST_CODE = 1001;
public static final int SAVE_RESULT_CODE = 2;
public static final int EXIT_RESULT_CODE = 3;
public static final String TAG = ExitBottomSheetDialogFragment.class.getSimpleName();
@Override
public void createMenuItems(Bundle savedInstanceState) {
items.add(new TitleItem(getString(R.string.exit_without_saving)));
items.add(new ShortDescriptionItem.Builder()
.setDescription(getString(R.string.plan_route_exit_dialog_descr))
.setDescriptionColorId(nightMode ? R.color.text_color_primary_dark : R.color.text_color_primary_light)
.setLayoutId(R.layout.bottom_sheet_item_description_long)
.create());
items.add(new DividerSpaceItem(getContext(),
getResources().getDimensionPixelSize(R.dimen.bottom_sheet_exit_button_margin)));
items.add(new BottomSheetItemButton.Builder()
.setButtonType(UiUtilities.DialogButtonType.SECONDARY)
.setTitle(getString(R.string.shared_string_exit))
.setLayoutId(R.layout.bottom_sheet_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {
targetFragment.onActivityResult(REQUEST_CODE, EXIT_RESULT_CODE, null);
}
dismiss();
}
})
.create());
items.add(new DividerSpaceItem(getContext(),
getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin)));
items.add(new BottomSheetItemButton.Builder()
.setTitle(getString(R.string.shared_string_save))
.setLayoutId(R.layout.bottom_sheet_button)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Fragment targetFragment = getTargetFragment();
if (targetFragment != null) {
targetFragment.onActivityResult(REQUEST_CODE, SAVE_RESULT_CODE, null);
}
dismiss();
}
})
.create());
}
@Override
protected int getDismissButtonTextId() {
return R.string.shared_string_close;
}
public static void showInstance(@NonNull FragmentManager fragmentManager, @Nullable Fragment targetFragment) {
if (!fragmentManager.isStateSaved()) {
ExitBottomSheetDialogFragment fragment = new ExitBottomSheetDialogFragment();
fragment.setTargetFragment(targetFragment, REQUEST_CODE);
fragment.show(fragmentManager, TAG);
}
}
}

View file

@ -31,8 +31,6 @@ import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
import org.apache.commons.logging.Log;
import java.io.IOException;
import static net.osmand.plus.measurementtool.ProfileCard.ProfileCardListener;
import static net.osmand.plus.measurementtool.SliderCard.SliderCardListener;
@ -40,7 +38,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
implements SliderCardListener, ProfileCardListener {
private static final Log LOG = PlatformUtil.getLog(GpxApproximationFragment.class);
public static final String TAG = GpxApproximationFragment.class.getSimpleName();
public static final String TAG = GpxApproximationFragment.class.getName();
public static final String DISTANCE_THRESHOLD_KEY = "distance_threshold";
public static final String SNAP_TO_ROAD_APP_MODE_STRING_KEY = "snap_to_road_app_mode";
@ -49,11 +47,14 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
private int menuTitleHeight;
private ApplicationMode snapToRoadAppMode = ApplicationMode.CAR;
private int distanceThreshold = 50;
private boolean applyApproximation;
private LocationsHolder locationsHolder;
@Nullable
private GpxApproximator gpxApproximator;
private ProgressBar progressBar;
private View cancelButton;
private View applyButton;
@Override
public int getMainLayoutId() {
@ -139,6 +140,8 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
});
}
applyButton = mainView.findViewById(R.id.right_bottom_button);
cancelButton = mainView.findViewById(R.id.dismiss_button);
if (isPortrait()) {
updateCardsLayout();
}
@ -182,10 +185,15 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
@Override
public void onDestroyView() {
super.onDestroyView();
if (gpxApproximator != null) {
gpxApproximator.cancelApproximation();
}
exitGpxApproximationMode();
Fragment fragment = getTargetFragment();
if (fragment instanceof GpxApproximationFragmentListener) {
((GpxApproximationFragmentListener) fragment).onCancelGpxApproximation();
if (!applyApproximation) {
Fragment fragment = getTargetFragment();
if (fragment instanceof GpxApproximationFragmentListener) {
((GpxApproximationFragmentListener) fragment).onCancelGpxApproximation();
}
}
}
@ -213,7 +221,6 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
private void updateButtons(View view) {
View buttonsContainer = view.findViewById(R.id.buttons_container);
buttonsContainer.setBackgroundColor(AndroidUtils.getColorFromAttr(view.getContext(), R.attr.route_info_bg));
View applyButton = view.findViewById(R.id.right_bottom_button);
applyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -221,11 +228,10 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
if (fragment instanceof GpxApproximationFragmentListener) {
((GpxApproximationFragmentListener) fragment).onApplyGpxApproximation();
}
applyApproximation = true;
dismiss();
}
});
View cancelButton = view.findViewById(R.id.dismiss_button);
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -235,14 +241,18 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
}
}
});
UiUtilities.setupDialogButton(isNightMode(), cancelButton, UiUtilities.DialogButtonType.SECONDARY, R.string.shared_string_cancel);
UiUtilities.setupDialogButton(isNightMode(), applyButton, UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_apply);
AndroidUiHelper.updateVisibility(applyButton, true);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.buttons_divider), true);
}
private void setApplyButtonEnabled(boolean enabled) {
if (applyButton != null) {
applyButton.setEnabled(enabled);
}
}
private void updateCards() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
@ -328,14 +338,18 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
@Override
public void onSliderChange(int sliderValue) {
distanceThreshold = sliderValue;
calculateGpxApproximation();
if (distanceThreshold != sliderValue) {
distanceThreshold = sliderValue;
calculateGpxApproximation();
}
}
@Override
public void onProfileSelect(ApplicationMode applicationMode) {
snapToRoadAppMode = applicationMode;
calculateGpxApproximation();
if (snapToRoadAppMode != applicationMode) {
snapToRoadAppMode = applicationMode;
calculateGpxApproximation();
}
}
public LocationsHolder getLocationsHolder() {
@ -370,6 +384,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
private void approximateGpx() {
if (gpxApproximator != null) {
setApplyButtonEnabled(false);
gpxApproximator.calculateGpxApproximation(new ResultMatcher<GpxRouteApproximation>() {
@Override
public boolean publish(final GpxRouteApproximation gpxApproximation) {
@ -380,8 +395,9 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
public void run() {
Fragment fragment = getTargetFragment();
if (fragment instanceof GpxApproximationFragmentListener) {
((GpxApproximationFragmentListener) fragment).onGpxApproximationDone(gpxApproximation);
((GpxApproximationFragmentListener) fragment).onGpxApproximationDone(gpxApproximation, gpxApproximator.getMode());
}
setApplyButtonEnabled(gpxApproximation != null);
}
});
return true;
@ -399,7 +415,7 @@ public class GpxApproximationFragment extends ContextMenuScrollFragment
public interface GpxApproximationFragmentListener {
void onGpxApproximationDone(GpxRouteApproximation gpxApproximation);
void onGpxApproximationDone(GpxRouteApproximation gpxApproximation, ApplicationMode mode);
void onApplyGpxApproximation();

View file

@ -17,7 +17,7 @@ import net.osmand.plus.routing.RouteCalculationResult;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.RouteCalculationProgress;
import net.osmand.router.RoutePlannerFrontEnd;
import net.osmand.router.RouteImporter;
import net.osmand.router.RoutePlannerFrontEnd.GpxPoint;
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
import net.osmand.router.RouteSegmentResult;
@ -26,20 +26,20 @@ import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType.*;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.NEXT_SEGMENT;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.WHOLE_TRACK;
public class MeasurementEditingContext {
public enum CalculationType {
NEXT_SEGMENT,
WHOLE_TRACK
}
public final static ApplicationMode DEFAULT_APP_MODE = ApplicationMode.DEFAULT;
private OsmandApplication application;
private final MeasurementCommandManager commandManager = new MeasurementCommandManager();
@ -55,16 +55,55 @@ public class MeasurementEditingContext {
private WptPt originalPointToMove;
private boolean inAddPointMode;
private boolean inSnapToRoadMode;
private boolean needUpdateCacheForSnap;
private int calculatedPairs;
private CalculationType calculationType = WHOLE_TRACK;
private CalculationMode calculationMode = WHOLE_TRACK;
private SnapToRoadProgressListener progressListener;
private ApplicationMode snapToRoadAppMode;
private ApplicationMode appMode = DEFAULT_APP_MODE;
private RouteCalculationProgress calculationProgress;
private final Queue<Pair<WptPt, WptPt>> snapToRoadPairsToCalculate = new ConcurrentLinkedQueue<>();
private final Map<Pair<WptPt, WptPt>, List<WptPt>> snappedToRoadPoints = new ConcurrentHashMap<>();
private final Map<Pair<WptPt, WptPt>, RoadSegmentData> roadSegmentData = new ConcurrentHashMap<>();
public enum CalculationMode {
NEXT_SEGMENT,
WHOLE_TRACK
}
public static class RoadSegmentData {
private ApplicationMode appMode;
private WptPt start;
private WptPt end;
private List<WptPt> snappedToRoadPoints = new ArrayList<>();
private List<RouteSegmentResult> snappedToRoadSegments = new ArrayList<>();
public RoadSegmentData(ApplicationMode appMode, WptPt start, WptPt end, List<WptPt> snappedToRoadPoints, List<RouteSegmentResult> snappedToRoadSegments) {
this.appMode = appMode;
this.start = start;
this.end = end;
this.snappedToRoadPoints = snappedToRoadPoints;
this.snappedToRoadSegments = snappedToRoadSegments;
}
public ApplicationMode getAppMode() {
return appMode;
}
public WptPt getStart() {
return start;
}
public WptPt getEnd() {
return end;
}
public List<WptPt> getSnappedToRoadPoints() {
return Collections.unmodifiableList(snappedToRoadPoints);
}
public List<RouteSegmentResult> getSnappedToRoadSegments() {
return Collections.unmodifiableList(snappedToRoadSegments);
}
}
public void setApplication(OsmandApplication application) {
this.application = application;
@ -78,10 +117,6 @@ public class MeasurementEditingContext {
return inAddPointMode;
}
boolean isInSnapToRoadMode() {
return inSnapToRoadMode;
}
public boolean isNeedUpdateCacheForSnap() {
return needUpdateCacheForSnap;
}
@ -91,7 +126,7 @@ public class MeasurementEditingContext {
updateCacheForSnapIfNeeded(true);
}
int getSelectedPointPosition() {
public int getSelectedPointPosition() {
return selectedPointPosition;
}
@ -111,8 +146,8 @@ public class MeasurementEditingContext {
this.inAddPointMode = inAddPointMode;
}
void setInSnapToRoadMode(boolean inSnapToRoadMode) {
this.inSnapToRoadMode = inSnapToRoadMode;
boolean isInSnapToRoadMode() {
return appMode != DEFAULT_APP_MODE;
}
NewGpxData getNewGpxData() {
@ -131,31 +166,33 @@ public class MeasurementEditingContext {
return newGpxData != null && newGpxData.getGpxFile() != null && newGpxData.getGpxFile().hasRtePt();
}
public CalculationType getCalculationType() {
return calculationType;
public CalculationMode getCalculationMode() {
return calculationMode;
}
public void setCalculationType(CalculationType calculationType) {
this.calculationType = calculationType;
public void setCalculationMode(CalculationMode calculationMode) {
this.calculationMode = calculationMode;
}
void setProgressListener(SnapToRoadProgressListener progressListener) {
this.progressListener = progressListener;
}
public ApplicationMode getSnapToRoadAppMode() {
return snapToRoadAppMode;
@NonNull
public ApplicationMode getAppMode() {
return appMode;
}
void setSnapToRoadAppMode(ApplicationMode snapToRoadAppMode) {
if (this.snapToRoadAppMode != null && snapToRoadAppMode != null
&& !this.snapToRoadAppMode.getStringKey().equals(snapToRoadAppMode.getStringKey())) {
if (calculationType == WHOLE_TRACK) {
snappedToRoadPoints.clear();
updateCacheForSnapIfNeeded(true);
}
}
this.snapToRoadAppMode = snapToRoadAppMode;
public void setAppMode(@NonNull ApplicationMode appMode) {
this.appMode = appMode;
}
public void resetAppMode() {
this.appMode = DEFAULT_APP_MODE;
}
public void clearSnappedToRoadPoints() {
roadSegmentData.clear();
}
TrkSegment getBeforeTrkSegmentLine() {
@ -228,7 +265,7 @@ public class MeasurementEditingContext {
public void clearSegments() {
before.points.clear();
after.points.clear();
if (inSnapToRoadMode) {
if (isInSnapToRoadMode()) {
if (beforeCacheForSnap != null && afterCacheForSnap != null) {
beforeCacheForSnap.points.clear();
afterCacheForSnap.points.clear();
@ -241,7 +278,7 @@ public class MeasurementEditingContext {
}
}
void scheduleRouteCalculateIfNotEmpty() {
public void scheduleRouteCalculateIfNotEmpty() {
needUpdateCacheForSnap = true;
if (application == null || (before.points.size() == 0 && after.points.size() == 0)) {
return;
@ -267,7 +304,7 @@ public class MeasurementEditingContext {
for (List<WptPt> points : pointsList) {
for (int i = 0; i < points.size() - 1; i++) {
Pair<WptPt, WptPt> pair = new Pair<>(points.get(i), points.get(i + 1));
if (snappedToRoadPoints.get(pair) == null) {
if (roadSegmentData.get(pair) == null) {
snapToRoadPairsToCalculate.add(pair);
}
}
@ -278,11 +315,12 @@ public class MeasurementEditingContext {
if (original.points.size() > 1) {
for (int i = 0; i < original.points.size() - 1; i++) {
Pair<WptPt, WptPt> pair = new Pair<>(original.points.get(i), original.points.get(i + 1));
List<WptPt> pts = snappedToRoadPoints.get(pair);
RoadSegmentData data = this.roadSegmentData.get(pair);
List<WptPt> pts = data != null ? data.getSnappedToRoadPoints() : null;
if (pts != null) {
cache.points.addAll(pts);
} else {
if (inSnapToRoadMode) {
if (isInSnapToRoadMode()) {
scheduleRouteCalculateIfNotEmpty();
}
cache.points.addAll(Arrays.asList(pair.first, pair.second));
@ -300,6 +338,8 @@ public class MeasurementEditingContext {
}
List<WptPt> points = newGpxData.getTrkSegment().points;
if (isTrackSnappedToRoad()) {
RouteImporter routeImporter = new RouteImporter(newGpxData.getGpxFile());
List<RouteSegmentResult> segments = routeImporter.importRoute();
List<WptPt> routePoints = newGpxData.getGpxFile().getRoutePoints();
int prevPointIndex = 0;
for (int i = 0; i < routePoints.size() - 1; i++) {
@ -313,12 +353,20 @@ public class MeasurementEditingContext {
endIndex = findPointIndex(pair.second, points, startIndex);
}
if (startIndex >= 0 && endIndex >= 0) {
List<WptPt> cacheSegment = new ArrayList<>();
List<WptPt> segmentPoints = new ArrayList<>();
for (int j = startIndex; j < endIndex && j < points.size(); j++) {
cacheSegment.add(points.get(j));
segmentPoints.add(points.get(j));
prevPointIndex = j;
}
snappedToRoadPoints.put(pair, cacheSegment);
Iterator<RouteSegmentResult> it = segments.iterator();
int k = endIndex - startIndex;
while (it.hasNext() && k >= 0) {
RouteSegmentResult s = it.next();
it.remove();
k -= Math.abs(s.getEndPointIndex() - s.getStartPointIndex());
}
ApplicationMode appMode = ApplicationMode.valueOfStringKey(pair.first.getProfileType(), DEFAULT_APP_MODE);
roadSegmentData.put(pair, new RoadSegmentData(appMode, pair.first, pair.second, segmentPoints, segments));
}
}
addPoints(routePoints);
@ -327,36 +375,52 @@ public class MeasurementEditingContext {
}
}
void setPoints(GpxRouteApproximation gpxApproximation) {
public void setPoints(GpxRouteApproximation gpxApproximation) {
if (gpxApproximation == null || Algorithms.isEmpty(gpxApproximation.finalPoints) || Algorithms.isEmpty(gpxApproximation.result)) {
return;
}
clearSegments();
List<GpxPoint> routePoints = gpxApproximation.finalPoints;
for (int i = 0; i < routePoints.size() - 1; i++) {
GpxPoint rp1 = routePoints.get(i);
GpxPoint rp2 = routePoints.get(i + 1);
roadSegmentData.clear();
List<WptPt> routePoints = new ArrayList<>();
List<GpxPoint> gpxPoints = gpxApproximation.finalPoints;
for (int i = 0; i < gpxPoints.size() - 1; i++) {
GpxPoint rp1 = gpxPoints.get(i);
GpxPoint rp2 = gpxPoints.get(i + 1);
WptPt p1 = new WptPt();
p1.lat = rp1.loc.getLatitude();
p1.lon = rp1.loc.getLongitude();
if (i == 0) {
routePoints.add(p1);
}
WptPt p2 = new WptPt();
p2.lat = rp2.loc.getLatitude();
p2.lon = rp2.loc.getLongitude();
routePoints.add(p2);
Pair<WptPt, WptPt> pair = new Pair<>(p1, p2);
List<WptPt> cacheSegment = new ArrayList<>();
List<WptPt> points = new ArrayList<>();
List<RouteSegmentResult> segments = new ArrayList<>();
for (RouteSegmentResult seg : rp1.routeToTarget) {
int start = seg.isForwardDirection() ? seg.getStartPointIndex() : seg.getEndPointIndex();
int end = seg.isForwardDirection() ? seg.getEndPointIndex() : seg.getStartPointIndex();
for (int ik = start; ik <= end; ik++) {
LatLon l = seg.getPoint(ik);
WptPt pt = new WptPt();
pt.lat = l.getLatitude();
pt.lon = l.getLongitude();
cacheSegment.add(pt);
segments.add(seg);
if (seg.isForwardDirection()) {
for (int ik = seg.getStartPointIndex(); ik <= seg.getEndPointIndex(); ik++) {
LatLon l = seg.getPoint(ik);
WptPt pt = new WptPt();
pt.lat = l.getLatitude();
pt.lon = l.getLongitude();
points.add(pt);
}
} else {
for (int ik = seg.getEndPointIndex(); ik >= seg.getStartPointIndex(); ik--) {
LatLon l = seg.getPoint(ik);
WptPt pt = new WptPt();
pt.lat = l.getLatitude();
pt.lon = l.getLongitude();
points.add(pt);
}
}
}
snappedToRoadPoints.put(pair, cacheSegment);
roadSegmentData.put(pair, new RoadSegmentData(appMode, pair.first, pair.second, points, segments));
}
addPoints(routePoints);
}
private int findPointIndex(WptPt point, List<WptPt> points, int firstIndex) {
@ -376,7 +440,7 @@ public class MeasurementEditingContext {
NewGpxData newGpxData = getNewGpxData();
return newGpxData != null && newGpxData.getTrkSegment() != null
&& !newGpxData.getTrkSegment().points.isEmpty()
&& !newGpxData.getGpxFile().getRoutePoints().isEmpty();
&& newGpxData.getGpxFile().hasRoute();
}
private void updateCacheForSnapIfNeeded(boolean both) {
@ -411,9 +475,23 @@ public class MeasurementEditingContext {
final RouteCalculationParams params = new RouteCalculationParams();
params.inSnapToRoadMode = true;
params.start = start;
ApplicationMode currentPointSnapToRoadMode;
if (calculationMode == NEXT_SEGMENT) {
currentPointSnapToRoadMode = ApplicationMode.valueOfStringKey(currentPair.first.getProfileType(),
null);
} else {
currentPointSnapToRoadMode = appMode;
}
params.end = end;
RoutingHelper.applyApplicationSettings(params, application.getSettings(), snapToRoadAppMode);
params.mode = snapToRoadAppMode;
if (currentPointSnapToRoadMode == null) {
ApplicationMode straightLine = ApplicationMode.AIRCRAFT;
RoutingHelper.applyApplicationSettings(params, application.getSettings(), straightLine);
params.mode = straightLine;
} else {
RoutingHelper.applyApplicationSettings(params, application.getSettings(), currentPointSnapToRoadMode);
params.mode = currentPointSnapToRoadMode;
}
params.ctx = application;
params.calculationProgress = calculationProgress = new RouteCalculationProgress();
params.calculationProgressCallback = new RoutingHelper.RouteCalculationProgressCallback() {
@ -460,7 +538,7 @@ public class MeasurementEditingContext {
pts.add(pt);
}
calculatedPairs++;
snappedToRoadPoints.put(currentPair, pts);
roadSegmentData.put(currentPair, new RoadSegmentData(route.getAppMode(), currentPair.first, currentPair.second, pts, route.getOriginalRoute()));
int trkptIndex = currentPair.first.getTrkPtIndex();
trkptIndex += pts.size() - 1;
currentPair.second.setTrkPtIndex(trkptIndex);
@ -539,8 +617,14 @@ public class MeasurementEditingContext {
params.start = start;
params.end = end;
params.intermediates = intermediates;
RoutingHelper.applyApplicationSettings(params, application.getSettings(), snapToRoadAppMode);
params.mode = snapToRoadAppMode;
if (appMode == null) {
ApplicationMode straightLine = ApplicationMode.AIRCRAFT;
RoutingHelper.applyApplicationSettings(params, application.getSettings(), straightLine);
params.mode = straightLine;
} else {
RoutingHelper.applyApplicationSettings(params, application.getSettings(), appMode);
params.mode = appMode;
}
params.ctx = application;
params.calculationProgress = calculationProgress = new RouteCalculationProgress();
params.calculationProgressCallback = new RoutingHelper.RouteCalculationProgressCallback() {

View file

@ -15,8 +15,8 @@ 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.CompoundButton;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -70,6 +70,8 @@ import net.osmand.plus.measurementtool.SelectedPointBottomSheetDialogFragment.Se
import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter;
import net.osmand.plus.measurementtool.adapter.MeasurementToolAdapter.MeasurementAdapterListener;
import net.osmand.plus.measurementtool.command.AddPointCommand;
import net.osmand.plus.measurementtool.command.ChangeRouteModeCommand;
import net.osmand.plus.measurementtool.command.ApplyGpxApproximationCommand;
import net.osmand.plus.measurementtool.command.ClearPointsCommand;
import net.osmand.plus.measurementtool.command.MovePointCommand;
import net.osmand.plus.measurementtool.command.RemovePointCommand;
@ -93,7 +95,7 @@ import java.util.List;
import java.util.Locale;
import static net.osmand.IndexConstants.GPX_FILE_EXT;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.ExportAsGpxListener;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.SnapToRoadProgressListener;
import static net.osmand.plus.measurementtool.SelectFileBottomSheet.Mode.ADD_TO_TRACK;
@ -161,6 +163,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
final MapActivity mapActivity = (MapActivity) getActivity();
if (mapActivity == null) {
return null;
}
final MeasurementToolLayer measurementLayer = mapActivity.getMapLayers().getMeasurementToolLayer();
editingCtx.setApplication(mapActivity.getMyApplication());
@ -215,7 +220,9 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
AndroidUtils.setBackground(mapActivity, mainView, nightMode, R.drawable.bg_bottom_menu_light, R.drawable.bg_bottom_menu_dark);
pointsListContainer = view.findViewById(R.id.points_list_container);
if (portrait && pointsListContainer != null) {
final int backgroundColor = ContextCompat.getColor(mapActivity, nightMode ? R.color.activity_background_color_dark : R.color.activity_background_color_light);
final int backgroundColor = ContextCompat.getColor(mapActivity, nightMode
? R.color.activity_background_color_dark
: R.color.activity_background_color_light);
pointsListContainer.setBackgroundColor(backgroundColor);
}
@ -231,14 +238,14 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
upDownBtn = (ImageView) mainView.findViewById(R.id.up_down_button);
upDownBtn.setImageDrawable(upIcon);
mainView.findViewById(R.id.cancel_move_point_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.cancel_move_point_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
cancelMovePointMode();
}
});
mainView.findViewById(R.id.cancel_point_before_after_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.cancel_point_before_after_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
cancelAddPointBeforeOrAfterMode();
@ -246,7 +253,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
});
upDownRow = mainView.findViewById(R.id.up_down_row);
upDownRow.setOnClickListener(new View.OnClickListener() {
upDownRow.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (!pointsListOpened && editingCtx.getPointsCount() > 0 && editingCtx.getSelectedPointPosition() == -1) {
@ -257,37 +264,35 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
});
mainView.findViewById(R.id.apply_move_point_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.apply_move_point_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
applyMovePointMode();
}
});
mainView.findViewById(R.id.apply_point_before_after_point_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.apply_point_before_after_point_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
applyAddPointBeforeAfterMode();
}
});
mainView.findViewById(R.id.add_point_before_after_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.add_point_before_after_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
addPointBeforeAfter();
}
});
mainView.findViewById(R.id.options_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.options_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
OptionsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
MeasurementToolFragment.this,
editingCtx.isTrackSnappedToRoad() || editingCtx.isNewData(),
editingCtx.isInSnapToRoadMode(),
editingCtx.getSnapToRoadAppMode() != null
? editingCtx.getSnapToRoadAppMode().getStringKey()
: null
editingCtx.getAppMode().getStringKey()
);
}
});
@ -297,39 +302,29 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
Drawable undoDrawable = getActiveIcon(R.drawable.ic_action_undo_dark);
undoBtn.setImageDrawable(AndroidUtils.getDrawableForDirection(mapActivity, undoDrawable));
undoBtn.setOnClickListener(new View.OnClickListener() {
undoBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
editingCtx.getCommandManager().undo();
updateUndoRedoButton(editingCtx.getCommandManager().canUndo(), undoBtn);
hidePointsListIfNoPoints();
if (editingCtx.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
updateUndoRedoButton(true, redoBtn);
updateDistancePointsText();
updateUndoRedoCommonStuff();
}
});
Drawable redoDrawable = getActiveIcon(R.drawable.ic_action_redo_dark);
redoBtn.setImageDrawable(AndroidUtils.getDrawableForDirection(mapActivity, redoDrawable));
redoBtn.setOnClickListener(new View.OnClickListener() {
redoBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
editingCtx.getCommandManager().redo();
updateUndoRedoButton(editingCtx.getCommandManager().canRedo(), redoBtn);
hidePointsListIfNoPoints();
if (editingCtx.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
updateUndoRedoButton(true, undoBtn);
updateDistancePointsText();
updateUndoRedoCommonStuff();
}
});
mainView.findViewById(R.id.add_point_button).setOnClickListener(new View.OnClickListener() {
mainView.findViewById(R.id.add_point_button).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
addCenterPoint();
@ -405,25 +400,19 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
} else {
toolBarController.setTitle(getString(R.string.plan_route));
}
toolBarController.setOnBackButtonClickListener(new View.OnClickListener() {
toolBarController.setOnBackButtonClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
quit(false);
}
});
toolBarController.setOnSaveViewClickListener(new View.OnClickListener() {
toolBarController.setOnSaveViewClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (editingCtx.getPointsCount() > 0) {
if (newGpxData != null && newGpxData.getActionType() == ActionType.EDIT_SEGMENT
&& editingCtx.isInSnapToRoadMode()) {
if (mapActivity != null) {
if (editingCtx.getPointsCount() > 0) {
openSaveAsNewTrackMenu(mapActivity);
} else {
Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
}
}
} else {
if (newGpxData == null) {
final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
@ -438,14 +427,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
}
});
toolBarController.setOnSwitchCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (!checked) {
disableSnapToRoadMode();
}
}
});
mapActivity.showTopToolbar(toolBarController);
adapter = new MeasurementToolAdapter(getMapActivity(), editingCtx.getPoints(),
@ -461,6 +442,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
pointsRv.setLayoutManager(new LinearLayoutManager(getContext()));
pointsRv.setAdapter(adapter);
ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle);
snapToRoadBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
startSnapToRoad(false);
}
});
snapToRoadBtn.setVisibility(View.VISIBLE);
initMeasurementMode(newGpxData);
if (planRouteMode && savedInstanceState == null) {
@ -470,33 +461,45 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
return view;
}
private void updateUndoRedoCommonStuff() {
hidePointsListIfNoPoints();
if (editingCtx.getPointsCount() > 0) {
enable(upDownBtn);
}
adapter.notifyDataSetChanged();
updateDistancePointsText();
updateSnapToRoadControls();
}
private void initMeasurementMode(NewGpxData newGpxData) {
editingCtx.getCommandManager().resetMeasurementLayer(getMapActivity().getMapLayers().getMeasurementToolLayer());
enterMeasurementMode();
showSnapToRoadControls();
if (newGpxData != null && !gpxPointsAdded) {
List<WptPt> points = newGpxData.getGpxFile().getRoutePoints();
if (!points.isEmpty()) {
ApplicationMode snapToRoadAppMode = ApplicationMode
.valueOfStringKey(points.get(points.size() - 1).getProfileType(), null);
if (snapToRoadAppMode != null) {
enableSnapToRoadMode(snapToRoadAppMode);
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
editingCtx.getCommandManager().setMeasurementLayer(mapActivity.getMapLayers().getMeasurementToolLayer());
enterMeasurementMode();
updateSnapToRoadControls();
if (newGpxData != null && !gpxPointsAdded) {
List<WptPt> points = newGpxData.getGpxFile().getRoutePoints();
if (!points.isEmpty()) {
ApplicationMode snapToRoadAppMode = ApplicationMode.valueOfStringKey(points.get(points.size() - 1).getProfileType(), null);
if (snapToRoadAppMode != null) {
setSnapToRoadMode(snapToRoadAppMode);
}
}
ActionType actionType = newGpxData.getActionType();
if (actionType == ActionType.ADD_ROUTE_POINTS) {
displayRoutePoints();
gpxPointsAdded = true;
} else if (actionType == ActionType.EDIT_SEGMENT) {
displaySegmentPoints();
gpxPointsAdded = true;
}
}
ActionType actionType = newGpxData.getActionType();
if (actionType == ActionType.ADD_ROUTE_POINTS) {
displayRoutePoints();
gpxPointsAdded = true;
} else if (actionType == ActionType.EDIT_SEGMENT) {
displaySegmentPoints();
gpxPointsAdded = true;
if (saved == null) {
saved = newGpxData != null
&& (newGpxData.getActionType() == ActionType.ADD_ROUTE_POINTS
|| newGpxData.getActionType() == ActionType.EDIT_SEGMENT);
}
}
if (saved == null) {
saved = newGpxData != null
&& (newGpxData.getActionType() == ActionType.ADD_ROUTE_POINTS
|| newGpxData.getActionType() == ActionType.EDIT_SEGMENT);
}
}
@Override
@ -541,7 +544,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Nullable
private MapActivity getMapActivity() {
Activity activity = getActivity();
if (activity instanceof MapActivity && !activity.isFinishing()) {
if (AndroidUtils.isActivityNotDestroyed(activity)) {
return (MapActivity) activity;
}
return null;
@ -595,10 +598,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
toolBarController.setTitle(getString(R.string.route_between_points));
mapActivity.refreshMap();
if (editingCtx.isNewData() || editingCtx.hasRoutePoints()) {
if (editingCtx.isNewData() || editingCtx.hasRoutePoints() || editingCtx.isInSnapToRoadMode()) {
RouteBetweenPointsBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(),
this, editingCtx.getCalculationType(),
editingCtx.getSnapToRoadAppMode());
this, editingCtx.getCalculationMode(),
editingCtx.getAppMode());
} else {
SnapTrackWarningBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), this);
}
@ -608,20 +611,31 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SnapTrackWarningBottomSheet.REQUEST_CODE) {
switch (resultCode) {
case SnapTrackWarningBottomSheet.CANCEL_REQUEST_CODE:
toolBarController.setSaveViewVisible(true);
updateToolbar();
break;
case SnapTrackWarningBottomSheet.CONTINUE_REQUEST_CODE:
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
this, new LocationsHolder(editingCtx.getPoints()));
}
break;
}
switch (requestCode) {
case SnapTrackWarningBottomSheet.REQUEST_CODE:
switch (resultCode) {
case SnapTrackWarningBottomSheet.CANCEL_RESULT_CODE:
toolBarController.setSaveViewVisible(true);
updateToolbar();
break;
case SnapTrackWarningBottomSheet.CONTINUE_RESULT_CODE:
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
GpxApproximationFragment.showInstance(mapActivity.getSupportFragmentManager(),
this, new LocationsHolder(editingCtx.getPoints()));
}
break;
}
break;
case ExitBottomSheetDialogFragment.REQUEST_CODE:
switch (resultCode) {
case ExitBottomSheetDialogFragment.EXIT_RESULT_CODE:
dismiss(getMapActivity());
break;
case ExitBottomSheetDialogFragment.SAVE_RESULT_CODE:
openSaveAsNewTrackMenu(getMapActivity());
break;
}
}
}
@ -667,17 +681,10 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
}
@Override
public void saveAsNewTrackOnClick() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
if (editingCtx.getPointsCount() > 0) {
openSaveAsNewTrackMenu(mapActivity);
} else {
Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
@Override
public void saveAsNewTrackOnClick() {
openSaveAsNewTrackMenu(getMapActivity());
}
}
}
@Override
public void addToTheTrackOnClick() {
@ -719,40 +726,35 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
switchMovePointMode(true);
}
@Override
public void onDeletePoint() {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
removePoint(measurementLayer, editingCtx.getSelectedPointPosition());
}
editingCtx.setSelectedPointPosition(-1);
}
@Override
public void deleteOnClick() {
removePoint(measurementLayer, editingCtx.getSelectedPointPosition());
editingCtx.setSelectedPointPosition(-1);
}
@Override
public void onAddPointAfter() {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
measurementLayer.moveMapToPoint(editingCtx.getSelectedPointPosition());
editingCtx.setInAddPointMode(true);
editingCtx.splitSegments(editingCtx.getSelectedPointPosition() + 1);
}
((TextView) mainView.findViewById(R.id.add_point_before_after_text)).setText(mainView.getResources().getString(R.string.add_point_after));
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_addpoint_above));
switchAddPointBeforeAfterMode(true);
}
@Override
public void addPointAfterOnClick() {
if (measurementLayer != null) {
measurementLayer.moveMapToPoint(editingCtx.getSelectedPointPosition());
editingCtx.setInAddPointMode(true);
editingCtx.splitSegments(editingCtx.getSelectedPointPosition() + 1);
}
((TextView) mainView.findViewById(R.id.add_point_before_after_text)).setText(mainView.getResources().getString(R.string.add_point_after));
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_addpoint_above));
switchAddPointBeforeAfterMode(true);
}
@Override
public void onAddPointBefore() {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
measurementLayer.moveMapToPoint(editingCtx.getSelectedPointPosition());
editingCtx.setInAddPointMode(true);
editingCtx.splitSegments(editingCtx.getSelectedPointPosition());
}
((TextView) mainView.findViewById(R.id.add_point_before_after_text)).setText(mainView.getResources().getString(R.string.add_point_before));
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_addpoint_below));
switchAddPointBeforeAfterMode(true);
}
@Override
public void addPointBeforeOnClick() {
if (measurementLayer != null) {
measurementLayer.moveMapToPoint(editingCtx.getSelectedPointPosition());
editingCtx.setInAddPointMode(true);
editingCtx.splitSegments(editingCtx.getSelectedPointPosition());
}
((TextView) mainView.findViewById(R.id.add_point_before_after_text)).setText(mainView.getResources().getString(R.string.add_point_before));
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_addpoint_below));
switchAddPointBeforeAfterMode(true);
}
@Override
public void onTrimRouteBefore() {
@ -796,21 +798,17 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
@Override
public void onChangeApplicationMode(ApplicationMode mode) {
if (mode == null) {
disableSnapToRoadMode();
editingCtx.setSnapToRoadAppMode(null);
showSnapToRoadControls();
} else {
enableSnapToRoadMode(mode);
public void onChangeApplicationMode(ApplicationMode mode, CalculationMode calculationMode) {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
editingCtx.getCommandManager().execute(new ChangeRouteModeCommand(measurementLayer, mode, calculationMode));
updateUndoRedoButton(false, redoBtn);
disable(upDownBtn);
updateSnapToRoadControls();
updateDistancePointsText();
}
}
@Override
public void onChangeCalculationType(CalculationType calculationType) {
editingCtx.setCalculationType(calculationType);
}
private StartPlanRouteListener createStartPlanRouteListener() {
return new StartPlanRouteListener() {
@Override
@ -825,6 +823,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void openLastEditTrackOnClick(String gpxFileName) {
addNewGpxData(getGpxFile(gpxFileName));
saved = true;
}
@Override
@ -839,6 +838,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void selectFileOnCLick(String gpxFileName) {
addNewGpxData(getGpxFile(gpxFileName));
saved = true;
}
@Override
@ -916,14 +916,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
return null;
}
private void removePoint(MeasurementToolLayer layer, int position) {
editingCtx.getCommandManager().execute(new RemovePointCommand(layer, position));
adapter.notifyDataSetChanged();
updateUndoRedoButton(true, undoBtn);
updateUndoRedoButton(false, redoBtn);
updateDistancePointsText();
saved = false;
hidePointsListIfNoPoints();
private void removePoint(MeasurementToolLayer measurementLayer, int position) {
if (measurementLayer != null) {
editingCtx.getCommandManager().execute(new RemovePointCommand(measurementLayer, position));
adapter.notifyDataSetChanged();
updateUndoRedoButton(true, undoBtn);
updateUndoRedoButton(false, redoBtn);
updateDistancePointsText();
saved = false;
hidePointsListIfNoPoints();
}
}
private SaveAsNewTrackFragmentListener createSaveAsNewTrackFragmentListener() {
@ -950,9 +952,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
@Override
public void onRemoveClick(int position) {
if (measurementLayer != null) {
removePoint(measurementLayer, position);
}
removePoint(measurementLayer, position);
}
@Override
@ -992,42 +992,17 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
};
}
private void enableSnapToRoadMode(ApplicationMode appMode) {
editingCtx.setSnapToRoadAppMode(appMode);
editingCtx.setInSnapToRoadMode(true);
private void setSnapToRoadMode(@NonNull ApplicationMode appMode) {
editingCtx.setAppMode(appMode);
editingCtx.scheduleRouteCalculateIfNotEmpty();
showSnapToRoadControls();
updateSnapToRoadControls();
}
private void showSnapToRoadControls() {
final MapActivity mapActivity = getMapActivity();
final ApplicationMode appMode = editingCtx.getSnapToRoadAppMode();
if (mapActivity != null) {
Drawable icon;
if (appMode == null) {
icon = getActiveIcon(R.drawable.ic_action_split_interval);
} else {
icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode));
}
ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
snapToRoadBtn.setBackgroundResource(nightMode ? R.drawable.btn_circle_night : R.drawable.btn_circle);
snapToRoadBtn.setImageDrawable(icon);
snapToRoadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startSnapToRoad(false);
}
});
snapToRoadBtn.setVisibility(View.VISIBLE);
mapActivity.refreshMap();
}
}
private void disableSnapToRoadMode() {
private void resetSnapToRoadMode() {
toolBarController.setTopBarSwitchVisible(false);
toolBarController.setTitle(previousToolBarTitle);
mainIcon.setImageDrawable(getActiveIcon(R.drawable.ic_action_ruler));
editingCtx.setInSnapToRoadMode(false);
editingCtx.resetAppMode();
editingCtx.cancelSnapToRoad();
visibleSnapToRoadIcon(false);
MapActivity mapActivity = getMapActivity();
@ -1037,6 +1012,22 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
}
private void updateSnapToRoadControls() {
final MapActivity mapActivity = getMapActivity();
final ApplicationMode appMode = editingCtx.getAppMode();
if (mapActivity != null) {
Drawable icon;
if (appMode == MeasurementEditingContext.DEFAULT_APP_MODE) {
icon = getActiveIcon(R.drawable.ic_action_split_interval);
} else {
icon = getIcon(appMode.getIconRes(), appMode.getIconColorInfo().getColor(nightMode));
}
ImageButton snapToRoadBtn = (ImageButton) mapActivity.findViewById(R.id.snap_to_road_image_button);
snapToRoadBtn.setImageDrawable(icon);
mapActivity.refreshMap();
}
}
private void visibleSnapToRoadIcon(boolean show) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
@ -1068,15 +1059,6 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
}
public void displayApproximatedPoints(GpxRouteApproximation gpxApproximation) {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
editingCtx.setPoints(gpxApproximation);
adapter.notifyDataSetChanged();
updateDistancePointsText();
}
}
private void openSelectedPointMenu(MapActivity mapActivity) {
if (mapActivity != null) {
SelectedPointBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), this);
@ -1084,10 +1066,16 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
private void openSaveAsNewTrackMenu(MapActivity mapActivity) {
SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment();
fragment.setUsedOnMap(true);
fragment.setListener(createSaveAsNewTrackFragmentListener());
fragment.show(mapActivity.getSupportFragmentManager(), SaveAsNewTrackBottomSheetDialogFragment.TAG);
if (mapActivity != null) {
if (editingCtx.getPointsCount() > 0) {
SaveAsNewTrackBottomSheetDialogFragment fragment = new SaveAsNewTrackBottomSheetDialogFragment();
fragment.setUsedOnMap(true);
fragment.setListener(createSaveAsNewTrackFragmentListener());
fragment.show(mapActivity.getSupportFragmentManager(), SaveAsNewTrackBottomSheetDialogFragment.TAG);
} else {
Toast.makeText(mapActivity, getString(R.string.none_point_error), Toast.LENGTH_SHORT).show();
}
}
}
private void showAddToTrackDialog(final MapActivity mapActivity) {
@ -1102,8 +1090,8 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
WptPt newPoint = measurementLayer.getMovedPointToApply();
ApplicationMode applicationMode = editingCtx.getSnapToRoadAppMode();
if (applicationMode != null) {
ApplicationMode applicationMode = editingCtx.getAppMode();
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
newPoint.setProfileType(applicationMode.getStringKey());
}
WptPt oldPoint = editingCtx.getOriginalPointToMove();
@ -1373,7 +1361,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
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 View.OnClickListener() {
buttonView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showOnMapToggle.setChecked(!showOnMapToggle.isChecked());
@ -1632,7 +1620,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
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 View.OnClickListener() {
.setAction(R.string.shared_string_rename, new OnClickListener() {
@Override
public void onClick(View view) {
MapActivity mapActivity = mapActivityRef.get();
@ -1789,51 +1777,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
dismiss(mapActivity);
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(UiUtilities.getThemedContext(mapActivity, nightMode));
if (editingCtx.isNewData()) {
final File dir = mapActivity.getMyApplication().getAppPath(IndexConstants.GPX_INDEX_DIR);
final View view = UiUtilities.getInflater(mapActivity, nightMode).inflate(R.layout.close_measurement_tool_dialog, null);
final SwitchCompat showOnMapToggle = (SwitchCompat) view.findViewById(R.id.toggle_show_on_map);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showOnMapToggle.setChecked(!showOnMapToggle.isChecked());
}
});
builder.setView(view);
builder.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (showOnMapToggle.isChecked()) {
final String name = new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date());
String fileName = name + GPX_FILE_EXT;
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, true, SaveType.LINE, true);
} else {
dismiss(mapActivity);
}
}
});
UiUtilities.setupCompoundButton(showOnMapToggle, nightMode, UiUtilities.CompoundButtonType.GLOBAL);
} else {
builder.setPositiveButton(R.string.shared_string_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dismiss(mapActivity);
}
});
}
builder.setTitle(getString(R.string.exit_without_saving))
.setMessage(getString(R.string.unsaved_changes_will_be_lost))
.setNegativeButton(R.string.shared_string_cancel, null);
builder.show();
ExitBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager(), this);
}
}
@ -1844,7 +1788,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
hidePointsList();
}
if (editingCtx.isInSnapToRoadMode()) {
disableSnapToRoadMode();
resetSnapToRoadMode();
} else {
visibleSnapToRoadIcon(false);
}
@ -1939,17 +1883,28 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
}
@Override
public void onGpxApproximationDone(GpxRouteApproximation gpxApproximation) {
displayApproximatedPoints(gpxApproximation);
public void onGpxApproximationDone(GpxRouteApproximation gpxApproximation, ApplicationMode mode) {
MeasurementToolLayer measurementLayer = getMeasurementLayer();
if (measurementLayer != null) {
ApplyGpxApproximationCommand command = new ApplyGpxApproximationCommand(measurementLayer, gpxApproximation, mode);
if (!editingCtx.getCommandManager().update(command)) {
editingCtx.getCommandManager().execute(command);
}
if (pointsListOpened) {
hidePointsList();
}
updateSnapToRoadControls();
}
}
@Override
public void onApplyGpxApproximation() {
doAddOrMovePointCommonStuff();
}
@Override
public void onCancelGpxApproximation() {
editingCtx.getCommandManager().undo();
updateSnapToRoadControls();
}
}

View file

@ -324,8 +324,8 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
if (allowed) {
ApplicationMode applicationMode = editingCtx.getSnapToRoadAppMode();
if (applicationMode != null) {
ApplicationMode applicationMode = editingCtx.getAppMode();
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
pt.setProfileType(applicationMode.getStringKey());
}
editingCtx.addPoint(pt);
@ -344,8 +344,8 @@ public class MeasurementToolLayer extends OsmandMapLayer implements ContextMenuL
pressedPointLatLon = null;
boolean allowed = editingCtx.getPointsCount() == 0 || !editingCtx.getPoints().get(editingCtx.getPointsCount() - 1).equals(pt);
if (allowed) {
ApplicationMode applicationMode = editingCtx.getSnapToRoadAppMode();
if (applicationMode != null) {
ApplicationMode applicationMode = editingCtx.getAppMode();
if (applicationMode != MeasurementEditingContext.DEFAULT_APP_MODE) {
pt.setProfileType(applicationMode.getStringKey());
}
editingCtx.addPoint(pt);

View file

@ -26,7 +26,7 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.BottomSheetDialogFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType;
import net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode;
import net.osmand.plus.settings.backend.ApplicationMode;
import org.apache.commons.logging.Log;
@ -35,22 +35,22 @@ import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.UiUtilities.CustomRadioButtonType.*;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType.NEXT_SEGMENT;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationType.WHOLE_TRACK;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.NEXT_SEGMENT;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.CalculationMode.WHOLE_TRACK;
public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDialogFragment {
private static final Log LOG = PlatformUtil.getLog(RouteBetweenPointsBottomSheetDialogFragment.class);
public static final String TAG = RouteBetweenPointsBottomSheetDialogFragment.class.getSimpleName();
public static final int STRAIGHT_LINE_TAG = -1;
public static final String CALCULATION_TYPE_KEY = "calculation_type";
public static final String CALCULATION_MODE_KEY = "calculation_type";
public static final String ROUTE_APP_MODE_KEY = "route_app_mode";
private boolean nightMode;
private boolean portrait;
private boolean snapToRoadEnabled;
private boolean snapToRoadEnabled = true;
private TextView btnDescription;
private CalculationType calculationType = WHOLE_TRACK;
private CalculationMode calculationMode = WHOLE_TRACK;
private ApplicationMode snapToRoadAppMode;
private LinearLayout customRadioButton;
@ -61,10 +61,10 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
Bundle args = getArguments();
if (args != null) {
snapToRoadAppMode = ApplicationMode.valueOfStringKey(args.getString(ROUTE_APP_MODE_KEY), null);
calculationType = (CalculationType) args.get(CALCULATION_TYPE_KEY);
calculationMode = (CalculationMode) args.get(CALCULATION_MODE_KEY);
}
if (savedInstanceState != null) {
calculationType = (CalculationType) savedInstanceState.get(CALCULATION_TYPE_KEY);
calculationMode = (CalculationMode) savedInstanceState.get(CALCULATION_MODE_KEY);
}
OsmandApplication app = requiredMyApplication();
nightMode = app.getDaynightHelper().isNightModeForMapControls();
@ -108,7 +108,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
}
Fragment fragment = getTargetFragment();
if (fragment instanceof RouteBetweenPointsFragmentListener) {
((RouteBetweenPointsFragmentListener) fragment).onChangeApplicationMode(mode);
((RouteBetweenPointsFragmentListener) fragment).onChangeApplicationMode(mode, calculationMode);
}
dismiss();
}
@ -137,7 +137,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
updateModeButtons(WHOLE_TRACK);
}
});
updateModeButtons(calculationType);
updateModeButtons(calculationMode);
return mainView;
}
@ -150,19 +150,15 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
container.addView(row);
}
private void updateModeButtons(CalculationType calculationType) {
if (calculationType == NEXT_SEGMENT) {
private void updateModeButtons(CalculationMode calculationMode) {
if (calculationMode == NEXT_SEGMENT) {
UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode, LEFT);
btnDescription.setText(R.string.rourte_between_points_next_segment_button_desc);
} else {
btnDescription.setText(R.string.rourte_between_points_whole_track_button_desc);
UiUtilities.updateCustomRadioButtons(getMyApplication(), customRadioButton, nightMode, RIGHT);
}
setCalculationType(calculationType);
Fragment fragment = getTargetFragment();
if (fragment instanceof RouteBetweenPointsFragmentListener) {
((RouteBetweenPointsFragmentListener) fragment).onChangeCalculationType(calculationType);
}
setCalculationMode(calculationMode);
}
private void addProfileView(LinearLayout container, View.OnClickListener onClickListener, Object tag,
@ -197,7 +193,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(CALCULATION_TYPE_KEY, calculationType);
outState.putSerializable(CALCULATION_MODE_KEY, calculationMode);
}
@Override
@ -209,18 +205,18 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
super.onDestroyView();
}
public void setCalculationType(CalculationType calculationType) {
this.calculationType = calculationType;
public void setCalculationMode(CalculationMode calculationMode) {
this.calculationMode = calculationMode;
}
public static void showInstance(FragmentManager fm, Fragment targetFragment, CalculationType calculationType,
public static void showInstance(FragmentManager fm, Fragment targetFragment, CalculationMode calculationMode,
ApplicationMode applicationMode) {
try {
if (!fm.isStateSaved()) {
RouteBetweenPointsBottomSheetDialogFragment fragment = new RouteBetweenPointsBottomSheetDialogFragment();
Bundle args = new Bundle();
args.putString(ROUTE_APP_MODE_KEY, applicationMode != null ? applicationMode.getStringKey() : null);
args.putSerializable(CALCULATION_TYPE_KEY, calculationType);
args.putSerializable(CALCULATION_MODE_KEY, calculationMode);
fragment.setArguments(args);
fragment.setTargetFragment(targetFragment, 0);
fragment.show(fm, TAG);
@ -234,8 +230,7 @@ public class RouteBetweenPointsBottomSheetDialogFragment extends BottomSheetDial
void onCloseRouteDialog(boolean snapToRoadEnabled);
void onChangeApplicationMode(ApplicationMode mode);
void onChangeApplicationMode(ApplicationMode mode, CalculationMode calculationMode);
void onChangeCalculationType(CalculationType calculationType);
}
}

View file

@ -23,8 +23,8 @@ import org.apache.commons.logging.Log;
public class SnapTrackWarningBottomSheet extends MenuBottomSheetDialogFragment {
public static final int REQUEST_CODE = 1000;
public static final int CANCEL_REQUEST_CODE = 2;
public static final int CONTINUE_REQUEST_CODE = 3;
public static final int CANCEL_RESULT_CODE = 2;
public static final int CONTINUE_RESULT_CODE = 3;
public static final String TAG = SnapTrackWarningBottomSheet.class.getSimpleName();
private static final Log LOG = PlatformUtil.getLog(SnapTrackWarningBottomSheet.class);
@ -58,7 +58,7 @@ public class SnapTrackWarningBottomSheet extends MenuBottomSheetDialogFragment {
protected void onRightBottomButtonClick() {
Fragment fragment = getTargetFragment();
if (fragment != null) {
fragment.onActivityResult(REQUEST_CODE, CONTINUE_REQUEST_CODE, null);
fragment.onActivityResult(REQUEST_CODE, CONTINUE_RESULT_CODE, null);
}
dismiss();
}
@ -77,7 +77,7 @@ public class SnapTrackWarningBottomSheet extends MenuBottomSheetDialogFragment {
}
Fragment fragment = getTargetFragment();
if (fragment != null) {
fragment.onActivityResult(REQUEST_CODE, CANCEL_REQUEST_CODE, null);
fragment.onActivityResult(REQUEST_CODE, CANCEL_RESULT_CODE, null);
}
}

View file

@ -11,7 +11,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.view.MotionEventCompat;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.GPXUtilities.WptPt;
@ -67,7 +66,7 @@ public class MeasurementToolAdapter extends RecyclerView.Adapter<MeasurementTool
holder.iconReorder.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
listener.onDragStarted(holder);
}
return false;

View file

@ -11,19 +11,21 @@ public class AddPointCommand extends MeasurementModeCommand {
private boolean center;
public AddPointCommand(MeasurementToolLayer measurementLayer, boolean center) {
super(measurementLayer);
init(measurementLayer, null, center);
}
public AddPointCommand(MeasurementToolLayer measurementLayer, LatLon latLon) {
super(measurementLayer);
init(measurementLayer, latLon, false);
}
private void init(MeasurementToolLayer measurementLayer, LatLon latLon, boolean center) {
this.measurementLayer = measurementLayer;
if (latLon != null) {
point = new WptPt();
point.lat = latLon.getLatitude();
point.lon = latLon.getLongitude();
point.setProfileType(measurementLayer.getEditingCtx().getAppMode().getStringKey());
}
this.center = center;
position = measurementLayer.getEditingCtx().getPointsCount();
@ -32,27 +34,27 @@ public class AddPointCommand extends MeasurementModeCommand {
@Override
public boolean execute() {
if (point != null) {
measurementLayer.getEditingCtx().addPoint(point);
getEditingCtx().addPoint(point);
measurementLayer.moveMapToPoint(position);
} else if (center) {
point = measurementLayer.addCenterPoint();
} else {
point = measurementLayer.addPoint();
}
measurementLayer.refreshMap();
refreshMap();
return point != null;
}
@Override
public void undo() {
measurementLayer.getEditingCtx().removePoint(position, true);
measurementLayer.refreshMap();
getEditingCtx().removePoint(position, true);
refreshMap();
}
@Override
public void redo() {
measurementLayer.getEditingCtx().addPoint(position, point);
measurementLayer.refreshMap();
getEditingCtx().addPoint(position, point);
refreshMap();
measurementLayer.moveMapToPoint(position);
}

View file

@ -0,0 +1,75 @@
package net.osmand.plus.measurementtool.command;
import androidx.annotation.NonNull;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
import java.util.ArrayList;
import java.util.List;
public class ApplyGpxApproximationCommand extends MeasurementModeCommand {
private ApplicationMode mode;
private GpxRouteApproximation approximation;
private List<WptPt> points;
private boolean needUpdateCache;
public ApplyGpxApproximationCommand(MeasurementToolLayer measurementLayer, GpxRouteApproximation approximation, ApplicationMode mode) {
super(measurementLayer);
this.approximation = approximation;
this.mode = mode;
}
@Override
MeasurementCommandType getType() {
return MeasurementCommandType.APPROXIMATE_POINTS;
}
@Override
public boolean execute() {
List<WptPt> pts = getEditingCtx().getPoints();
needUpdateCache = getEditingCtx().isNeedUpdateCacheForSnap();
points = new ArrayList<>(pts);
applyApproximation();
refreshMap();
return true;
}
@Override
public boolean update(@NonNull Command command) {
if (command instanceof ApplyGpxApproximationCommand) {
ApplyGpxApproximationCommand approxCommand = (ApplyGpxApproximationCommand) command;
approximation = approxCommand.approximation;
applyApproximation();
refreshMap();
return true;
}
return false;
}
@Override
public void undo() {
getEditingCtx().resetAppMode();
getEditingCtx().clearSegments();
getEditingCtx().addPoints(points);
if (needUpdateCache) {
getEditingCtx().setNeedUpdateCacheForSnap(true);
}
refreshMap();
}
@Override
public void redo() {
applyApproximation();
refreshMap();
}
public void applyApproximation() {
getEditingCtx().setAppMode(mode);
getEditingCtx().clearSegments();
getEditingCtx().setPoints(approximation);
}
}

View file

@ -0,0 +1,80 @@
package net.osmand.plus.measurementtool.command;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import net.osmand.plus.settings.backend.ApplicationMode;
import java.util.LinkedList;
import java.util.List;
import static net.osmand.plus.measurementtool.MeasurementEditingContext.*;
public class ChangeRouteModeCommand extends MeasurementModeCommand {
private List<WptPt> points;
int pointIdx;
ApplicationMode oldMode;
ApplicationMode newMode;
CalculationMode oldCalculationMode;
CalculationMode newCalculationMode;
public ChangeRouteModeCommand(MeasurementToolLayer measurementLayer, ApplicationMode newMode,
CalculationMode newCalculationMode) {
super(measurementLayer);
this.newMode = newMode;
this.newCalculationMode = newCalculationMode;
MeasurementEditingContext editingCtx = getEditingCtx();
oldMode = editingCtx.getAppMode();
oldCalculationMode = editingCtx.getCalculationMode();
}
@Override
public boolean execute() {
MeasurementEditingContext editingCtx = getEditingCtx();
points = new LinkedList<>(editingCtx.getPoints());
pointIdx = points.size() - 1;
executeCommand();
return true;
}
@Override
public void undo() {
MeasurementEditingContext editingCtx = getEditingCtx();
editingCtx.getPoints().clear();
editingCtx.addPoints(points);
editingCtx.setAppMode(oldMode);
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
editingCtx.clearSnappedToRoadPoints();
}
editingCtx.setCalculationMode(oldCalculationMode);
editingCtx.setNeedUpdateCacheForSnap(true);
}
@Override
public void redo() {
executeCommand();
}
@Override
MeasurementCommandType getType() {
return MeasurementCommandType.CHANGE_ROUTE_MODE;
}
private void executeCommand() {
MeasurementEditingContext editingCtx = getEditingCtx();
if (pointIdx > 0 && newCalculationMode != CalculationMode.WHOLE_TRACK) {
if (newMode != null) {
points.get(pointIdx).setProfileType(newMode.getStringKey());
} else {
points.get(pointIdx).removeProfileType();
}
}
editingCtx.setCalculationMode(newCalculationMode);
editingCtx.setAppMode(newMode);
if (newCalculationMode == CalculationMode.WHOLE_TRACK) {
editingCtx.clearSnappedToRoadPoints();
}
editingCtx.setNeedUpdateCacheForSnap(true);
}
}

View file

@ -3,6 +3,7 @@ package net.osmand.plus.measurementtool.command;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@ -12,33 +13,33 @@ public class ClearPointsCommand extends MeasurementModeCommand {
private boolean needUpdateCache;
public ClearPointsCommand(MeasurementToolLayer measurementLayer) {
this.measurementLayer = measurementLayer;
super(measurementLayer);
}
@Override
public boolean execute() {
List<WptPt> pts = measurementLayer.getEditingCtx().getPoints();
needUpdateCache = measurementLayer.getEditingCtx().isNeedUpdateCacheForSnap();
points = new LinkedList<>(pts);
List<WptPt> pts = getEditingCtx().getPoints();
needUpdateCache = getEditingCtx().isNeedUpdateCacheForSnap();
points = new ArrayList<>(pts);
pts.clear();
measurementLayer.getEditingCtx().clearSegments();
measurementLayer.refreshMap();
getEditingCtx().clearSegments();
refreshMap();
return true;
}
@Override
public void undo() {
measurementLayer.getEditingCtx().addPoints(points);
getEditingCtx().addPoints(points);
if (needUpdateCache) {
measurementLayer.getEditingCtx().setNeedUpdateCacheForSnap(true);
getEditingCtx().setNeedUpdateCacheForSnap(true);
}
measurementLayer.refreshMap();
refreshMap();
}
@Override
public void redo() {
measurementLayer.getEditingCtx().clearSegments();
measurementLayer.refreshMap();
getEditingCtx().clearSegments();
refreshMap();
}
@Override

View file

@ -1,9 +1,13 @@
package net.osmand.plus.measurementtool.command;
import androidx.annotation.NonNull;
interface Command {
boolean execute();
boolean update(@NonNull Command command);
void undo();
void redo();

View file

@ -30,6 +30,11 @@ public class MeasurementCommandManager {
return false;
}
public boolean update(MeasurementModeCommand command) {
MeasurementModeCommand prevCommand = undoCommands.peek();
return prevCommand != null && prevCommand.update(command);
}
@Nullable
public MeasurementCommandType undo() {
if (canUndo()) {
@ -52,7 +57,7 @@ public class MeasurementCommandManager {
return null;
}
public void resetMeasurementLayer(MeasurementToolLayer layer) {
public void setMeasurementLayer(MeasurementToolLayer layer) {
for (MeasurementModeCommand command : undoCommands) {
command.setMeasurementLayer(layer);
}

View file

@ -1,23 +1,45 @@
package net.osmand.plus.measurementtool.command;
import androidx.annotation.NonNull;
import net.osmand.plus.measurementtool.MeasurementEditingContext;
import net.osmand.plus.measurementtool.MeasurementToolLayer;
public abstract class MeasurementModeCommand implements Command {
MeasurementToolLayer measurementLayer;
public MeasurementModeCommand(MeasurementToolLayer measurementLayer) {
this.measurementLayer = measurementLayer;
}
void setMeasurementLayer(MeasurementToolLayer layer) {
this.measurementLayer = layer;
}
@Override
public boolean update(@NonNull Command command) {
return false;
}
abstract MeasurementCommandType getType();
MeasurementEditingContext getEditingCtx() {
return measurementLayer.getEditingCtx();
}
void refreshMap() {
measurementLayer.refreshMap();
}
public enum MeasurementCommandType {
ADD_POINT,
CLEAR_POINTS,
MOVE_POINT,
REMOVE_POINT,
REORDER_POINT,
SNAP_TO_ROAD
SNAP_TO_ROAD,
CHANGE_ROUTE_MODE,
APPROXIMATE_POINTS
}
}

View file

@ -10,7 +10,7 @@ public class MovePointCommand extends MeasurementModeCommand {
private final int position;
public MovePointCommand(MeasurementToolLayer measurementLayer, WptPt oldPoint, WptPt newPoint, int position) {
this.measurementLayer = measurementLayer;
super(measurementLayer);
this.oldPoint = oldPoint;
this.newPoint = newPoint;
this.position = position;
@ -23,16 +23,16 @@ public class MovePointCommand extends MeasurementModeCommand {
@Override
public void undo() {
measurementLayer.getEditingCtx().removePoint(position, false);
measurementLayer.getEditingCtx().addPoint(position, oldPoint);
measurementLayer.refreshMap();
getEditingCtx().removePoint(position, false);
getEditingCtx().addPoint(position, oldPoint);
refreshMap();
}
@Override
public void redo() {
measurementLayer.getEditingCtx().removePoint(position, false);
measurementLayer.getEditingCtx().addPoint(position, newPoint);
measurementLayer.refreshMap();
getEditingCtx().removePoint(position, false);
getEditingCtx().addPoint(position, newPoint);
refreshMap();
}
@Override

View file

@ -9,28 +9,28 @@ public class RemovePointCommand extends MeasurementModeCommand {
private WptPt point;
public RemovePointCommand(MeasurementToolLayer measurementLayer, int position) {
this.measurementLayer = measurementLayer;
super(measurementLayer);
this.position = position;
}
@Override
public boolean execute() {
point = measurementLayer.getEditingCtx().removePoint(position, true);
measurementLayer.refreshMap();
point = getEditingCtx().removePoint(position, true);
refreshMap();
return true;
}
@Override
public void undo() {
measurementLayer.getEditingCtx().addPoint(position, point);
measurementLayer.refreshMap();
getEditingCtx().addPoint(position, point);
refreshMap();
measurementLayer.moveMapToPoint(position);
}
@Override
public void redo() {
measurementLayer.getEditingCtx().removePoint(position, true);
measurementLayer.refreshMap();
getEditingCtx().removePoint(position, true);
refreshMap();
}
@Override

View file

@ -11,15 +11,15 @@ public class ReorderPointCommand extends MeasurementModeCommand {
private final int to;
public ReorderPointCommand(MeasurementToolLayer measurementLayer, int from, int to) {
this.measurementLayer = measurementLayer;
super(measurementLayer);
this.from = from;
this.to = to;
}
@Override
public boolean execute() {
measurementLayer.getEditingCtx().setNeedUpdateCacheForSnap(true);
measurementLayer.refreshMap();
getEditingCtx().setNeedUpdateCacheForSnap(true);
refreshMap();
return true;
}
@ -34,10 +34,10 @@ public class ReorderPointCommand extends MeasurementModeCommand {
}
private void reorder(int addTo, int removeFrom) {
List<WptPt> points = measurementLayer.getEditingCtx().getPoints();
List<WptPt> points = getEditingCtx().getPoints();
points.add(addTo, points.remove(removeFrom));
measurementLayer.getEditingCtx().setNeedUpdateCacheForSnap(true);
measurementLayer.refreshMap();
getEditingCtx().setNeedUpdateCacheForSnap(true);
refreshMap();
}
@Override

View file

@ -27,6 +27,7 @@ import net.osmand.FileUtils;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.WptPt;
import net.osmand.IndexConstants;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
@ -39,6 +40,8 @@ import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -49,6 +52,7 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
public static final String TAG = "OnSaveCurrentTrackBottomSheetFragment";
public static final String SAVED_TRACKS_KEY = "saved_track_filename";
private static final Log LOG = PlatformUtil.getLog(OnSaveCurrentTrackFragment.class);
private boolean openTrack = false;
private File file;
@ -216,10 +220,17 @@ public class OnSaveCurrentTrackFragment extends BottomSheetDialogFragment {
}
public static void showInstance(FragmentManager fragmentManager, List<String> filenames) {
if (fragmentManager.isStateSaved()) {
return;
}
OnSaveCurrentTrackFragment f = new OnSaveCurrentTrackFragment();
Bundle b = new Bundle();
b.putStringArrayList(SAVED_TRACKS_KEY, new ArrayList<>(filenames));
f.setArguments(b);
f.show(fragmentManager, TAG);
try {
f.show(fragmentManager, TAG);
} catch (IllegalStateException ex) {
LOG.error("Can not perform this action after onSaveInstanceState");
}
}
}

View file

@ -43,7 +43,6 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.view.ActionMode;
import androidx.appcompat.widget.SearchView;
import androidx.core.content.ContextCompat;
import androidx.core.view.MenuItemCompat;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
@ -430,11 +429,11 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.clear();
MenuItem mi = createMenuItem(menu, SEARCH_ID, R.string.search_poi_filter, R.drawable.ic_action_search_dark, MenuItemCompat.SHOW_AS_ACTION_ALWAYS
| MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
MenuItem mi = createMenuItem(menu, SEARCH_ID, R.string.search_poi_filter, R.drawable.ic_action_search_dark, MenuItem.SHOW_AS_ACTION_ALWAYS
| MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
SearchView searchView = new SearchView(getActivity());
FavoritesActivity.updateSearchView(getActivity(), searchView);
MenuItemCompat.setActionView(mi, searchView);
mi.setActionView(searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
@ -449,7 +448,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
return true;
}
});
MenuItemCompat.setOnActionExpandListener(mi, new MenuItemCompat.OnActionExpandListener() {
mi.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
return true;
@ -518,7 +517,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
final MenuItem item;
ContextMenuItem contextMenuItem = optionsMenuAdapter.getItem(j);
item = menu.add(0, contextMenuItem.getTitleId(), j + 1, contextMenuItem.getTitle());
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
if (AndroidUiHelper.isOrientationPortrait(getActivity())) {
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
@ -617,8 +616,8 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
updateSelectionMode(mode);
MenuItem it = menu.add(R.string.shared_string_show_on_map);
it.setIcon(R.drawable.ic_action_done);
MenuItemCompat.setShowAsAction(it, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM
| MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
it.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
updateCurrentTrack();
return true;
}
@ -686,8 +685,8 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
if (actionIconId != 0) {
it.setIcon(actionIconId);
}
MenuItemCompat.setShowAsAction(it, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM
| MenuItemCompat.SHOW_AS_ACTION_WITH_TEXT);
it.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM
| MenuItem.SHOW_AS_ACTION_WITH_TEXT);
return true;
}

Some files were not shown because too many files have changed in this diff Show more