Merge remote-tracking branch 'origin/master' into fix_using_google_maps_links
This commit is contained in:
commit
53b3addcb5
135 changed files with 7347 additions and 2836 deletions
|
@ -1727,13 +1727,12 @@ public class BinaryMapIndexReader {
|
|||
double half16t = MapUtils.getDistance(lat, MapUtils.getLongitudeFromTile(16, ((int) dx) + 0.5),
|
||||
lat, MapUtils.getLongitudeFromTile(16, (int) dx));
|
||||
double cf31 = ((double) radiusMeters / (half16t * 2)) * (1 << 15);
|
||||
int y31 = MapUtils.get31TileNumberY(lat);
|
||||
int x31 = MapUtils.get31TileNumberX(lon);
|
||||
left = (int) (x31 - cf31);
|
||||
right = (int) (x31 + cf31);
|
||||
top = (int) (y31 - cf31);
|
||||
bottom = (int) (y31 + cf31);
|
||||
|
||||
y = MapUtils.get31TileNumberY(lat);
|
||||
x = MapUtils.get31TileNumberX(lon);
|
||||
left = (int) (x - cf31);
|
||||
right = (int) (x + cf31);
|
||||
top = (int) (y - cf31);
|
||||
bottom = (int) (y + cf31);
|
||||
}
|
||||
|
||||
public boolean publish(T obj) {
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
package net.osmand.binary;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.binary.BinaryMapAddressReaderAdapter.AddressRegion;
|
||||
import net.osmand.binary.BinaryMapAddressReaderAdapter.CitiesBlock;
|
||||
|
@ -29,42 +23,50 @@ import net.osmand.binary.OsmandIndex.TransportPart;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
|
||||
public class CachedOsmandIndexes {
|
||||
|
||||
|
||||
private OsmAndStoredIndex storedIndex;
|
||||
private OsmAndStoredIndex.Builder storedIndexBuilder;
|
||||
private Log log = PlatformUtil.getLog(CachedOsmandIndexes.class);
|
||||
private boolean hasChanged = true;
|
||||
|
||||
|
||||
public static final int VERSION = 2;
|
||||
|
||||
public void addToCache(BinaryMapIndexReader reader, File f) {
|
||||
hasChanged = true;
|
||||
if(storedIndexBuilder == null) {
|
||||
if (storedIndexBuilder == null) {
|
||||
storedIndexBuilder = OsmandIndex.OsmAndStoredIndex.newBuilder();
|
||||
storedIndexBuilder.setVersion(VERSION);
|
||||
storedIndexBuilder.setDateCreated(System.currentTimeMillis());
|
||||
if(storedIndex != null) {
|
||||
for(FileIndex ex : storedIndex.getFileIndexList()) {
|
||||
storedIndexBuilder.addFileIndex(ex);
|
||||
if (storedIndex != null) {
|
||||
for (FileIndex ex : storedIndex.getFileIndexList()) {
|
||||
if (!ex.getFileName().equals(f.getName())) {
|
||||
storedIndexBuilder.addFileIndex(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FileIndex.Builder fileIndex = OsmandIndex.FileIndex.newBuilder();
|
||||
long d = reader.getDateCreated();
|
||||
fileIndex.setDateModified(d== 0?f.lastModified() : d);
|
||||
fileIndex.setDateModified(d == 0 ? f.lastModified() : d);
|
||||
fileIndex.setSize(f.length());
|
||||
fileIndex.setVersion(reader.getVersion());
|
||||
fileIndex.setFileName(f.getName());
|
||||
for(MapIndex index : reader.getMapIndexes()) {
|
||||
for (MapIndex index : reader.getMapIndexes()) {
|
||||
MapPart.Builder map = OsmandIndex.MapPart.newBuilder();
|
||||
map.setSize(index.getLength());
|
||||
map.setOffset(index.getFilePointer());
|
||||
if(index.getName() != null) {
|
||||
if (index.getName() != null) {
|
||||
map.setName(index.getName());
|
||||
}
|
||||
for(MapRoot mr : index.getRoots() ) {
|
||||
for (MapRoot mr : index.getRoots()) {
|
||||
MapLevel.Builder lev = OsmandIndex.MapLevel.newBuilder();
|
||||
lev.setSize(mr.length);
|
||||
lev.setOffset(mr.filePointer);
|
||||
|
@ -78,36 +80,36 @@ public class CachedOsmandIndexes {
|
|||
}
|
||||
fileIndex.addMapIndex(map);
|
||||
}
|
||||
|
||||
for(AddressRegion index : reader.getAddressIndexes()) {
|
||||
|
||||
for (AddressRegion index : reader.getAddressIndexes()) {
|
||||
AddressPart.Builder addr = OsmandIndex.AddressPart.newBuilder();
|
||||
addr.setSize(index.getLength());
|
||||
addr.setOffset(index.getFilePointer());
|
||||
if(index.getName() != null) {
|
||||
if (index.getName() != null) {
|
||||
addr.setName(index.getName());
|
||||
}
|
||||
if(index.getEnName() != null) {
|
||||
if (index.getEnName() != null) {
|
||||
addr.setNameEn(index.getEnName());
|
||||
}
|
||||
addr.setIndexNameOffset(index.getIndexNameOffset());
|
||||
for(CitiesBlock mr : index.getCities() ) {
|
||||
for (CitiesBlock mr : index.getCities()) {
|
||||
CityBlock.Builder cblock = OsmandIndex.CityBlock.newBuilder();
|
||||
cblock.setSize(mr.length);
|
||||
cblock.setOffset(mr.filePointer);
|
||||
cblock.setType(mr.type);
|
||||
addr.addCities(cblock);
|
||||
}
|
||||
for(String s : index.getAttributeTagsTable()) {
|
||||
for (String s : index.getAttributeTagsTable()) {
|
||||
addr.addAdditionalTags(s);
|
||||
}
|
||||
fileIndex.addAddressIndex(addr);
|
||||
}
|
||||
|
||||
for(PoiRegion index : reader.getPoiIndexes()) {
|
||||
|
||||
for (PoiRegion index : reader.getPoiIndexes()) {
|
||||
PoiPart.Builder poi = OsmandIndex.PoiPart.newBuilder();
|
||||
poi.setSize(index.getLength());
|
||||
poi.setOffset(index.getFilePointer());
|
||||
if(index.getName() != null) {
|
||||
if (index.getName() != null) {
|
||||
poi.setName(index.getName());
|
||||
}
|
||||
poi.setLeft(index.left31);
|
||||
|
@ -116,12 +118,12 @@ public class CachedOsmandIndexes {
|
|||
poi.setBottom(index.bottom31);
|
||||
fileIndex.addPoiIndex(poi.build());
|
||||
}
|
||||
|
||||
for(TransportIndex index : reader.getTransportIndexes()) {
|
||||
|
||||
for (TransportIndex index : reader.getTransportIndexes()) {
|
||||
TransportPart.Builder transport = OsmandIndex.TransportPart.newBuilder();
|
||||
transport.setSize(index.getLength());
|
||||
transport.setOffset(index.getFilePointer());
|
||||
if(index.getName() != null) {
|
||||
if (index.getName() != null) {
|
||||
transport.setName(index.getName());
|
||||
}
|
||||
transport.setLeft(index.getLeft());
|
||||
|
@ -130,33 +132,33 @@ public class CachedOsmandIndexes {
|
|||
transport.setBottom(index.getBottom());
|
||||
transport.setStopsTableLength(index.stopsFileLength);
|
||||
transport.setStopsTableOffset(index.stopsFileOffset);
|
||||
// if(index.incompleteRoutesLength > 0) {
|
||||
// if(index.incompleteRoutesLength > 0) {
|
||||
transport.setIncompleteRoutesLength(index.incompleteRoutesLength);
|
||||
transport.setIncompleteRoutesOffset(index.incompleteRoutesOffset);
|
||||
// }
|
||||
// }
|
||||
transport.setStringTableLength(index.stringTable.length);
|
||||
transport.setStringTableOffset(index.stringTable.fileOffset);
|
||||
fileIndex.addTransportIndex(transport);
|
||||
}
|
||||
|
||||
for(RouteRegion index : reader.getRoutingIndexes()) {
|
||||
|
||||
for (RouteRegion index : reader.getRoutingIndexes()) {
|
||||
RoutingPart.Builder routing = OsmandIndex.RoutingPart.newBuilder();
|
||||
routing.setSize(index.getLength());
|
||||
routing.setOffset(index.getFilePointer());
|
||||
if(index.getName() != null) {
|
||||
if (index.getName() != null) {
|
||||
routing.setName(index.getName());
|
||||
}
|
||||
for(RouteSubregion sub : index.getSubregions()) {
|
||||
for (RouteSubregion sub : index.getSubregions()) {
|
||||
addRouteSubregion(routing, sub, false);
|
||||
}
|
||||
for(RouteSubregion sub : index.getBaseSubregions()) {
|
||||
for (RouteSubregion sub : index.getBaseSubregions()) {
|
||||
addRouteSubregion(routing, sub, true);
|
||||
}
|
||||
fileIndex.addRoutingIndex(routing);
|
||||
}
|
||||
|
||||
|
||||
storedIndexBuilder.addFileIndex(fileIndex);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void addRouteSubregion(RoutingPart.Builder routing, RouteSubregion sub, boolean base) {
|
||||
|
@ -171,11 +173,11 @@ public class CachedOsmandIndexes {
|
|||
rpart.setShifToData(sub.shiftToData);
|
||||
routing.addSubregions(rpart);
|
||||
}
|
||||
|
||||
public BinaryMapIndexReader getReader(File f) throws IOException {
|
||||
|
||||
public BinaryMapIndexReader getReader(File f, boolean useStoredIndex) throws IOException {
|
||||
RandomAccessFile mf = new RandomAccessFile(f.getPath(), "r");
|
||||
FileIndex found = null;
|
||||
if (storedIndex != null) {
|
||||
if (storedIndex != null && useStoredIndex) {
|
||||
for (int i = 0; i < storedIndex.getFileIndexCount(); i++) {
|
||||
FileIndex fi = storedIndex.getFileIndex(i);
|
||||
if (f.length() == fi.getSize() && f.getName().equals(fi.getFileName())) {
|
||||
|
@ -191,26 +193,26 @@ public class CachedOsmandIndexes {
|
|||
reader = new BinaryMapIndexReader(mf, f);
|
||||
addToCache(reader, f);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Initializing db " + f.getAbsolutePath() + " " + (System.currentTimeMillis() - val ) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
log.debug("Initializing db " + f.getAbsolutePath() + " " + (System.currentTimeMillis() - val) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
}
|
||||
} else {
|
||||
reader = initFileIndex(found, mf, f);
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
|
||||
|
||||
private BinaryMapIndexReader initFileIndex(FileIndex found, RandomAccessFile mf, File f) throws IOException {
|
||||
BinaryMapIndexReader reader = new BinaryMapIndexReader(mf, f, false);
|
||||
reader.version = found.getVersion();
|
||||
reader.dateCreated = found.getDateModified();
|
||||
|
||||
for(MapPart index : found.getMapIndexList()) {
|
||||
|
||||
for (MapPart index : found.getMapIndexList()) {
|
||||
MapIndex mi = new MapIndex();
|
||||
mi.length = (int) index.getSize();
|
||||
mi.filePointer = (int) index.getOffset();
|
||||
mi.name = index.getName();
|
||||
|
||||
for(MapLevel mr : index.getLevelsList()) {
|
||||
|
||||
for (MapLevel mr : index.getLevelsList()) {
|
||||
MapRoot root = new MapRoot();
|
||||
root.length = (int) mr.getSize();
|
||||
root.filePointer = (int) mr.getOffset();
|
||||
|
@ -226,15 +228,15 @@ public class CachedOsmandIndexes {
|
|||
reader.indexes.add(mi);
|
||||
reader.basemap = reader.basemap || mi.isBaseMap();
|
||||
}
|
||||
|
||||
for(AddressPart index : found.getAddressIndexList()) {
|
||||
|
||||
for (AddressPart index : found.getAddressIndexList()) {
|
||||
AddressRegion mi = new AddressRegion();
|
||||
mi.length = (int) index.getSize();
|
||||
mi.filePointer = (int) index.getOffset();
|
||||
mi.name = index.getName();
|
||||
mi.enName = index.getNameEn();
|
||||
mi.indexNameOffset = index.getIndexNameOffset();
|
||||
for(CityBlock mr : index.getCitiesList() ) {
|
||||
for (CityBlock mr : index.getCitiesList()) {
|
||||
CitiesBlock cblock = new CitiesBlock();
|
||||
cblock.length = (int) mr.getSize();
|
||||
cblock.filePointer = (int) mr.getOffset();
|
||||
|
@ -245,8 +247,8 @@ public class CachedOsmandIndexes {
|
|||
reader.addressIndexes.add(mi);
|
||||
reader.indexes.add(mi);
|
||||
}
|
||||
|
||||
for(PoiPart index : found.getPoiIndexList()) {
|
||||
|
||||
for (PoiPart index : found.getPoiIndexList()) {
|
||||
PoiRegion mi = new PoiRegion();
|
||||
mi.length = (int) index.getSize();
|
||||
mi.filePointer = (int) index.getOffset();
|
||||
|
@ -258,14 +260,14 @@ public class CachedOsmandIndexes {
|
|||
reader.poiIndexes.add(mi);
|
||||
reader.indexes.add(mi);
|
||||
}
|
||||
|
||||
for(TransportPart index : found.getTransportIndexList()) {
|
||||
|
||||
for (TransportPart index : found.getTransportIndexList()) {
|
||||
TransportIndex mi = new TransportIndex();
|
||||
mi.length = (int) index.getSize();
|
||||
mi.filePointer = (int) index.getOffset();
|
||||
mi.name = index.getName();
|
||||
mi.left = index.getLeft();
|
||||
mi.right =index.getRight();
|
||||
mi.right = index.getRight();
|
||||
mi.top = index.getTop();
|
||||
mi.bottom = index.getBottom();
|
||||
mi.stopsFileLength = index.getStopsTableLength();
|
||||
|
@ -278,14 +280,14 @@ public class CachedOsmandIndexes {
|
|||
reader.transportIndexes.add(mi);
|
||||
reader.indexes.add(mi);
|
||||
}
|
||||
|
||||
for(RoutingPart index : found.getRoutingIndexList()) {
|
||||
|
||||
for (RoutingPart index : found.getRoutingIndexList()) {
|
||||
RouteRegion mi = new RouteRegion();
|
||||
mi.length = (int) index.getSize();
|
||||
mi.filePointer = (int) index.getOffset();
|
||||
mi.name = index.getName();
|
||||
|
||||
for(RoutingSubregion mr : index.getSubregionsList()) {
|
||||
|
||||
for (RoutingSubregion mr : index.getSubregionsList()) {
|
||||
RouteSubregion sub = new RouteSubregion(mi);
|
||||
sub.length = (int) mr.getSize();
|
||||
sub.filePointer = (int) mr.getOffset();
|
||||
|
@ -294,7 +296,7 @@ public class CachedOsmandIndexes {
|
|||
sub.top = mr.getTop();
|
||||
sub.bottom = mr.getBottom();
|
||||
sub.shiftToData = mr.getShifToData();
|
||||
if(mr.getBasemap()) {
|
||||
if (mr.getBasemap()) {
|
||||
mi.basesubregions.add(sub);
|
||||
} else {
|
||||
mi.subregions.add(sub);
|
||||
|
@ -303,7 +305,7 @@ public class CachedOsmandIndexes {
|
|||
reader.routingIndexes.add(mi);
|
||||
reader.indexes.add(mi);
|
||||
}
|
||||
|
||||
|
||||
return reader;
|
||||
}
|
||||
|
||||
|
@ -313,7 +315,7 @@ public class CachedOsmandIndexes {
|
|||
try {
|
||||
storedIndex = OsmandIndex.OsmAndStoredIndex.newBuilder().mergeFrom(is).build();
|
||||
hasChanged = false;
|
||||
if(storedIndex.getVersion() != version){
|
||||
if (storedIndex.getVersion() != version) {
|
||||
storedIndex = null;
|
||||
}
|
||||
} finally {
|
||||
|
@ -321,7 +323,7 @@ public class CachedOsmandIndexes {
|
|||
}
|
||||
log.info("Initialize cache " + (System.currentTimeMillis() - time));
|
||||
}
|
||||
|
||||
|
||||
public void writeToFile(File f) throws IOException {
|
||||
if (hasChanged) {
|
||||
FileOutputStream outputStream = new FileOutputStream(f);
|
||||
|
|
|
@ -764,6 +764,7 @@ public class CommonWords {
|
|||
addFrequentlyUsed("martiri");
|
||||
addFrequentlyUsed("verdi");
|
||||
addFrequentlyUsed("augusta");
|
||||
addFrequentlyUsed("neuburger");
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ public class Amenity extends MapObject {
|
|||
public static final String IS_AGGR_PART = "is_aggr_part";
|
||||
public static final String CONTENT_JSON = "content_json";
|
||||
public static final String ROUTE_ID = "route_id";
|
||||
public static final String ROUTE_SOURCE = "route_source";
|
||||
|
||||
|
||||
private String subType;
|
||||
|
|
|
@ -16,11 +16,13 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
|
||||
|
|
|
@ -650,7 +650,7 @@ public class SearchCoreFactory {
|
|||
if (p.hasObjectType(ObjectType.POI_TYPE)) {
|
||||
return -1;
|
||||
}
|
||||
if (p.getUnknownWordToSearch().length() >= FIRST_WORD_MIN_LENGTH || p.getRadiusLevel() > 1) {
|
||||
if (p.getUnknownWordToSearch().length() >= FIRST_WORD_MIN_LENGTH || p.isFirstUnknownSearchWordComplete()) {
|
||||
return SEARCH_AMENITY_BY_NAME_API_PRIORITY_IF_3_CHAR;
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -78,6 +78,10 @@ public class Algorithms {
|
|||
return map == null || map.size() == 0;
|
||||
}
|
||||
|
||||
public static String emptyIfNull(String s) {
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(CharSequence s) {
|
||||
return s == null || s.length() == 0;
|
||||
}
|
||||
|
@ -86,6 +90,10 @@ public class Algorithms {
|
|||
return s == null || s.trim().length() == 0;
|
||||
}
|
||||
|
||||
public static int hash(Object... values) {
|
||||
return Arrays.hashCode(values);
|
||||
}
|
||||
|
||||
public static boolean stringsEqual(String s1, String s2) {
|
||||
if (s1 == null && s2 == null) {
|
||||
return true;
|
||||
|
|
|
@ -63,7 +63,8 @@
|
|||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:resource="@dimen/app_minimumsize_h" android:value="" />
|
||||
<meta-data android:name="com.sec.minimode.icon.portrait.normal" android:resource="@mipmap/icon" android:value="" />
|
||||
<meta-data android:name="com.sec.minimode.icon.landscape.normal" android:resource="@mipmap/icon" android:value="" />
|
||||
<activity android:name="net.osmand.plus.activities.HelpActivity" />
|
||||
<meta-data android:name="android.webkit.WebView.MetricsOptOut" android:value="true" />
|
||||
<activity android:name="net.osmand.plus.activities.HelpActivity" />
|
||||
<activity android:name="net.osmand.plus.activities.ExitActivity" />
|
||||
|
||||
<provider
|
||||
|
|
56
OsmAnd/res/layout/bottom_sheet_item_with_descr_64dp.xml
Normal file
56
OsmAnd/res/layout/bottom_sheet_item_with_descr_64dp.xml
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:minHeight="@dimen/setting_list_item_group_height"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
tools:src="@drawable/list_destination"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
app:typeface="@string/font_roboto_regular"
|
||||
tools:text="Some title" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
app:typeface="@string/font_roboto_regular"
|
||||
tools:text="Some description" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="63dp"
|
||||
android:layout_height="@dimen/bottom_sheet_large_list_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/list_content_padding"
|
||||
|
@ -71,8 +71,8 @@
|
|||
android:id="@+id/divider_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="64dp"
|
||||
android:layout_marginLeft="64dp"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_divider_margin_start"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_divider_margin_start"
|
||||
android:background="?attr/divider_color" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_large_list_item_height"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/bottom_sheet_large_list_item_height"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_item_part"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingRight="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_icon_margin"
|
||||
tools:src="@drawable/ic_action_coordinates_latitude"
|
||||
tools:tint="?attr/default_icon_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@style/TextAppearance.ListItemTitle"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="Item Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
tools:text="Item additional desription" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatRadioButton
|
||||
android:id="@+id/compound_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:saveEnabled="false"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="36dp"
|
||||
android:background="?attr/divider_color_basic"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/eng_button"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center_vertical"
|
||||
app:srcCompat="@drawable/ic_action_settings"
|
||||
android:tint="?attr/default_icon_color" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_divider_margin_start"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_divider_margin_start"
|
||||
android:background="?attr/divider_color" />
|
||||
|
||||
</LinearLayout>
|
|
@ -109,61 +109,6 @@
|
|||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginStart="@dimen/content_padding" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/split_color_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/split_interval_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.6"
|
||||
android:minHeight="@dimen/card_row_min_height"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingRight="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/split_interval_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
android:text="@string/gpx_split_interval"/>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/split_interval_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="10 km"
|
||||
android:paddingEnd="@dimen/content_padding_half"
|
||||
android:paddingStart="@dimen/content_padding_half" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/split_interval_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
osmand:srcCompat="@drawable/ic_action_arrow_drop_down"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/appearance_view"
|
||||
android:layout_width="match_parent"
|
||||
|
|
35
OsmAnd/res/layout/online_routing_engine_fragment.xml
Normal file
35
OsmAnd/res/layout/online_routing_engine_fragment.xml
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/list_background_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<include layout="@layout/preference_toolbar_with_action_button" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/segments_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<include
|
||||
layout="@layout/bottom_buttons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_ex_height" />
|
||||
|
||||
</LinearLayout>
|
186
OsmAnd/res/layout/online_routing_preference_segment.xml
Normal file
186
OsmAnd/res/layout/online_routing_preference_segment.xml
Normal file
|
@ -0,0 +1,186 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/bottom_sheet_list_item_height"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone"
|
||||
tools:text="Title" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone"
|
||||
tools:text="Subtitle" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/selection_menu"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
tools:itemCount="3"
|
||||
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/point_editor_icon_category_item"
|
||||
tools:orientation="horizontal"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Description"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/field_box_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:orientation="vertical"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone">
|
||||
|
||||
<net.osmand.plus.widgets.OsmandTextFieldBoxes
|
||||
android:id="@+id/field_box"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
osmand:errorColor="@color/color_invalid"
|
||||
osmand:helperTextColor="?android:textColorSecondary"
|
||||
tools:labelText="Hint"
|
||||
osmand:primaryColor="@color/active_color_primary_dark"
|
||||
osmand:secondaryColor="?android:textColorSecondary">
|
||||
|
||||
<studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
||||
android:id="@+id/edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine|textNoSuggestions"
|
||||
android:maxLines="4"
|
||||
android:saveEnabled="false"
|
||||
android:scrollHorizontally="false"
|
||||
tools:text="Text" />
|
||||
|
||||
</net.osmand.plus.widgets.OsmandTextFieldBoxes>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/helper_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Helper text"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/bottom_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/divider_color_basic"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include
|
||||
android:id="@+id/button"
|
||||
layout="@layout/bottom_sheet_dialog_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_marginTop="@dimen/content_padding_half"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/result_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/setting_list_item_group_height"
|
||||
android:orientation="horizontal"
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/result_icon"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:tint="?attr/default_icon_color"
|
||||
tools:src="@drawable/ic_action_gdirections_dark" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/result_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="OK" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
95
OsmAnd/res/layout/preference_toolbar_with_action_button.xml
Normal file
95
OsmAnd/res/layout/preference_toolbar_with_action_button.xml
Normal file
|
@ -0,0 +1,95 @@
|
|||
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="@dimen/toolbar_height"
|
||||
app:contentInsetLeft="0dp"
|
||||
app:contentInsetStart="0dp"
|
||||
app:contentInsetRight="0dp"
|
||||
app:contentInsetEnd="0dp"
|
||||
app:theme="@style/ThemeOverlay.AppCompat.ActionBar">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="@dimen/toolbar_height"
|
||||
android:background="?attr/card_and_list_background_basic"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/close_button"
|
||||
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||
android:layout_width="@dimen/toolbar_height"
|
||||
android:layout_height="@dimen/toolbar_height"
|
||||
android:contentDescription="@string/access_shared_string_navigate_up"
|
||||
app:srcCompat="@drawable/ic_arrow_back"
|
||||
android:tint="?attr/default_icon_color" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_half"
|
||||
android:paddingBottom="@dimen/content_padding_half"
|
||||
android:background="?attr/card_and_list_background_basic"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/toolbar_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/dialog_header_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:text="@string/routing_settings_2" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/toolbar_subtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:textColor="@null"
|
||||
tools:text="Some description" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/action_button"
|
||||
android:layout_gravity="center"
|
||||
android:layout_width="@dimen/acceptable_touch_radius"
|
||||
android:layout_height="@dimen/acceptable_touch_radius">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/action_button_icon"
|
||||
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:contentDescription="@string/access_shared_string_navigate_up"
|
||||
android:duplicateParentState="true"
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="fitCenter"
|
||||
tools:src="@drawable/ic_action_info_dark" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
|
@ -56,6 +56,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:maxLines="4"
|
||||
android:scrollbars="none"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular" />
|
||||
|
|
127
OsmAnd/res/layout/track_menu.xml
Normal file
127
OsmAnd/res/layout/track_menu.xml
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/color_transparent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/context_menu_top_shadow" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/route_menu_top_shadow_all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/list_background_color"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/content_padding"
|
||||
android:layout_height="2dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
|
||||
android:layout_marginBottom="@dimen/list_item_button_padding"
|
||||
android:background="?attr/bg_dash_line" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/context_menu_top_shadow_all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/context_menu_top_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/context_menu_padding_margin_default"
|
||||
android:paddingLeft="@dimen/context_menu_padding_margin_default"
|
||||
android:paddingEnd="@dimen/context_menu_padding_margin_default"
|
||||
android:paddingRight="@dimen/context_menu_padding_margin_default">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/context_menu_first_line_top_margin"
|
||||
android:layout_marginEnd="@dimen/context_menu_padding_margin_default"
|
||||
android:layout_marginRight="@dimen/context_menu_padding_margin_default"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.ContextMenuTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/search_address_building" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
style="@style/TextAppearance.ContextMenuSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
tools:text="@string/amenity_type_finance" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/context_menu_icon_view"
|
||||
android:layout_width="@dimen/map_widget_icon"
|
||||
android:layout_height="@dimen/map_widget_icon"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_default"
|
||||
android:tint="?attr/default_icon_color"
|
||||
osmand:srcCompat="@drawable/ic_action_polygom_dark" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/bottom_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/activity_background_basic"
|
||||
android:foreground="@drawable/bg_contextmenu_shadow"
|
||||
android:foregroundGravity="top|fill_horizontal">
|
||||
|
||||
<net.osmand.plus.LockableScrollView
|
||||
android:id="@+id/route_menu_bottom_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/route_menu_cards_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/context_menu_action_buttons_height" />
|
||||
|
||||
</net.osmand.plus.LockableScrollView>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
android:id="@+id/bottom_navigation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/context_menu_action_buttons_height"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/wikivoyage_card_bg_color"
|
||||
osmand:itemBackground="?attr/wikivoyage_card_bg_color"
|
||||
osmand:itemIconTint="@color/bottom_navigation_color_selector_light"
|
||||
osmand:itemTextColor="@color/bottom_navigation_color_selector_light"
|
||||
osmand:labelVisibilityMode="labeled"
|
||||
osmand:menu="@menu/track_menu_bottom_navigation" />
|
||||
|
||||
</FrameLayout>
|
6
OsmAnd/res/layout/track_segments_container.xml
Normal file
6
OsmAnd/res/layout/track_segments_container.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</LinearLayout>
|
21
OsmAnd/res/menu/track_menu_bottom_navigation.xml
Normal file
21
OsmAnd/res/menu/track_menu_bottom_navigation.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/action_overview"-->
|
||||
<!-- android:icon="@drawable/ic_action_trail_overview"-->
|
||||
<!-- android:title="@string/shared_string_overview" />-->
|
||||
|
||||
<item
|
||||
android:id="@+id/action_track"
|
||||
android:icon="@drawable/ic_action_polygom_dark"
|
||||
android:title="@string/shared_string_gpx_track" />
|
||||
<item
|
||||
android:id="@+id/action_points"
|
||||
android:icon="@drawable/ic_action_waypoint"
|
||||
android:title="@string/shared_string_gpx_points" />
|
||||
|
||||
<!-- <item-->
|
||||
<!-- android:id="@+id/action_options"-->
|
||||
<!-- android:icon="@drawable/ic_overflow_menu_white"-->
|
||||
<!-- android:title="@string/shared_string_options" />-->
|
||||
</menu>
|
|
@ -740,7 +740,7 @@
|
|||
<string name="layer_overlay">الخريطة العلوية…</string>
|
||||
<string name="shared_string_none">بدون</string>
|
||||
<string name="map_overlay">الخريطة العلوية</string>
|
||||
<string name="map_overlay_descr">اختيار خريطة التراكب</string>
|
||||
<string name="map_overlay_descr">اختيار خريطة علوية أو سفلية</string>
|
||||
<string name="poi_dialog_other_tags_message">يتم الاحتفاظ بكافة العلامات الأخرى</string>
|
||||
<string name="amenity_type_seamark">سيمارك</string>
|
||||
<string name="poi_dialog_comment_default">متغير POI</string>
|
||||
|
@ -2379,12 +2379,12 @@
|
|||
\n• يدعم نقاط وسيطة خلال مسارك
|
||||
\n• إعادة تلقائية للتوجيه كلما انحرفت عن الطريق
|
||||
\n• البحث عن الأماكن حسب العنوان، النوع (مثل: مطعم، فندق، محطة وقود، متحف)،أو حسب الإحداثيات الجغرافية</string>
|
||||
<string name="osmand_plus_extended_description_part3">عرض الخريطة
|
||||
\n• عرض موقعك والتوجيه
|
||||
\n• محاذاة اختيارية للصورة وفق البوصلة أو توجيه الحركة
|
||||
\n• حفظ أهم أماكنك المفضلة
|
||||
\n• عرض النقاط المهمة من حولك (POI)
|
||||
\n• عرض متخصص لبيانات خرائط على الإنترنت، الرؤية من الأقمار الصناعية (من بينج) وتراكب طبقات خرائط مختلفة كالسياحة ومسارات GPX للملاحة وطبقات إضافية مع شفافية قابلة للتعديل
|
||||
<string name="osmand_plus_extended_description_part3">عرض الخريطة
|
||||
\n• عرض موقعك والتوجيه
|
||||
\n• محاذاة اختيارية للصورة وفق البوصلة أو توجيه الحركة
|
||||
\n• حفظ أهم أماكنك المفضلة
|
||||
\n• عرض نقاط الاهتمام من حولك
|
||||
\n• عرض متخصص لبيانات خرائط على الإنترنت، الرؤية من الأقمار الصناعية (من بينج) وتراكب طبقات خرائط مختلفة كالسياحة ومسارات GPX للملاحة وطبقات إضافية مع شفافية قابلة للتعديل
|
||||
\n• عرض اختياري لأسماء الأماكن باللغة الإنكليزية، اللغة المحلية، أو عبر الإملاء الصوتي
|
||||
\n</string>
|
||||
<string name="osmand_plus_extended_description_part4">استخدام OSM وبيانات ويكيبيديا
|
||||
|
@ -4014,4 +4014,5 @@
|
|||
<string name="routing_attr_allow_streams_name">السماح بالتيارات والمصارف</string>
|
||||
<string name="routing_attr_allow_intermittent_description">السماح بالممرات المائية المتقطعة</string>
|
||||
<string name="routing_attr_allow_intermittent_name">السماح بالممرات المائية المتقطعة</string>
|
||||
<string name="voice_prompts_timetable">مطالبة صوتية</string>
|
||||
</resources>
|
|
@ -2888,4 +2888,9 @@
|
|||
<string name="poi_cuisine_cajun">Cajun</string>
|
||||
<string name="poi_cuisine_burrito">Burritos</string>
|
||||
<string name="poi_cuisine_waffle">Gofres</string>
|
||||
<string name="poi_motorcycle_clothes_no">Roba de motorista: no</string>
|
||||
<string name="poi_motorcycle_clothes_yes">Roba de motorista</string>
|
||||
<string name="poi_motorcycle_tyres_no">Pneumàtics: no</string>
|
||||
<string name="poi_motorcycle_tyres_yes">Pneumàtics</string>
|
||||
<string name="poi_motorcycle_parts_no">Recanvis: no</string>
|
||||
</resources>
|
|
@ -3925,4 +3925,12 @@
|
|||
\n
|
||||
\n</string>
|
||||
<string name="reverse_all_points">Revertir tots els punts</string>
|
||||
<string name="profile_by_default_description">Seleccioneu el perfil que s\'utilitzarà en iniciar l\'aplicació.</string>
|
||||
<string name="shared_string_last_used">Darrera utilització</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_description">Prioritza les rutes de senderisme</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_name">Prioritza les rutes de senderisme</string>
|
||||
<string name="routing_attr_allow_streams_description">Permet rierols i torrents</string>
|
||||
<string name="routing_attr_allow_streams_name">Permet rierols i torrents</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permet les vies navegables no permanents</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permet les vies navegables no permanents</string>
|
||||
</resources>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="switch_to_raster_map_to_see">Off-line vektorová mapa pro toto místo není dostupná. Stáhněte jí v \'Nastavení\' (\'Stáhnout mapy\'), nebo se přepněte na modul \'Online mapy\'.</string>
|
||||
<string name="switch_to_raster_map_to_see">Stáhněte si off-line vektorovou mapu pro tuto oblast v menu \'Nastavení\' (\'Stáhnout mapy\'), nebo se přepněte na modul \'Online mapy\'.</string>
|
||||
<string name="send_files_to_osm">Nahrát GPX soubory do OSM?</string>
|
||||
<string name="gpx_visibility_txt">Viditelnost</string>
|
||||
<string name="gpx_tags_txt">Tagy</string>
|
||||
|
@ -24,17 +24,17 @@
|
|||
<string name="north">sever</string>
|
||||
<string name="north_north_east">severoseverovýchod</string>
|
||||
<string name="north_east">severovýchod</string>
|
||||
<string name="east_north_east">východovýchodosever</string>
|
||||
<string name="east_north_east">východoseverovýchod</string>
|
||||
<string name="east">východ</string>
|
||||
<string name="east_south_east">východovýchodojih</string>
|
||||
<string name="east_south_east">východojihovýchod</string>
|
||||
<string name="south_east">jihovýchod</string>
|
||||
<string name="south_south_east">jihojihovýchod</string>
|
||||
<string name="south">jih</string>
|
||||
<string name="south_south_west">jihojihozápad</string>
|
||||
<string name="south_west">jihozápad</string>
|
||||
<string name="west_south_west">západozápadojih</string>
|
||||
<string name="west_south_west">západojihozápad</string>
|
||||
<string name="west">západ</string>
|
||||
<string name="west_north_west">západozápadosever</string>
|
||||
<string name="west_north_west">západoseverozápad</string>
|
||||
<string name="north_west">severozápad</string>
|
||||
<string name="north_north_west">severoseverozápad</string>
|
||||
<string name="front">vpřed</string>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<string name="direction_style_sidewise">Podle stran (8 sektorů)</string>
|
||||
<string name="direction_style_clockwise">Podle hodin (12 sektorů)</string>
|
||||
<string name="settings_direction_style">Styl interpretace směrů</string>
|
||||
<string name="settings_direction_style_descr">Vyberte způsob vyjádření relativního směru pohybu.</string>
|
||||
<string name="settings_direction_style_descr">Vyberte způsob vyjádření relativního směru pohybu</string>
|
||||
<string name="auto_announce_on">Spustit automatické ohlašování</string>
|
||||
<string name="auto_announce_off">Zastavit automatické ohlašování</string>
|
||||
<string name="i_am_here">Jsem zde</string>
|
||||
|
@ -64,16 +64,16 @@
|
|||
<string name="use_fluorescent_overlays">Fluorescentní barvy</string>
|
||||
<string name="use_fluorescent_overlays_descr">Použít fluorescentní barvy pro zobrazení cest a tras.</string>
|
||||
<string name="offline_edition">Off-line editace</string>
|
||||
<string name="offline_edition_descr">Vždy používat off-line editaci.</string>
|
||||
<string name="offline_edition_descr">Pokud je povolena off-line editace, změny budou nejprve uloženy lokálně a odeslány až na žádost, jinak budou změny odeslány ihned.</string>
|
||||
<string name="update_poi_does_not_change_indexes">Změny POI bodů v aplikaci nemají vliv na zobrazení stažených map, změny se ukládají do souboru ve vašem zařízení.</string>
|
||||
<string name="local_openstreetmap_uploading">Nahrávání…</string>
|
||||
<string name="local_openstreetmap_were_uploaded">{0} POI/Poznámek bylo odesláno</string>
|
||||
<string name="local_openstreetmap_were_uploaded">{0} POI/poznámek bylo odesláno</string>
|
||||
<string name="local_openstreetmap_uploadall">Odeslat všechny</string>
|
||||
<string name="local_openstreetmap_upload">Odeslat změny do OSM</string>
|
||||
<string name="local_openstreetmap_upload">Odeslat změnu do OSM</string>
|
||||
<string name="local_openstreetmap_delete">Smazat změnu</string>
|
||||
<string name="local_openstreetmap_descr_title">Off-line editace OSM:</string>
|
||||
<string name="local_openstreetmap_settings">OSM POI body/poznámky uložené na zařízení</string>
|
||||
<string name="local_openstreetmap_settings_descr">Zobrazit a spravovat OSM POI body/poznámky uložené v databázi na zařízení.</string>
|
||||
<string name="local_openstreetmap_settings">OSM POI/poznámky uložené v zařízení</string>
|
||||
<string name="local_openstreetmap_settings_descr">Zobrazit a spravovat OSM POI/poznámky uložené v databázi v zařízení.</string>
|
||||
<string name="live_monitoring_interval_descr">Zadejte interval nahrávání pozice na server.</string>
|
||||
<string name="live_monitoring_interval">Interval přímého přenosu</string>
|
||||
<string name="live_monitoring_url_descr">Zadejte webovou adresu serveru pro přímý přenos pozice. Parametry: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
|
||||
|
@ -97,7 +97,7 @@
|
|||
<string name="index_name_other">Mapy celého světa a tematické mapy</string>
|
||||
<string name="index_name_wiki">Celý svět - Wikipedie</string>
|
||||
<string name="index_name_voice">Hlasové pokyny (nahrávky, omezené funkce)</string>
|
||||
<string name="index_name_tts_voice">Hlasové pokyny (TTS-generované)</string>
|
||||
<string name="index_name_tts_voice">Hlasové pokyny (TTS, doporučeno)</string>
|
||||
<string name="amenity_type_osmwiki">Wikipedie (off-line)</string>
|
||||
<string name="amenity_type_user_defined">Uživatelsky definované</string>
|
||||
<string name="fav_export_confirmation">Soubor exportu obsahující Oblíbené již existuje. Nahradit ho\?</string>
|
||||
|
@ -110,9 +110,9 @@
|
|||
<string name="index_settings">Spravovat mapové soubory</string>
|
||||
<string name="index_settings_descr">Stáhnout a spravovat off-line mapy uložené ve vašem zařízení.</string>
|
||||
<string name="general_settings">Obecné</string>
|
||||
<string name="general_settings_descr">Nastavení displeje, jazyka, zvuku a dalších parametrů.</string>
|
||||
<string name="general_settings_descr">Nastavení zobrazení a dalších společných parametrů aplikace.</string>
|
||||
<string name="user_name">Vaše OSM uživatelské jméno</string>
|
||||
<string name="open_street_map_login_descr">Vaše uživatelské jméno na openstreetmap.org.</string>
|
||||
<string name="open_street_map_login_descr">Potřebné pro přispívání do openstreetmap.org.</string>
|
||||
<string name="user_password">Heslo</string>
|
||||
<string name="osmand_service">Služba na pozadí</string>
|
||||
<string name="osmand_service_descr">OsmAnd běží na pozadí i při vypnuté obrazovce.</string>
|
||||
|
@ -139,10 +139,10 @@
|
|||
<string name="city_type_city">Velké město</string>
|
||||
<string name="animate_route_off">Zastavit simulaci</string>
|
||||
<string name="animate_route">Zapnout animaci</string>
|
||||
<string name="file_can_not_be_renamed">Nelze přejmenovat soubor.</string>
|
||||
<string name="file_with_name_already_exists">Soubor tohoto jména již existuje.</string>
|
||||
<string name="poi_query_by_name_matches_categories">Vašemu dotazu odpovídá několik kategorií POI:</string>
|
||||
<string name="data_to_search_poi_not_available">Lokální data pro vyhledávání POI není dostupný.</string>
|
||||
<string name="file_can_not_be_renamed">Nepodařilo se přejmenovat soubor.</string>
|
||||
<string name="file_with_name_already_exists">Soubor s tímto názvem již existuje.</string>
|
||||
<string name="poi_query_by_name_matches_categories">Bylo nalezeno několik souvisejících kategorií POI.</string>
|
||||
<string name="data_to_search_poi_not_available">Stáhněte si offline data pro vyhledávání POI.</string>
|
||||
<string name="poi_filter_by_name">Hledat podle jména</string>
|
||||
<string name="old_poi_file_should_be_deleted">Soubor s POI daty \'%1$s\' již není potřeba a může být smazán.</string>
|
||||
<string name="update_poi_file_not_found">Lokální soubor pro úpravu POI bodů nebyl nalezen a ani nemohl být vytvořen.</string>
|
||||
|
@ -168,7 +168,7 @@
|
|||
<string name="show_more_map_detail">Více mapových detailů</string>
|
||||
<string name="show_more_map_detail_descr">Zobrazit některé detaily vektorové mapy (silnice, atd.) již při menším zvětšení.</string>
|
||||
<string name="favourites_delete_multiple_succesful">Oblíbené body smazány.</string>
|
||||
<string name="favorite_delete_multiple">Chystáte se smazat %1$d Oblíbených a %2$d skupin Oblíbených. Opravdu smazat\?</string>
|
||||
<string name="favorite_delete_multiple">Opravdu chcete smazat %1$d Oblíbených a %2$d skupin Oblíbených\?</string>
|
||||
<string name="favorite_home_category">Doma</string>
|
||||
<string name="favorite_friends_category">Přátelé</string>
|
||||
<string name="favorite_places_category">Místa</string>
|
||||
|
@ -194,7 +194,7 @@
|
|||
<string name="local_index_map_data">Mapová data</string>
|
||||
<string name="local_indexes_cat_backup">Záloha</string>
|
||||
<string name="local_indexes_cat_tts">Hlasové pokyny (TTS)</string>
|
||||
<string name="local_indexes_cat_voice">Hlasové pokyny (media)</string>
|
||||
<string name="local_indexes_cat_voice">Hlasové pokyny (nahrané)</string>
|
||||
<string name="local_indexes_cat_tile">On-line mapy a dlaždice v mezipaměti</string>
|
||||
<string name="local_indexes_cat_map">Standardní mapy (vektorové)</string>
|
||||
<string name="local_indexes_cat_poi">Data POI</string>
|
||||
|
@ -248,25 +248,25 @@
|
|||
<string name="select_build_to_install">Vyberte jeden z balíčků OsmAnd k nainstalování</string>
|
||||
<string name="contribution_activity">Speciální aktivita pro vývojovou verzi</string>
|
||||
<string name="search_offline_clear_search">Nové hledání</string>
|
||||
<string name="map_text_size_descr">Zvolte velikost písma ve jménech na mapě.</string>
|
||||
<string name="map_text_size_descr">Velikost písma pro názvy na mapě:</string>
|
||||
<string name="map_text_size">Velikost písma</string>
|
||||
<string name="installing_new_resources">Rozbalování nových dat…</string>
|
||||
<string name="internet_connection_required_for_online_route">On-line navigaci nelze použít, protože připojení k Internetu není k dispozici.</string>
|
||||
<string name="internet_connection_required_for_online_route">On-line navigaci nelze použít bez připojení k internetu.</string>
|
||||
<string name="tts_language_not_supported_title">Nepodporovaný jazyk</string>
|
||||
<string name="tts_language_not_supported">Vybraný jazyk není podporován nainstalovaným TTS enginem. Najít jiný TTS v obchodě\? Jinak bude použit výchozí TTS jazyk.</string>
|
||||
<string name="tts_language_not_supported">Vybraný jazyk není podporován nainstalovaným TTS (text-to-speech) modulem Androidu. Bude použit výchozí TTS jazyk. Najít jiný TTS modul v obchodě\?</string>
|
||||
<string name="tts_missing_language_data_title">Chybějící data</string>
|
||||
<string name="tts_missing_language_data">Přejít do obchodu pro stažení vybraného jazyka\?</string>
|
||||
<string name="gpx_option_reverse_route">Obrátit GPX trasu</string>
|
||||
<string name="gpx_option_reverse_route">Obrátit směr stopy</string>
|
||||
<string name="gpx_option_destination_point">Použít současný cíl trasy</string>
|
||||
<string name="gpx_option_from_start_point">Projet celou trasu</string>
|
||||
<string name="switch_to_vector_map_to_see">Pro tuto oblast je k dispozici offline vektorová mapa.
|
||||
\t
|
||||
\t Pro zobrazení zvolte Menu → Nastavení mapy → Zdroj map… → Vektorové off-line mapy.</string>
|
||||
\n\t
|
||||
\n\tPro zobrazení zvolte Menu → Nastavení mapy → Zdroj map… → Vektorové off-line mapy.</string>
|
||||
<string name="choose_audio_stream">Kanál pro navádění</string>
|
||||
<string name="choose_audio_stream_descr">Zvolte kanál poskytující hlasové navádění.</string>
|
||||
<string name="choose_audio_stream_descr">Zvolte reproduktor pro hlasové navádění.</string>
|
||||
<string name="voice_stream_voice_call">Zvuk telefonního hovoru (přeruší Bluetooth autorádio)</string>
|
||||
<string name="voice_stream_notification">Upozornění</string>
|
||||
<string name="voice_stream_music">Média/Zvuk navigace</string>
|
||||
<string name="voice_stream_music">Média/zvuky navigace</string>
|
||||
<string name="warning_tile_layer_not_downloadable">Data pro mapovou vrstvu %1$s nelze stáhnout, reinstalace může pomoci.</string>
|
||||
<string name="overlay_transparency_descr">Upravit průhlednost překryvné mapy.</string>
|
||||
<string name="overlay_transparency">Průhlednost překryvu</string>
|
||||
|
@ -279,9 +279,9 @@
|
|||
<string name="layer_overlay">Překryvná mapa…</string>
|
||||
<string name="shared_string_none">Žádná</string>
|
||||
<string name="map_overlay">Překryvná mapa</string>
|
||||
<string name="map_overlay_descr">Vyberte překryvnou mapu.</string>
|
||||
<string name="map_overlay_descr">Vyberte překryvnou mapu</string>
|
||||
<string name="tile_source_already_installed">Mapa již nainstalována, \'Nastavení\' budou aktualizována.</string>
|
||||
<string name="select_tile_source_to_install">Vyberte mapy k instalaci nebo aktualizaci.</string>
|
||||
<string name="select_tile_source_to_install">Vyberte (dlaždicové) mapy k instalaci nebo aktualizaci.</string>
|
||||
<string name="internet_not_available">Nelze provést tuto akci bez připojení k Internetu.</string>
|
||||
<string name="install_more">Instalovat další…</string>
|
||||
<string name="level_to_switch_vector_raster_descr">Použít rastrové mapy pro cokoli nad tuto úroveň.</string>
|
||||
|
@ -289,7 +289,7 @@
|
|||
<string name="error_doing_search">Nelze provést offline hledání.</string>
|
||||
<string name="search_osm_offline">Hledat pomocí polohy</string>
|
||||
<string name="system_locale">Podle systému</string>
|
||||
<string name="preferred_locale_descr">Volba jazyka (projeví se jakmile bude OsmAnd restartován).</string>
|
||||
<string name="preferred_locale_descr">Jazyk zobrazení aplikace (projeví se po restartu OsmAnd).</string>
|
||||
<string name="preferred_locale">Jazyk</string>
|
||||
<string name="shared_string_next">Další</string>
|
||||
<string name="shared_string_previous">Předchozí</string>
|
||||
|
@ -310,18 +310,18 @@
|
|||
<string name="add_waypoint_dialog_added">GPX bod na trase \'\'{0}\'\' byl přidán</string>
|
||||
<string name="add_waypoint_dialog_title">Přidat bod na zaznamenávanou GPX trasu</string>
|
||||
<string name="osmand_routing_experimental">Off-line navigace je experimentální a funguje jen pro větší vzdálenosti než 20 km. Navigace je dočasně přepnuta na on-line CloudMade.</string>
|
||||
<string name="specified_dir_doesnt_exist">Nemohu najít zadaný adresář.</string>
|
||||
<string name="specified_dir_doesnt_exist">Nepodařilo se najít zadaný adresář.</string>
|
||||
<string name="application_dir">Adresář pro data</string>
|
||||
<string name="gps_status_app_not_found">Aplikace pro zobrazení stavu GPS není nainstalovaná. Hledat v obchodě?</string>
|
||||
<string name="voice_is_not_available_msg">Hlasové navádění je nedostupné. Přejděte do „Nastavení“ → „Nastavení navigace“ → „Hlasová data“ a vyberte nebo stáhněte balíček s hlasovými pokyny.</string>
|
||||
<string name="voice_is_not_available_title">Žádná hlasová data nejsou zvolena</string>
|
||||
<string name="voice_is_not_available_title">Zvolte balíček hlasových údajů</string>
|
||||
<string name="trace_rendering_descr">Zaškrtněte pro zobrazení statistik o vykreslování mapy.</string>
|
||||
<string name="trace_rendering">Sledovat vykreslování</string>
|
||||
<string name="daynight_mode_day">Den</string>
|
||||
<string name="daynight_mode_night">Noc</string>
|
||||
<string name="daynight_mode_auto">Východ/západ slunce</string>
|
||||
<string name="daynight_mode_sensor">Senzor osvětlení</string>
|
||||
<string name="daynight_descr">Vyberte logiku pro přepínání mezi denním a nočním režimem.</string>
|
||||
<string name="daynight_descr">Upravte přepínání mezi denním a nočním režimem.</string>
|
||||
<string name="daynight">Denní/noční režim</string>
|
||||
<string name="download_files_question">Stáhnout {0} souborů ({1} MB)?</string>
|
||||
<string name="items_were_selected">vybráno {0} položek</string>
|
||||
|
@ -332,24 +332,24 @@
|
|||
<string name="fast_route_mode_descr">Zapněte pro výpočet nejrychlejší trasy nebo vypněte pro ekonomickou trasu.</string>
|
||||
<string name="tiles_to_download_estimated_size">Pro zvětšení {0} je třeba stáhnout {1} mapových dlaždic, celkem {2} MB</string>
|
||||
<string name="shared_string_download_map">Stáhnout mapu</string>
|
||||
<string name="select_max_zoom_preload_area">Vyberte maximální zvětšení stahovaných map</string>
|
||||
<string name="select_max_zoom_preload_area">Maximální přiblížení pro přednačítání</string>
|
||||
<string name="maps_could_not_be_downloaded">Tuto mapu nelze stáhnout</string>
|
||||
<string name="continuous_rendering">Průběžné vykreslování</string>
|
||||
<string name="continuous_rendering_descr">Při zaškrtnuté volbě se mapa bude vykreslovat postupně.</string>
|
||||
<string name="rendering_exception">Nelze vykreslit vybranou oblast</string>
|
||||
<string name="rendering_exception">Nepodařilo se vykreslit vybranou oblast.</string>
|
||||
<string name="rendering_out_of_memory">Nedostatek paměti pro zobrazení vybrané oblasti</string>
|
||||
<string name="show_point_options">Možnosti bodu…</string>
|
||||
<string name="renderer_load_sucess">Vykreslovač načten</string>
|
||||
<string name="renderer_load_exception">Nepodařilo se načíst vykreslovač</string>
|
||||
<string name="renderer_load_exception">Nepodařilo se načíst vykreslovací modul.</string>
|
||||
<string name="renderers">Vektorový vykreslovač</string>
|
||||
<string name="renderers_descr">Vyberte styl vektorového vykreslování.</string>
|
||||
<string name="renderers_descr">Vyberte styl vykreslování</string>
|
||||
<string name="poi_context_menu_website">Zobrazit webovou stránku bodu</string>
|
||||
<string name="poi_context_menu_call">Zobrazit telefonní číslo bodu</string>
|
||||
<string name="website">Webová stránka</string>
|
||||
<string name="phone">telefon</string>
|
||||
<string name="download_type_to_filter">vyhledat</string>
|
||||
<string name="use_high_res_maps">Vysoké rozlišení</string>
|
||||
<string name="use_high_res_maps_descr">Použít mapu s vysokým rozlišením pro jemné displeje.</string>
|
||||
<string name="use_high_res_maps_descr">Neroztahovat (a nerozmazávat) mapové dlaždice na displejích s vysokou hustotou bodů.</string>
|
||||
<string name="unknown_location">Pozice ještě není známa.</string>
|
||||
<string name="context_menu_item_search_transport">Hledat veřejnou dopravu</string>
|
||||
<string name="transport_searching_transport">Hledání dopravy (žádný cíl):</string>
|
||||
|
@ -358,15 +358,15 @@
|
|||
<string name="voice">Nahrávka hlasu</string>
|
||||
<string name="no_vector_map_loaded">Vektorové mapy nebyly načteny</string>
|
||||
<string name="gpx_files_not_found">Žádné GPX soubory nebyly nalezeny v adresáři tracks</string>
|
||||
<string name="error_reading_gpx">Nelze načíst GPX data</string>
|
||||
<string name="error_reading_gpx">Nepodařilo se načíst GPX data.</string>
|
||||
<string name="vector_data">Vektorové off-line mapy</string>
|
||||
<string name="transport_context_menu">Hledat dopravu ze zastávky</string>
|
||||
<string name="transport_context_menu">Hledat dopravu na zastávce</string>
|
||||
<string name="poi_context_menu_modify">Upravit POI</string>
|
||||
<string name="poi_context_menu_delete">Smazat POI</string>
|
||||
<string name="rotate_map_compass_opt">Směr kompasu</string>
|
||||
<string name="rotate_map_bearing_opt">Směr pohybu</string>
|
||||
<string name="rotate_map_none_opt">Neotáčet (sever vždy nahoru)</string>
|
||||
<string name="rotate_map_to_bearing_descr">Zvolte směr natočení mapy.</string>
|
||||
<string name="rotate_map_to_bearing_descr">Směr natočení mapy:</string>
|
||||
<string name="rotate_map_to_bearing">Natočení mapy</string>
|
||||
<string name="show_route">Ukázat cestu</string>
|
||||
<string name="fav_imported_sucessfully">Oblíbená místa importována</string>
|
||||
|
@ -374,7 +374,7 @@
|
|||
<string name="fav_saved_sucessfully">Oblíbená místa uložena do {0}</string>
|
||||
<string name="no_fav_to_save">Žádná Oblíbená místa k uložení</string>
|
||||
<string name="shared_string_import">Importovat</string>
|
||||
<string name="error_occurred_loading_gpx">Nelze načíst GPX</string>
|
||||
<string name="error_occurred_loading_gpx">Nepodařilo se načíst GPX.</string>
|
||||
<string name="send_report">Odeslat hlášení</string>
|
||||
<string name="none_region_found">Na paměťové kartě nelze najít žádné stáhnuté mapy.</string>
|
||||
<string name="poi_namefinder_query_empty">Psaním hledejte POI</string>
|
||||
|
@ -383,7 +383,7 @@
|
|||
<string name="layer_yandex_traffic">Yandex doprava</string>
|
||||
<string name="layer_route">Cesta</string>
|
||||
<string name="shared_string_favorites">Oblíbené</string>
|
||||
<string name="layer_osm_bugs">OSM Poznámky (on-line)</string>
|
||||
<string name="layer_osm_bugs">OSM poznámky (online)</string>
|
||||
<string name="layer_poi">Vrstva POI…</string>
|
||||
<string name="layer_map">Zdroj map…</string>
|
||||
<string name="menu_layers">Mapová data</string>
|
||||
|
@ -398,9 +398,9 @@
|
|||
<string name="gps_provider">GPS</string>
|
||||
<string name="int_seconds">sekund</string>
|
||||
<string name="int_min">min.</string>
|
||||
<string name="background_service_int_descr">Vyberte interval pro zaměřování polohy pro službu na pozadí.</string>
|
||||
<string name="background_service_int_descr">Interval probuzení pro službu na pozadí:</string>
|
||||
<string name="background_service_int">Interval zaměřování GPS</string>
|
||||
<string name="background_service_provider_descr">Vyberte způsob získání polohy pro službu na pozadí.</string>
|
||||
<string name="background_service_provider_descr">Způsob získání polohy službou na pozadí:</string>
|
||||
<string name="background_service_provider">Poskytovatel polohy</string>
|
||||
<string name="background_router_service_descr">Sleduje vaši pozici i když je obrazovka vypnutá.</string>
|
||||
<string name="background_router_service">Sledování polohy na pozadí</string>
|
||||
|
@ -415,7 +415,7 @@
|
|||
<string name="voice_data_initializing">Inicializace hlasových dat…</string>
|
||||
<string name="voice_data_not_supported">Nepodporovaná verze hlasových dat</string>
|
||||
<string name="voice_data_corrupted">Zvolené hlasové údaje jsou poškozené</string>
|
||||
<string name="voice_data_unavailable">Vybraná hlasová data jsou nedostupná</string>
|
||||
<string name="voice_data_unavailable">Vybraný balíček hlasových dat není dostupný</string>
|
||||
<string name="sd_unmounted">Paměťová karta není dostupná.
|
||||
\nNeuvidíte mapu a nebudete moci ani nic najít.</string>
|
||||
<string name="sd_mounted_ro">Paměťová karta má zakázaný zápis.
|
||||
|
|
|
@ -222,7 +222,7 @@
|
|||
<string name="poi_craft_gardener">Gärtner</string>
|
||||
<string name="poi_gas">Flüssiggasspeicher</string>
|
||||
<string name="poi_gate">Tor</string>
|
||||
<string name="poi_shop_yes">Gemischtwarenhandlung</string>
|
||||
<string name="poi_shop_yes">Allgemeines Geschäft</string>
|
||||
<string name="poi_geyser">Geysir</string>
|
||||
<string name="poi_gift">Geschenkeladen</string>
|
||||
<string name="poi_glacier">Gletscher</string>
|
||||
|
@ -3901,4 +3901,8 @@
|
|||
<string name="poi_waste_transfer_station">Müllumladestation</string>
|
||||
<string name="poi_weightbridge">Fahrzeugwaage</string>
|
||||
<string name="poi_ranger_station">Rangerstation</string>
|
||||
<string name="poi_swimming_area">Schwimmbereich</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Fledermaustunnel</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Fledermausbrücke</string>
|
||||
<string name="poi_wildlife_crossing">Wildwechsel</string>
|
||||
</resources>
|
|
@ -4031,4 +4031,5 @@
|
|||
<string name="routing_attr_allow_streams_name">Bäche und Entwässerungsgräben erlauben</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Gewässer erlauben, die nicht ständig Wasser führen</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Gewässer erlauben, die nicht ständig Wasser führen</string>
|
||||
<string name="voice_prompts_timetable">Zeiten der Sprachansagen</string>
|
||||
</resources>
|
|
@ -322,7 +322,7 @@
|
|||
<string name="poi_fuel_e85">E85</string>
|
||||
<string name="poi_fuel_biogas">biogaso</string>
|
||||
<string name="poi_fuel_electricity">elektro</string>
|
||||
<string name="poi_electricity_combined_charging">Ŝargostacio</string>
|
||||
<string name="poi_electricity_combined_charging">Ŝargostacio;shargostacio;sxargostacio;stacio de ŝargo;elektroaŭto;elektra aŭto;tesla</string>
|
||||
<string name="poi_vehicle_ramp">Aŭtomobil-ripara fosaĵeto</string>
|
||||
<string name="poi_taxi">Taksistacio</string>
|
||||
<string name="poi_railway_buffer_stop">Baraĵo trakfina</string>
|
||||
|
@ -3891,4 +3891,8 @@
|
|||
<string name="poi_ranger_station">Oficejo de naturrezervejo</string>
|
||||
<string name="poi_lavoir">Vestaĵ-lavejo (ĉe rivero)</string>
|
||||
<string name="poi_waste_transfer_station">Stacio de rubmastrumado</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Tunelo por vespertoj</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Ponto por vespertoj</string>
|
||||
<string name="poi_wildlife_crossing">Trairejo por sovaĝaj bestoj</string>
|
||||
<string name="poi_swimming_area">Naĝejo natura</string>
|
||||
</resources>
|
|
@ -4027,4 +4027,5 @@
|
|||
<string name="routing_attr_allow_streams_name">Permesi riveretojn kaj fosaĵojn</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permesi navigi per periode sekiĝantaj akvovojoj</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permesi sezonajn akvovojojn</string>
|
||||
<string name="voice_prompts_timetable">Tempoj de voĉaj anoncoj</string>
|
||||
</resources>
|
|
@ -189,7 +189,7 @@
|
|||
<string name="poi_fuel_biogas">Biogás</string>
|
||||
<string name="poi_fuel_lh2">Hidrógeno líquido</string>
|
||||
<string name="poi_fuel_electricity">Electricidad</string>
|
||||
<string name="poi_electricity_combined_charging">Estación vehícular de carga eléctrica</string>
|
||||
<string name="poi_electricity_combined_charging">Estación de carga para vehículos eléctricos;Estación vehícular de carga eléctrica;Suministro para vehículos eléctricos</string>
|
||||
<string name="poi_vehicle_ramp">Rampa de vehículos</string>
|
||||
<string name="poi_compressed_air">Aire comprimido</string>
|
||||
<string name="poi_parking">Estacionamiento;Aparcamiento</string>
|
||||
|
@ -3905,4 +3905,8 @@
|
|||
<string name="poi_ranger_station">Estación de guardabosques</string>
|
||||
<string name="poi_lavoir">Lavadero público de ropa</string>
|
||||
<string name="poi_waste_transfer_station">Estación de transferencia de residuos</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Túnel para murciélagos</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Puente para murciélagos</string>
|
||||
<string name="poi_wildlife_crossing">Cruce de vida silvestre</string>
|
||||
<string name="poi_swimming_area">Área de natación</string>
|
||||
</resources>
|
|
@ -4032,4 +4032,5 @@
|
|||
<string name="routing_attr_allow_streams_name">Permitir arroyos y desagües</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permite cursos de agua intermitentes</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permitir cursos de agua intermitentes</string>
|
||||
<string name="voice_prompts_timetable">Tiempo de los avisos por voz</string>
|
||||
</resources>
|
|
@ -189,7 +189,7 @@
|
|||
<string name="poi_fuel_biogas">Biogás</string>
|
||||
<string name="poi_fuel_lh2">Hidrógeno líquido</string>
|
||||
<string name="poi_fuel_electricity">Electricidad</string>
|
||||
<string name="poi_electricity_combined_charging">Estación vehícular de carga eléctrica</string>
|
||||
<string name="poi_electricity_combined_charging">Estación de carga para vehículos eléctricos;Estación vehícular de carga eléctrica;Suministro para vehículos eléctricos</string>
|
||||
<string name="poi_vehicle_ramp">Rampa de vehículos</string>
|
||||
<string name="poi_compressed_air">Aire comprimido</string>
|
||||
<string name="poi_parking">Estacionamiento;Aparcamiento</string>
|
||||
|
@ -3905,4 +3905,8 @@
|
|||
<string name="poi_water_source_tap">Grifo</string>
|
||||
<string name="poi_water_source_water_works">Planta potabilizadora</string>
|
||||
<string name="poi_water_source_tube_well">Pozo entubado</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Túnel para murciélagos</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Puente para murciélagos</string>
|
||||
<string name="poi_wildlife_crossing">Cruce de vida silvestre</string>
|
||||
<string name="poi_swimming_area">Área de natación</string>
|
||||
</resources>
|
|
@ -4029,4 +4029,5 @@
|
|||
<string name="profile_type_user_string">Perfil de usuario</string>
|
||||
<string name="profile_type_osmand_string">Perfil de OsmAnd</string>
|
||||
<string name="profile_by_default_description">Elige el perfil que será usado al iniciar la aplicación.</string>
|
||||
<string name="voice_prompts_timetable">Tiempo de indicaciones por voz</string>
|
||||
</resources>
|
|
@ -124,7 +124,7 @@
|
|||
<string name="poi_fuel_methanol">Metanol</string>
|
||||
<string name="poi_fuel_lh2">Hidrógeno líquido</string>
|
||||
<string name="poi_fuel_electricity">Electricidad</string>
|
||||
<string name="poi_electricity_combined_charging">Estación de carga</string>
|
||||
<string name="poi_electricity_combined_charging">Estación de carga;Estación de carga de vehículos eléctricos; Punto de recarga eléctrica; Punto de carga; Estación de carga electrónica; Equipo de suministro de vehículos eléctricos</string>
|
||||
<string name="poi_vehicle_ramp">Rampa de vehículos</string>
|
||||
<string name="poi_compressed_air">Aire comprimido</string>
|
||||
<string name="poi_parking">Aparcamiento</string>
|
||||
|
@ -3626,7 +3626,7 @@
|
|||
<string name="poi_vehicle_military">Acceso de vehículos: militar</string>
|
||||
<string name="poi_vehicle_delivery">Acceso del vehículo: entrega</string>
|
||||
<string name="poi_vehicle_forestry">Acceso de vehículos: silvicultura</string>
|
||||
<string name="poi_motorcar_yes">Acceso a los coches:</string>
|
||||
<string name="poi_motorcar_yes">Acceso a los coches: si</string>
|
||||
<string name="poi_motorcar_private">Acceso para automóviles: privado</string>
|
||||
<string name="poi_motorcar_no">Acceso para automóviles: no</string>
|
||||
<string name="poi_motorcar_destination">Acceso para automóviles: destino</string>
|
||||
|
@ -3851,4 +3851,56 @@
|
|||
<string name="poi_parking_rooftop">Azotea</string>
|
||||
<string name="poi_gpx_point">Punto GPX</string>
|
||||
<string name="poi_fuel_lng">Gas natural licuado</string>
|
||||
<string name="poi_liaison_filter">Enlace</string>
|
||||
<string name="poi_diplomatic_liaison">Enlace</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Túnel para murciélagos</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Puente para murciélagos</string>
|
||||
<string name="poi_wildlife_crossing">Cruce de vida silvestre</string>
|
||||
<string name="poi_swimming_area">Área de natación</string>
|
||||
<string name="poi_lavoir">Lavadero público de ropa</string>
|
||||
<string name="poi_ranger_station">Estación de guardabosques</string>
|
||||
<string name="poi_water_source_well">Pozo</string>
|
||||
<string name="poi_water_source_tube_well">Pozo entubado</string>
|
||||
<string name="poi_nurse">Enfermera</string>
|
||||
<string name="poi_mobile_money_agent">Agente de dinero móvil</string>
|
||||
<string name="poi_consulate_honorary_consul">Cónsul honorario</string>
|
||||
<string name="poi_consulate_consular_office">Oficina consular</string>
|
||||
<string name="poi_consulate_consular_agency">Agencia consular</string>
|
||||
<string name="poi_consulate_yes">Dirigido por un cónsul</string>
|
||||
<string name="poi_embassy_nunciature">Nunciatura</string>
|
||||
<string name="poi_diplomatic_services_citizen_services_filter">Servicios al ciudadano</string>
|
||||
<string name="poi_diplomatic_services_immigrant_visas_filter">Visas de inmigrante</string>
|
||||
<string name="poi_diplomatic_services_non_immigrant_visas_filter">Visas de no inmigrante</string>
|
||||
<string name="poi_waste_transfer_station">Estación de transferencia de residuos</string>
|
||||
<string name="poi_weightbridge">Báscula</string>
|
||||
<string name="poi_water_source_lake">Lago</string>
|
||||
<string name="poi_water_source_river">Río</string>
|
||||
<string name="poi_water_source_powered_pump">Bomba accionada</string>
|
||||
<string name="poi_water_source_water_tank">Depósito de agua</string>
|
||||
<string name="poi_water_source_tap">Grifo</string>
|
||||
<string name="poi_water_source_water_works">Planta potabilizadora</string>
|
||||
<string name="poi_vaccination_covid19">Vacunación: COVID 19</string>
|
||||
<string name="poi_health_specialty_vaccination_yes">Vacunación</string>
|
||||
<string name="poi_lifeguard_base">Base de salvavidas</string>
|
||||
<string name="poi_siren">Sirena</string>
|
||||
<string name="poi_diplomatic_services_citizen_services_no">No</string>
|
||||
<string name="poi_diplomatic_services_citizen_services_yes">Sí</string>
|
||||
<string name="poi_diplomatic_services_immigrant_visas_no">No</string>
|
||||
<string name="poi_diplomatic_services_immigrant_visas_yes">Sí</string>
|
||||
<string name="poi_diplomatic_services_non_immigrant_visas_no">No</string>
|
||||
<string name="poi_diplomatic_services_non_immigrant_visas_yes">Sí</string>
|
||||
<string name="poi_liaison_subnational">Subnacional</string>
|
||||
<string name="poi_liaison_representative_office">Oficina representativa</string>
|
||||
<string name="poi_liaison_liaison_office">Oficina</string>
|
||||
<string name="poi_consulate_consulate_general">Consulado general</string>
|
||||
<string name="poi_embassy_residence">Residencia</string>
|
||||
<string name="poi_embassy_mission">Misión</string>
|
||||
<string name="poi_embassy_interests_section">Sección de intereses</string>
|
||||
<string name="poi_embassy_high_commission">Alto comisionado</string>
|
||||
<string name="poi_embassy_delegation">Delegación</string>
|
||||
<string name="poi_embassy_branch_embassy">Rama/sucursal</string>
|
||||
<string name="poi_embassy_yes">Encabezado por un embajador</string>
|
||||
<string name="poi_diplomatic_embassy">Embajada</string>
|
||||
<string name="poi_consulate_filter">Consulado</string>
|
||||
<string name="poi_embassy_filter">Embajada</string>
|
||||
</resources>
|
|
@ -14,7 +14,7 @@
|
|||
<string name="use_fluorescent_overlays">Usar superpuestos fluorescentes</string>
|
||||
<string name="use_fluorescent_overlays_descr">Usa colores fluorescentes para mostrar trazas y rutas.</string>
|
||||
<string name="offline_edition">Edición sin conexión</string>
|
||||
<string name="offline_edition_descr">Usa siempre edición sin conexión.</string>
|
||||
<string name="offline_edition_descr">Si la edición sin conexión está habilitada, los cambios se guardarán primero localmente y se cargarán a pedido; de lo contrario, los cambios se cargarán inmediatamente.</string>
|
||||
<string name="update_poi_does_not_change_indexes">Los cambios de PDI dentro de la aplicación no afectan a los archivos de mapa descargados; en su lugar, los cambios se guardan como un archivo en el dispositivo.</string>
|
||||
<string name="local_openstreetmap_uploading">Subiendo…</string>
|
||||
<string name="local_openstreetmap_were_uploaded">{0} PDI/Notas de OSM subidos</string>
|
||||
|
@ -64,7 +64,7 @@
|
|||
<string name="global_app_settings">Ajustes globales de la aplicación</string>
|
||||
<string name="user_name">Usuario de OSM</string>
|
||||
<string name="open_street_map_login_descr">Necesario para envíos a openstreetmap.org.</string>
|
||||
<string name="user_password">Contraseña de OSM</string>
|
||||
<string name="user_password">Contraseña</string>
|
||||
<string name="osmand_service">Modo reposo</string>
|
||||
<string name="osmand_service_descr">OsmAnd se ejecuta en modo reposo con la pantalla apagada.</string>
|
||||
<string name="switch_to_raster_map_to_see">Descargar un mapa vectorial sin conexión de esta ubicación en «Ajustes → Gestionar mapas», o cambiar al complemento «Mapas en línea».</string>
|
||||
|
@ -616,7 +616,7 @@
|
|||
\nDescarga los mapas de teselas directamente a través de fuentes en línea, o prepararlos para tu uso sin conexión (copiándolos manualmente en la carpeta de datos OsmAnd) como una base de datos SQLite que puede generarse con varias herramientas de preparación de mapas de terceros.</string>
|
||||
<string name="osmand_background_plugin_description">Muestra los ajustes para activar en modo reposo el seguimiento y la navegación, activando periódicamente el dispositivo GPS (con la pantalla apagada).</string>
|
||||
<string name="osmand_accessibility_description">Activa las funciones de accesibilidad del dispositivo directamente en OsmAnd. Facilita por ejemplo, el ajuste de la velocidad de la voz para voces de texto a voz, la configuración de navegación de pantalla con el panel direccional, usando la rueda de desplazamiento para el control del zoom, o la retroalimentación de texto a voz, por ejemplo, para anunciar la ubicación automáticamente.</string>
|
||||
<string name="osmand_development_plugin_description">Este complemento muestra los ajustes de funciones de desarrollo y depuración para probar la simulación de rutas, el rendimiento del renderizado, o las indicaciones por voz. Estos ajustes están destinados para los desarrolladores y no son necesarios para el usuario general.</string>
|
||||
<string name="osmand_development_plugin_description">Ajustes de funciones de desarrollo y depuración, como simulación de navegación, el rendimiento del renderizado, o las indicaciones por voz. Destinados a desarrolladores y no son necesarios para el uso normal de la aplicación.</string>
|
||||
<string name="plugins_screen">Complementos</string>
|
||||
<string name="prefs_plugins_descr">Los complementos activan ajustes avanzados y funcionalidades adicionales.</string>
|
||||
<string name="prefs_plugins">Complementos</string>
|
||||
|
@ -976,7 +976,7 @@
|
|||
<string name="files_limit">Quedan %1$d archivos</string>
|
||||
<string name="available_downloads_left">%1$d archivos para descargar</string>
|
||||
<string name="install_paid">Versión completa</string>
|
||||
<string name="cancel_route">Descartar ruta</string>
|
||||
<string name="cancel_route">¿Descartar ruta\?</string>
|
||||
<string name="cancel_navigation">Parar navegación</string>
|
||||
<string name="clear_destination">Limpiar destino</string>
|
||||
<string name="download_using_mobile_internet">No está conectado a una red Wi-Fi. ¿Usar la conexión actual a Internet para descargar?</string>
|
||||
|
@ -1054,15 +1054,15 @@
|
|||
<string name="driving_region_descr">Región de conducción: EEUU, Europa, Reino Unido, Asia u otras.</string>
|
||||
<string name="driving_region">Región de conducción</string>
|
||||
<string name="edit_tilesource_minzoom">Zoom mínimo</string>
|
||||
<string name="edit_tilesource_expiration_time">Expira (minutos)</string>
|
||||
<string name="edit_tilesource_expiration_time">Tiempo expirado (minutos)</string>
|
||||
<string name="edit_tilesource_successfully">Fuente de teselas «%1$s» guardada</string>
|
||||
<string name="local_index_tile_data_name">Datos de teselas: %1$s</string>
|
||||
<string name="local_index_tile_data_expire">Expira (minutos): %1$s</string>
|
||||
<string name="local_index_tile_data_expire">Tiempo de expiración (minutos): %1$s</string>
|
||||
<string name="shared_string_about">Información</string>
|
||||
<string name="about_settings_descr">Información de la versión, licencias, miembros del proyecto</string>
|
||||
<string name="edit_tilesource_choose_existing">Elegir existente…</string>
|
||||
<string name="local_index_tile_data_zooms">Zooms descargados: %1$s</string>
|
||||
<string name="edit_tilesource_elliptic_tile">Mercator elíptica</string>
|
||||
<string name="local_index_tile_data_zooms">Niveles de zooms descargados: %1$s</string>
|
||||
<string name="edit_tilesource_elliptic_tile">Proyección Mercator elíptica</string>
|
||||
<string name="map_widget_fps_info">Información de FPS</string>
|
||||
<string name="base_world_map">Mapa base mundial</string>
|
||||
<string name="map_magnifier">Ampliar mapa</string>
|
||||
|
@ -1537,7 +1537,7 @@
|
|||
<string name="routing_attr_height_name">Límite de altura</string>
|
||||
<string name="routing_attr_height_description">Indica la altura permitida del vehículo en rutas.</string>
|
||||
<string name="use_fast_recalculation">Recálculo inteligente de ruta</string>
|
||||
<string name="use_fast_recalculation_desc">Para viajes largos, recalcula sólo la parte inicial de la ruta.</string>
|
||||
<string name="use_fast_recalculation_desc">Recalcula solo la parte inicial de la ruta, útil para viajes largos.</string>
|
||||
<string name="rendering_value_disabled_name">Desactivado</string>
|
||||
<string name="rendering_value_walkingRoutesScopeOSMC_name">Color por red de afiliación</string>
|
||||
<string name="rendering_value_walkingRoutesOSMC_name">Color por símbolo de senderismo OSMC</string>
|
||||
|
@ -1728,7 +1728,7 @@
|
|||
<string name="faq_item">Preguntas Frecuentes</string>
|
||||
<string name="faq_item_description">Preguntas Frecuentes</string>
|
||||
<string name="map_viewing_item">Vista del mapa</string>
|
||||
<string name="search_on_the_map_item">Búsqueda en el mapa</string>
|
||||
<string name="search_on_the_map_item">Buscando en el mapa</string>
|
||||
<string name="planning_trip_item">Planificación de viaje</string>
|
||||
<string name="instalation_troubleshooting_item">Instalación y solución de problemas</string>
|
||||
<string name="techical_articles_item">Artículos técnicos</string>
|
||||
|
@ -1919,7 +1919,7 @@
|
|||
<string name="report">Informe</string>
|
||||
<string name="no_map_markers_found">Añade marcadores a través del mapa</string>
|
||||
<string name="no_waypoints_found">No se encontraron puntos de referencia</string>
|
||||
<string name="file_name_containes_illegal_char">El nombre del archivo contiene caracteres ilegales</string>
|
||||
<string name="file_name_containes_illegal_char">Carácter ilegal en el nombre del archivo</string>
|
||||
<string name="map_mode">Modo del mapa</string>
|
||||
<string name="rendering_value_thin_name">Fino</string>
|
||||
<string name="rendering_value_medium_name">Medio</string>
|
||||
|
@ -1955,7 +1955,7 @@
|
|||
<string name="access_direction_haptic_feedback_descr">Indica la dirección del destino mediante vibración.</string>
|
||||
<string name="use_osm_live_routing_description">Activa la navegación para cambios en vivo de OsmAnd.</string>
|
||||
<string name="use_osm_live_routing">Navegación con OsmAnd Live</string>
|
||||
<string name="access_no_destination">Destino indefinido</string>
|
||||
<string name="access_no_destination">Complemento de accesibilidad: sin destino definido</string>
|
||||
<string name="map_widget_magnetic_bearing">Rumbo magnético</string>
|
||||
<string name="map_widget_bearing">Rumbo relativo</string>
|
||||
<string name="current_track">Traza actual</string>
|
||||
|
@ -2368,19 +2368,19 @@
|
|||
\n • (Opcional) Grabación del viaje en modo reposo (mientras el dispositivo está bloqueado)
|
||||
\n OsmAnd es un software de código abierto, activamente desarrollado. Cualquiera puede contribuir con la aplicación informando sobre errores, mejorando las traducciones o desarrollando nuevas funciones. Además, el proyecto también depende de contribuciones financieras para desarrollar y probar nuevas funcionalidades.
|
||||
\n</string>
|
||||
<string name="osmand_plus_extended_description_part8">Cobertura y calidad aproximada del mapa:
|
||||
\n • Europa Occidental: ****
|
||||
\n • Europa Oriental: ***
|
||||
\n • Rusia: ***
|
||||
\n • Norteamérica: ***
|
||||
\n • Sudamérica: **
|
||||
\n • Asia: **
|
||||
\n • Japón y Corea: ***
|
||||
\n • Medio Oriente: **
|
||||
\n • África: **
|
||||
\n • Antártida: *
|
||||
\n
|
||||
\n ¡Más países alrededor del globo están disponibles para descargar! Desde Afganistán a Zimbabue, desde Australia a Estados Unidos. Argentina, Brasil, Canadá, Francia, Alemania, México, Reino Unido, España, …
|
||||
<string name="osmand_plus_extended_description_part8">Cobertura y calidad aproximada del mapa:
|
||||
\n • Europa Occidental: ****
|
||||
\n • Europa Oriental: ***
|
||||
\n • Rusia: ***
|
||||
\n • Norteamérica: ***
|
||||
\n • Sudamérica: **
|
||||
\n • Asia: **
|
||||
\n • Japón y Corea: ***
|
||||
\n • Medio Oriente: **
|
||||
\n • África: **
|
||||
\n • Antártida: *
|
||||
\n ¡Más países alrededor del globo están disponibles para descargar!
|
||||
\n Desde Afganistán a Zimbabue, desde Australia a Estados Unidos. Argentina, Brasil, Canadá, Francia, Alemania, México, Reino Unido, España, …
|
||||
\n</string>
|
||||
<string name="save_poi_too_many_uppercase">El nombre contiene demasiadas mayúsculas. ¿Continuar?</string>
|
||||
<string name="srtm_menu_download_descr">Descarga el mapa de «Curvas de nivel» para usarlas en esta región.</string>
|
||||
|
@ -2516,7 +2516,7 @@
|
|||
<string name="use_location">Usar ubicación</string>
|
||||
<string name="add_location_as_first_point_descr">Añade la ubicación como punto de partida para planificar la ruta perfecta.</string>
|
||||
<string name="my_location">Mi ubicación</string>
|
||||
<string name="shared_string_finish">Finalizar</string>
|
||||
<string name="shared_string_finish">Terminar</string>
|
||||
<string name="plan_route">Planificar ruta</string>
|
||||
<string name="shared_string_sort">Ordenar</string>
|
||||
<string name="coordinate_input">Ingresar coordenadas</string>
|
||||
|
@ -2644,7 +2644,7 @@
|
|||
<string name="copy_location_name">Copiar nombre de ubicación/PDI</string>
|
||||
<string name="toast_empty_name_error">Ubicación sin nombre</string>
|
||||
<string name="show_closed_notes">Mostrar notas de OSM cerradas</string>
|
||||
<string name="switch_osm_notes_visibility_desc">Mostrar/ocultar notas de OSM en el mapa.</string>
|
||||
<string name="switch_osm_notes_visibility_desc">Mostrar u ocultar notas de OSM en el mapa.</string>
|
||||
<string name="tunnel_warning">Túnel adelante</string>
|
||||
<string name="show_tunnels">Túneles</string>
|
||||
<string name="shared_string_current">Actual</string>
|
||||
|
@ -3118,9 +3118,9 @@
|
|||
<string name="zoom_by_wunderlinq_descr">Cambia el zoom del mapa desplazando la rueda hacia arriba y hacia abajo. Salir te devuelve a la aplicación WunderLINQ.</string>
|
||||
<string name="zoom_by_wunderlinq">Usa WunderLINQ para controlar</string>
|
||||
<string name="quick_action_need_to_add_item_to_list">Añadir al menos un elemento a la lista en los ajustes de «Acción rápida»</string>
|
||||
<string name="routing_attr_piste_type_downhill_name">Esquí alpino/de descenso</string>
|
||||
<string name="routing_attr_piste_type_downhill_name">Esquí alpino y de descenso</string>
|
||||
<string name="routing_attr_piste_type_downhill_description">Pistas de esquí alpino o de descenso y acceso a remontes mecánicos.</string>
|
||||
<string name="routing_attr_piste_type_nordic_name">Esquí de travesía/nórdico</string>
|
||||
<string name="routing_attr_piste_type_nordic_name">Esquí de travesía y nórdico</string>
|
||||
<string name="routing_attr_piste_type_nordic_description">Senderos para esquí nórdico o de travesía.</string>
|
||||
<string name="routing_attr_piste_type_skitour_name">Esquí de travesía</string>
|
||||
<string name="routing_attr_piste_type_skitour_description">Rutas para el esquí de montaña.</string>
|
||||
|
@ -3358,7 +3358,7 @@
|
|||
<string name="default_speed_dialog_msg">Estima la hora de llegada para tipos de vías desconocidos y límites de velocidad en todas las vías (puede afectar al enrutado)</string>
|
||||
<string name="rendering_attr_piste_type_skitour_name">Esquí de travesía</string>
|
||||
<string name="simulate_your_location_gpx_descr">Simular la ubicación usando una traza GPX grabada.</string>
|
||||
<string name="empty_filename">El nombre de archivo está vacío</string>
|
||||
<string name="empty_filename">Nombre de archivo vacío</string>
|
||||
<string name="track_saved">Traza guardada</string>
|
||||
<string name="shared_string_revert">Revertir</string>
|
||||
<string name="quick_action_directions_from_desc">Un botón que añade el centro de la pantalla como punto de partida. Pedirá luego que se fije el destino o iniciará el cálculo de la ruta.</string>
|
||||
|
@ -3424,9 +3424,9 @@
|
|||
<string name="route_recalculation">Recálculo de la ruta</string>
|
||||
<string name="accessibility_announce">Anunciar</string>
|
||||
<string name="login_and_pass">Nombre de usuario y clave</string>
|
||||
<string name="plugin_global_prefs_info">La configuración se aplica a todos los perfiles.</string>
|
||||
<string name="plugin_global_prefs_info">Esta configuración de complementos es global, y se aplica a todos los perfiles</string>
|
||||
<string name="osm_editing">Edición de OSM</string>
|
||||
<string name="osm_edits_view_descr">Puedes ver todas las ediciones y errores de osm no enviadas en %1$s. Los puntos enviados no se muestran en OsmAnd.</string>
|
||||
<string name="osm_edits_view_descr">Puedes ver todas las ediciones y errores de osm no subidos en %1$s. Los puntos ya subidos no se muestrarán más.</string>
|
||||
<string name="app_mode_osm">OSM</string>
|
||||
<string name="select_nav_icon_descr">El icono se muestra mientras navega o mientras te estés moviendo.</string>
|
||||
<string name="select_map_icon_descr">Icono que se muestra en reposo.</string>
|
||||
|
@ -3520,7 +3520,7 @@
|
|||
<string name="hillshade_description">Mapa de sombreado utilizando tonos oscuros para mostrar pendientes, picos y tierras bajas.</string>
|
||||
<string name="slope_description">Pendiente utiliza colores para visualizar la inclinación del terreno.</string>
|
||||
<string name="terrain_slider_description">Establezca los niveles de zoom mínimo y máximo en los que se mostrará la capa.</string>
|
||||
<string name="hillshade_download_description">Se necesitan mapas adicionales para ver Sombreado en el mapa.</string>
|
||||
<string name="hillshade_download_description">Se necesitan mapas adicionales para ver sombreado en el mapa.</string>
|
||||
<string name="slope_download_description">Se necesitan mapas adicionales para ver Pendientes en el mapa.</string>
|
||||
<string name="slope_read_more">Puede leer más sobre Pendientes en %1$s.</string>
|
||||
<string name="shared_string_transparency">Transparencia</string>
|
||||
|
@ -3542,7 +3542,7 @@
|
|||
<string name="recalculate_route_in_deviation">Recalcular ruta en caso de desvío</string>
|
||||
<string name="n_items_of_z">%1$s de %2$s</string>
|
||||
<string name="download_slope_maps">Cuestas</string>
|
||||
<string name="quick_action_show_hide_terrain">Mostrar / esconder terreno</string>
|
||||
<string name="quick_action_show_hide_terrain">Mostrar o esconder terreno</string>
|
||||
<string name="quick_action_terrain_hide">Esconder terreno</string>
|
||||
<string name="quick_action_terrain_show">Mostrar terreno</string>
|
||||
<string name="quick_action_terrain_descr">Un botón para mostrar o esconder una capa de terreno en el mapa.</string>
|
||||
|
@ -3591,11 +3591,11 @@
|
|||
<string name="map_markers_item">Marcadores de mapa</string>
|
||||
<string name="favorites_item">Favoritos</string>
|
||||
<string name="navigation_profiles_item">Perfiles de navegación</string>
|
||||
<string name="quick_action_show_hide_transport">Mostrar/ocultar transporte público</string>
|
||||
<string name="quick_action_show_hide_transport">Mostrar u ocultar transporte público</string>
|
||||
<string name="quick_action_transport_hide">Ocultar transporte público</string>
|
||||
<string name="quick_action_transport_show">Mostrar transporte público</string>
|
||||
<string name="create_edit_poi">Crear / Editar POI</string>
|
||||
<string name="add_edit_favorite">Agregar / Editar Favorito</string>
|
||||
<string name="create_edit_poi">Crear o editar POI</string>
|
||||
<string name="add_edit_favorite">Agregar o editar Favorito</string>
|
||||
<string name="shared_string_add_profile">Agregar perfil</string>
|
||||
<string name="lang_an">Aragones</string>
|
||||
<string name="custom_color">Color personalizado</string>
|
||||
|
@ -3787,7 +3787,7 @@
|
|||
<string name="lenght_limit_description">Proporcione la longitud de su vehículo, se pueden aplicar algunas restricciones de rutas para vehículos largos.</string>
|
||||
<string name="quick_action_remove_next_destination">Eliminar el punto de destino más cercano</string>
|
||||
<string name="please_provide_point_name_error">Por favor, proporcione un nombre para el punto</string>
|
||||
<string name="quick_action_remove_next_destination_descr">El punto de destino actual de la ruta será borrado. Si se trata del destino, la navegación se detendrá.</string>
|
||||
<string name="quick_action_remove_next_destination_descr">Elimina el próximo destino de su ruta. Si se trata del destino, la navegación se detendrá.</string>
|
||||
<string name="search_download_wikipedia_maps">Descargar mapas de Wikipedia</string>
|
||||
<string name="plan_route_open_existing_track">Abrir la pista existente</string>
|
||||
<string name="plan_route_create_new_route">Crea una nueva ruta</string>
|
||||
|
@ -3802,7 +3802,7 @@
|
|||
<string name="shared_string_file_name">Nombre de archivo</string>
|
||||
<string name="number_of_gpx_files_selected_pattern">%s archivos de traza seleccionados</string>
|
||||
<string name="monitoring_control_start">GRABAR</string>
|
||||
<string name="save_global_track_interval_descr">Especifica el intervalo de grabación general para trazas (habilitado a través del widget de grabación en el mapa).</string>
|
||||
<string name="save_global_track_interval_descr">Especifica el intervalo de grabación general para trazas (activado a través del widget de grabación en el mapa).</string>
|
||||
<string name="gpx_monitoring_stop">Pausar grabación del viaje</string>
|
||||
<string name="gpx_monitoring_start">Seguir grabando el viaje</string>
|
||||
<string name="system_default_theme">Predeterminado del sistema</string>
|
||||
|
@ -3817,7 +3817,7 @@
|
|||
<string name="one_point_error">Añade al menos dos puntos.</string>
|
||||
<string name="select_track_width">Seleccionar anchura</string>
|
||||
<string name="save_track_to_gpx">Grabar automáticamente la traza durante la navegación</string>
|
||||
<string name="plugin_wikipedia_description">Consigue información sobre puntos de interés en Wikipedia. Es tu guía de bolsillo sin conexión. Sólo tienes que activar el complemento de Wikipedia y disfrutar de los artículos sobre los objetos que te rodean.</string>
|
||||
<string name="plugin_wikipedia_description">Consigue información sobre puntos de interés en Wikipedia, una guía de bolsillo sin conexión con artículos sobre lugares y destinos.</string>
|
||||
<string name="add_hidden_group_info">El punto agregado no será visible en el mapa, ya que el grupo seleccionado está oculto, puedes encontrarlo en \"%s\".</string>
|
||||
<string name="app_mode_enduro_motorcycle">Motocicleta de enduro</string>
|
||||
<string name="app_mode_motor_scooter">Moto scooter</string>
|
||||
|
@ -3850,7 +3850,7 @@
|
|||
<string name="navigation_profile">Perfil de navegación</string>
|
||||
<string name="route_between_points_add_track_desc">Selecciona un archivo de traza al que agregar el nuevo segmento.</string>
|
||||
<string name="street_level_imagery">Fotos a pie de calle</string>
|
||||
<string name="plan_route_exit_dialog_descr">¿Estás seguro de que quieres descartar todos los cambios en la ruta planeada cerrándola\?</string>
|
||||
<string name="plan_route_exit_dialog_descr">¿Estás seguro de que quieres descartar todos los cambios en la ruta planeada\?</string>
|
||||
<string name="in_case_of_reverse_direction">En caso de dirección contraria</string>
|
||||
<string name="shared_string_save_as_gpx">Guardar como nuevo archivo de traza</string>
|
||||
<string name="add_segment_to_the_track">Añadir a un archivo de traza</string>
|
||||
|
@ -3877,11 +3877,11 @@
|
|||
<string name="plan_route_trim_before">Recortar antes de</string>
|
||||
<string name="plan_route_trim_after">Recortar después de</string>
|
||||
<string name="plan_route_change_route_type_after">Cambiar el tipo de ruta después de</string>
|
||||
<string name="disable_recording_once_app_killed_descrp">Pausará el registro de trazas cuando se mate la aplicación (a través de aplicaciones recientes). (La indicación OsmAnd de fondo desaparece de la barra de notificaciones de Android.)</string>
|
||||
<string name="disable_recording_once_app_killed_descrp">El registro de trazas se detendrá cuando se mate la aplicación (a través de aplicaciones recientes). (La indicación OsmAnd de fondo desaparece de la barra de notificaciones de Android.)</string>
|
||||
<string name="shared_string_redo">Rehacer</string>
|
||||
<string name="release_3_8">- Función actualizada de Planificar una ruta: permite utilizar diferentes tipos de navegación por segmento y la inclusión de trazas
|
||||
\n
|
||||
\n - Nuevo menú Apariencia para las trazas: selecciona el color, el grosor, muestra las flechas de dirección, los iconos de inicio/fin
|
||||
\n - Nuevo menú Apariencia para las trazas: selecciona el color, el grosor, muestra las flechas de dirección, los iconos de inicio y fin
|
||||
\n
|
||||
\n - Mejorada la visibilidad de los nodos de bicicleta.
|
||||
\n
|
||||
|
@ -3914,9 +3914,9 @@
|
|||
<string name="icon_group_sport">Deporte</string>
|
||||
<string name="icon_group_emergency">Emergencia</string>
|
||||
<string name="icon_group_travel">Viajar</string>
|
||||
<string name="message_you_need_add_two_points_to_show_graphs">Necesita añadir al menos dos puntos</string>
|
||||
<string name="message_you_need_add_two_points_to_show_graphs">Añadir al menos dos puntos</string>
|
||||
<string name="login_account">Cuenta</string>
|
||||
<string name="user_login">Nombre de usuario</string>
|
||||
<string name="user_login">Login</string>
|
||||
<string name="manage_subscription">Gestionar suscripción</string>
|
||||
<string name="send_files_to_openstreetmap">Enviar fichero GPX a OpenStreetMap</string>
|
||||
<string name="enter_text_separated">Introduzca las etiquetas separadas por una coma.</string>
|
||||
|
@ -3935,7 +3935,7 @@
|
|||
<string name="add_photos_descr">OsmAnd muestra fotos de diferentes fuentes:
|
||||
\nOpenPlaceReviews - fotos POI;
|
||||
\nMapillary - imágenes a nivel de calle;
|
||||
\nWeb / Wikimedia - fotos POI especificadas en los datos de OpenStreetMap.</string>
|
||||
\nWeb / Wikimedia - fotos POI según los datos de OpenStreetMap.</string>
|
||||
<string name="shared_string_resources">Recursos</string>
|
||||
<string name="approximate_file_size">Tamaño de fichero aproximado</string>
|
||||
<string name="select_data_to_export">Seleccione los datos para exportar al fichero.</string>
|
||||
|
@ -3943,11 +3943,81 @@
|
|||
<string name="export_not_enough_space">No hay espacio suficiente</string>
|
||||
<string name="release_3_9">• Se ha añadido la opción de exportar e importar todos los datos, incluyendo los ajustes, los recursos y «Mis sitios»
|
||||
\n
|
||||
\n • Planificar ruta: se añadieron gráficos para los segmentos de trazas con la ruta y capacidad de crear o editar trazas de segmentos múltiples
|
||||
\n • Planificar ruta: gráficos para los segmentos de trazas con la ruta y añadio capacidad de crear o editar trazas de segmentos múltiples
|
||||
\n
|
||||
\n • Se ha añadido el método de autenticación OAuth para OpenStreetMap y se ha mejorado la interfaz de usuario de los diálogos de OSM
|
||||
\n
|
||||
\n • Se añadieron colores personalizados para los favoritos y los puntos de referencia de la traza
|
||||
\n • Admite colores personalizados para los favoritos y los puntos de referencia de la traza
|
||||
\n
|
||||
\n</string>
|
||||
<string name="osm_live_payment_desc_hw">La suscripción se cobra por el período elegido. Puedes cancelarlo en AppGallery en cualquier momento.</string>
|
||||
<string name="osm_live_payment_subscription_management_hw">El pago será cargado a la cuenta de AppGallery al confirmar la compra.
|
||||
\n
|
||||
\nLa suscripción se renueva automáticamente a menos que se cancele antes de la fecha de renovación. La cuenta será cargada por el período de renovación (mes/trimestre/año) sólo en la fecha de renovación.
|
||||
\n
|
||||
\nPuedes administrar y cancelar las suscripciones en los ajustes de AppGallery.</string>
|
||||
<string name="use_native_pt">Desarrollo nativo del transporte público</string>
|
||||
<string name="use_native_pt_desc">Cambiar al cálculo de ruta Java (seguro) del transporte público</string>
|
||||
<string name="message_need_calculate_route_before_show_graph">Los datos de %1$s sólo están disponibles con las carreteras, calcula una ruta usando \"Ruta entre puntos\" para ver los gráficos.</string>
|
||||
<string name="app_mode_gap">Separador</string>
|
||||
<string name="gpx_upload_public_visibility_descr">\"Público\" significa que la traza se muestra públicamente en sus trazas de GPS y en listas de trazas de GPS públicas, y en la lista de trazas públicas con marcas de tiempo en forma sin formato. Los datos proporcionados a través de la API no hacen referencia a su página de seguimiento. Las marcas de tiempo de los puntos de seguimiento no están disponibles a través de la API de GPS pública y los puntos de seguimiento no están ordenados cronológicamente.</string>
|
||||
<string name="gpx_upload_private_visibility_descr">\"Privado\" significa que la traza no aparece en ninguna lista pública, pero los puntos de la traza en orden no cronológico están disponibles a través de la API de GPS pública sin marcas de tiempo.</string>
|
||||
<string name="gpx_upload_identifiable_visibility_descr">\"Identificable\" significa que la traza se mostrará públicamente en sus trazas GPS y en listas de trazas GPS públicas, es decir, otros usuarios podrán descargar la traza sin procesar y asociarla con su nombre de usuario. Los datos de puntos de seguimiento públicos con marca de tiempo de la API de GPS que se proporcionan a través de la API de puntos de seguimiento harán referencia a su página de seguimiento original.</string>
|
||||
<string name="gpx_upload_trackable_visibility_descr">\"Rastreable\" significa que el rastreo no aparece en ningún listado público, pero los trackpoints son procesados con marcas de tiempo (que no se pueden asociar con usted directamente) lo hacen mediante descargas de la API de GPS pública.</string>
|
||||
<string name="lang_de_casual">Alemán (casual)</string>
|
||||
<string name="snowmobile_render_descr">Para conducción de motos de nieve con carreteras y pistas exclusivas.</string>
|
||||
<string name="contour_lines_thanks">Gracias por comprar \'Contour lines\'</string>
|
||||
<string name="routing_attr_avoid_footways_description">Evite las aceras</string>
|
||||
<string name="routing_attr_avoid_footways_name">Evite las aceras</string>
|
||||
<string name="use_live_public_transport">Datos OsmAnd Live</string>
|
||||
<string name="use_live_routing">Datos OsmAnd Live</string>
|
||||
<string name="complex_routing_descr">Enrutamiento de dos fases para la navegación del automóvil.</string>
|
||||
<string name="perform_oauth_authorization_description">Inicie sesión con OAuth para usar las funciones de osmedit</string>
|
||||
<string name="perform_oauth_authorization">Iniciar sesión a través de OAuth</string>
|
||||
<string name="clear_osm_token">Borrar token de OpenStreetMap OAuth</string>
|
||||
<string name="osm_edit_logout_success">Desconectado</string>
|
||||
<string name="use_two_phase_routing">Utilice un algoritmo de enrutamiento de 2-fases A *</string>
|
||||
<string name="open_street_map_login_mode">Deberas iniciar sesión para subir cambios nuevos o modificados.
|
||||
\n
|
||||
\nPuede iniciar sesión utilizando el método seguro OAuth o utilizar su nombre de usuario y contraseña.</string>
|
||||
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permitir vías de agua intermitentes</string>
|
||||
<string name="shared_string_graph">Gráfico</string>
|
||||
<string name="message_graph_will_be_available_after_recalculation">Por favor espera.
|
||||
\nEl gráfico estará disponible después del nuevo cálculo de la ruta.</string>
|
||||
<string name="login_open_street_map">Inicie sesión en OpenStreetMap</string>
|
||||
<string name="login_open_street_map_org">Inicie sesión en OpenStreetMap.org</string>
|
||||
<string name="sign_in_with_open_street_map">Iniciar sesión con OpenStreetMap</string>
|
||||
<string name="use_login_password">Usar nombre de usuario y contraseña</string>
|
||||
<string name="subscription_payment_issue_title">Toque el botón para configurar un método de pago en Google Play para corregir su suscripción.</string>
|
||||
<string name="subscription_expired_title">La suscripción a OsmAnd Live ha caducado</string>
|
||||
<string name="subscription_paused_title">La suscripción a OsmAnd Live ha sido pausada</string>
|
||||
<string name="subscription_on_hold_title">La suscripción a OsmAnd Live está en espera</string>
|
||||
<string name="markers_history">Historial de marcadores</string>
|
||||
<string name="osm_login_descr">Puede iniciar sesión utilizando el método seguro OAuth o utilizar su nombre de usuario y contraseña.</string>
|
||||
<string name="register_on_openplacereviews_desc">Las fotos son proporcionadas por el proyecto de datos abiertos OpenPlaceReviews.org. Para cargar sus fotos, debe registrarse en su sitio web.</string>
|
||||
<string name="cannot_upload_image">No se puede cargar la imagen. Vuelve a intentarlo más tarde</string>
|
||||
<string name="select_picture">Seleccionar imagen</string>
|
||||
<string name="export_not_enough_space_descr">Tu dispositivo solo tiene %1$s libres. Libere espacio o anule la selección de algunos elementos para exportar.</string>
|
||||
<string name="select_groups_for_import">Seleccione los grupos que se importarán.</string>
|
||||
<string name="select_items_for_import">Seleccione los elementos que se importarán.</string>
|
||||
<string name="use_dev_url_descr">Cambie para usar dev.openstreetmap.org en lugar de openstreetmap.org para probar la carga de OSM Note / POI / GPX.</string>
|
||||
<string name="use_dev_url">Usar dev.openstreetmap.org</string>
|
||||
<string name="elevation_data">Puede utilizar los datos de elevación para tener en cuenta el ascenso/descenso de su viaje</string>
|
||||
<string name="app_mode_light_aircraft">Aeronave ligera</string>
|
||||
<string name="plan_route_join_segments">Unir segmentos</string>
|
||||
<string name="plan_route_split_before">Dividir antes</string>
|
||||
<string name="plan_route_split_after">Dividir después</string>
|
||||
<string name="plan_route_add_new_segment">Añadir un nuevo segmento</string>
|
||||
<string name="profile_type_osmand_string">Perfil de OsmAnd</string>
|
||||
<string name="profile_type_user_string">Perfil de usuario</string>
|
||||
<string name="reverse_all_points">Invertir todos los puntos</string>
|
||||
<string name="profile_by_default_description">Seleccione el perfil que se utilizará al iniciar la aplicación.</string>
|
||||
<string name="shared_string_last_used">Utilizado por última vez</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_description">Prefiero rutas de senderismo</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_name">Prefiero rutas de senderismo</string>
|
||||
<string name="routing_attr_allow_streams_description">Permitir arroyos y desagües</string>
|
||||
<string name="routing_attr_allow_streams_name">Permitir arroyos y desagües</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permitir vías de agua intermitentes</string>
|
||||
<string name="voice_prompts_timetable">Tiempo de indicaciones por voz</string>
|
||||
</resources>
|
|
@ -3895,4 +3895,9 @@
|
|||
<string name="poi_water_source_tap">Robinet</string>
|
||||
<string name="poi_vaccination_covid19">Vaccination : covid19</string>
|
||||
<string name="poi_health_specialty_vaccination_yes">Vaccination</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Tunnel à chauve-souris</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Pont à chauve-</string>
|
||||
<string name="poi_wildlife_crossing">Passage à faune</string>
|
||||
<string name="poi_swimming_area">Zone de</string>
|
||||
<string name="poi_lavoir">Lavoir</string>
|
||||
</resources>
|
|
@ -3543,18 +3543,18 @@
|
|||
<string name="shared_string_min">Min</string>
|
||||
<string name="n_items_of_z">%1$s de %2$s</string>
|
||||
<string name="shared_string_terrain">Terrain</string>
|
||||
<string name="hillshade_description">Carte ombrée utilisant des nuances sombres pour visualiser les pistes, les sommets et les plaines.</string>
|
||||
<string name="slope_description">La piste est colorée selon sa pente.</string>
|
||||
<string name="hillshade_description">Carte ombrée utilisant des nuances sombres pour visualiser les pentes, les sommets et les plaines.</string>
|
||||
<string name="slope_description">La pente est colorée selon l\'inclinaison du terrain.</string>
|
||||
<string name="terrain_slider_description">Définissez les niveaux de zoom minimum et maximum pour lesquels la couche sera affichée.</string>
|
||||
<string name="hillshade_download_description">Des cartes supplémentaires sont nécessaires pour afficher l\'ombrage du relief sur la carte.</string>
|
||||
<string name="slope_download_description">Des cartes supplémentaires sont nécessaires pour afficher les pistes sur la carte.</string>
|
||||
<string name="slope_read_more">Vous pouvez en apprendre plus sur les pistes dans %1$s.</string>
|
||||
<string name="slope_download_description">Des cartes supplémentaires sont nécessaires pour afficher les pentes sur la carte.</string>
|
||||
<string name="slope_read_more">Vous pouvez en savoir plus sur les pentes dans %1$s.</string>
|
||||
<string name="shared_string_transparency">Transparence</string>
|
||||
<string name="shared_string_zoom_levels">Niveaux de zoom</string>
|
||||
<string name="shared_string_legend">Légende</string>
|
||||
<string name="terrain_empty_state_text">Permet d\'afficher l\'ombrage du relief ou les pistes. Vous pouvez en apprendre plus sur ces types de cartes sur notre site.</string>
|
||||
<string name="terrain_empty_state_text">Active l\'affichage de l\'ombrage du relief et l\'inclinaison. Vous pouvez en savoir plus sur ces types de cartes sur notre site.</string>
|
||||
<string name="shared_string_hillshade">Ombrage du relief</string>
|
||||
<string name="download_slope_maps">Pistes</string>
|
||||
<string name="download_slope_maps">Pentes</string>
|
||||
<string name="quick_action_show_hide_terrain">Affiche ou masque le terrain</string>
|
||||
<string name="quick_action_terrain_hide">Masquer le terrain</string>
|
||||
<string name="quick_action_terrain_show">Afficher le terrain</string>
|
||||
|
@ -4006,4 +4006,17 @@
|
|||
<string name="routing_attr_allow_intermittent_name">Autoriser les voies navigables intermittentes</string>
|
||||
<string name="routing_attr_allow_streams_description">Autoriser les cours d’eau et les drains</string>
|
||||
<string name="routing_attr_allow_streams_name">Autoriser les cours d’eau et les drains</string>
|
||||
<string name="voice_prompts_timetable">Nombre d\'annonces vocales</string>
|
||||
<string name="keep_it_empty_if_not">Si non, laissez vide</string>
|
||||
<string name="shared_string_subtype">Sous-type</string>
|
||||
<string name="shared_string_vehicle">Véhicule</string>
|
||||
<string name="shared_string_api_key">Clé d\'API</string>
|
||||
<string name="shared_string_server_url">URL du serveur</string>
|
||||
<string name="shared_string_enter_param">Saisissez le paramètre</string>
|
||||
<string name="test_route_calculation">Calculer un itinéraire d’essai</string>
|
||||
<string name="routing_engine_vehicle_type_driving">En voiture</string>
|
||||
<string name="routing_engine_vehicle_type_foot">A pieds</string>
|
||||
<string name="routing_engine_vehicle_type_bike">Vélo</string>
|
||||
<string name="routing_engine_vehicle_type_car">Automobile</string>
|
||||
<string name="message_error_recheck_parameters">Erreur, vérifiez les paramètres</string>
|
||||
</resources>
|
|
@ -3891,4 +3891,8 @@
|
|||
<string name="poi_vaccination_covid19">Vacinación: COVID19</string>
|
||||
<string name="poi_health_specialty_vaccination_yes">Vacinación</string>
|
||||
<string name="poi_lifeguard_base">Base de salvavidas</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Túnel para morcegos</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Ponte para morcegos</string>
|
||||
<string name="poi_wildlife_crossing">Paso de fauna</string>
|
||||
<string name="poi_swimming_area">Área de natación</string>
|
||||
</resources>
|
|
@ -3998,7 +3998,7 @@ Lon %2$s</string>
|
|||
<string name="shared_string_add_photo">Engadir imaxe</string>
|
||||
<string name="register_on_openplacereviews">Rexistrarse no
|
||||
\nOpenPlaceReviews.org</string>
|
||||
<string name="register_on_openplacereviews_desc">As imaxes son fornecidas polo proxecto de datos abertos do OpenPlaceReviews.org. Para subir a túas imaxes precisas rexistrarte no sitio web.</string>
|
||||
<string name="register_on_openplacereviews_desc">As imaxes son fornecidas polo proxecto de datos abertos do OpenPlaceReviews.org. Para subir a túas imaxes precisas rexistrarte no seu sitio web.</string>
|
||||
<string name="register_opr_create_new_account">Crear nova conta</string>
|
||||
<string name="register_opr_have_account">Xa teño unha conta</string>
|
||||
<string name="shared_string_search_history">Historial de procura</string>
|
||||
|
@ -4042,4 +4042,12 @@ Lon %2$s</string>
|
|||
\n
|
||||
\n</string>
|
||||
<string name="reverse_all_points">Inverter todos os puntos</string>
|
||||
<string name="profile_by_default_description">Escolle o perfil que será empregado ao iniciar a aplicación.</string>
|
||||
<string name="shared_string_last_used">Usado por última vez</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_description">Preferir rutas de sendeirismo</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_name">Preferir rutas de sendeirismo</string>
|
||||
<string name="routing_attr_allow_streams_description">Permitir regatos e cunetas</string>
|
||||
<string name="routing_attr_allow_streams_name">Permitir regatos e cunetas</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permitir canles de auga intermitentes</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permitir canles de auga intermitentes</string>
|
||||
</resources>
|
|
@ -2176,7 +2176,7 @@
|
|||
<string name="poi_wheelchair_description">Leírás kerekesszékeseknek</string>
|
||||
<string name="poi_blind_description">Leírás vakoknak</string>
|
||||
<string name="poi_highway_steps">Lépcső</string>
|
||||
<string name="poi_handrail_yes">Korlát</string>
|
||||
<string name="poi_handrail_yes">Korlát van</string>
|
||||
<string name="poi_handrail_no">Korlát nincs</string>
|
||||
<string name="poi_ramp_yes">Rámpa</string>
|
||||
<string name="poi_ramp_no">Rámpa nincs</string>
|
||||
|
@ -2832,7 +2832,7 @@
|
|||
<string name="poi_free_flying_hanggliding_yes">Sárkányrepülés</string>
|
||||
<string name="poi_medical_system_ayurveeda_yes">Hagyományos indiai (ájurvéda)</string>
|
||||
<string name="poi_treat_inpatient_yes">Fekvőbeteg-ellátás</string>
|
||||
<string name="poi_emergency_yes">Vészhelyzet</string>
|
||||
<string name="poi_emergency_yes">Sürgősségi ellátás</string>
|
||||
<string name="poi_dispensing_yes">beváltható</string>
|
||||
<string name="poi_hygrometer_yes">Páratartalom-mérő</string>
|
||||
<string name="poi_water_heater_no">Vízforraló nincs</string>
|
||||
|
@ -2865,7 +2865,7 @@
|
|||
<string name="poi_free_flying_no_flight_time">Repüléstilalmi idő (siklórepüléshez)</string>
|
||||
<string name="poi_free_flying_guest_guidelines_yes">Vendégeknek szóló iránymutatás</string>
|
||||
<string name="poi_free_flying_guest_guidelines_no">Vendégeknek szóló iránymutatás nincs</string>
|
||||
<string name="poi_emergency_no">Vészhelyzet nincs</string>
|
||||
<string name="poi_emergency_no">Sürgősségi ellátás nincs</string>
|
||||
<string name="poi_bridge_ref">Híd száma</string>
|
||||
<string name="poi_cafeteria">Menza</string>
|
||||
<string name="poi_forestry_compartment">Útirányjelző tábla: erdőtag (RU)</string>
|
||||
|
@ -3317,7 +3317,7 @@
|
|||
<string name="poi_scooter_yes">Roller</string>
|
||||
<string name="poi_scooter_no">Roller nem</string>
|
||||
<string name="poi_truck_yes">Teherautó</string>
|
||||
<string name="poi_truck_no">Teherautó nem</string>
|
||||
<string name="poi_truck_no">Teherautóval nem használható</string>
|
||||
<string name="poi_parking_fee_yes">Parkolási díj</string>
|
||||
<string name="poi_parking_fee_no">Parkolási díj nincs</string>
|
||||
<string name="poi_parking_fee">Parkolási díj</string>
|
||||
|
@ -3890,4 +3890,8 @@
|
|||
<string name="poi_water_source_tap">Csap</string>
|
||||
<string name="poi_water_source_water_works">Vízmű</string>
|
||||
<string name="poi_water_source_tube_well">Csöves kút</string>
|
||||
<string name="poi_swimming_area">Fürdésre kijelölt terület</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Denevéralagút</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Denevérhíd</string>
|
||||
<string name="poi_wildlife_crossing">Vadátjáró</string>
|
||||
</resources>
|
|
@ -585,7 +585,7 @@
|
|||
<string name="choose_intersected_street">Keresztező utca kijelölése</string>
|
||||
<string name="Closest_Amenities">Legközelebbi hasznos létesítmények</string>
|
||||
<string name="app_mode_default">Térképböngészés</string>
|
||||
<string name="app_mode_car">Vezetés</string>
|
||||
<string name="app_mode_car">Autóvezetés</string>
|
||||
<string name="app_mode_bicycle">Kerékpározás</string>
|
||||
<string name="app_mode_pedestrian">Gyaloglás</string>
|
||||
<string name="position_on_map_center">Középen</string>
|
||||
|
@ -1292,7 +1292,7 @@
|
|||
<string name="speak_poi">Közeli érdekes helyek (POI)</string>
|
||||
<string name="download_additional_maps">Letöltöd a hiányzó térképeket %1$s (%2$d MB)?</string>
|
||||
<string name="rendering_value_browse_map_name">Térképböngészés</string>
|
||||
<string name="rendering_value_car_name">Autó</string>
|
||||
<string name="rendering_value_car_name">Személyautó</string>
|
||||
<string name="rendering_value_bicycle_name">Kerékpár</string>
|
||||
<string name="rendering_value_pedestrian_name">Gyalogos</string>
|
||||
<string name="record_plugin_description">Ez a bővítmény aktiválja a nyomvonalak rögzítésének és mentésének lehetőségét, ha megnyomja a GPX naplózó gombot a térképképernyőn, valamint képes minden navigációs útvonalat automatikusan egy GPX-fájlba naplózni.
|
||||
|
@ -4019,4 +4019,20 @@
|
|||
<string name="routing_attr_allow_streams_name">Patakok és vízelvezető árkok engedélyezése</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Időszakos vízfolyások engedélyezése</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Időszakos vízfolyások engedélyezése</string>
|
||||
<string name="routing_engine_vehicle_type_driving">Autóvezetés</string>
|
||||
<string name="routing_engine_vehicle_type_foot">Gyaloglás</string>
|
||||
<string name="routing_engine_vehicle_type_bike">Kerékpár</string>
|
||||
<string name="routing_engine_vehicle_type_car">Személyautó</string>
|
||||
<string name="voice_prompts_timetable">Hangutasítások ideje</string>
|
||||
<string name="add_online_routing_engine">Online útvonaltervező hozzáadása</string>
|
||||
<string name="edit_online_routing_engine">Online útvonaltervező szerkesztése</string>
|
||||
<string name="shared_string_subtype">Altípus</string>
|
||||
<string name="shared_string_vehicle">Jármű</string>
|
||||
<string name="shared_string_api_key">API-kulcs</string>
|
||||
<string name="shared_string_server_url">Kiszolgáló URL-je</string>
|
||||
<string name="shared_string_enter_param">Paraméter megadása</string>
|
||||
<string name="keep_it_empty_if_not">Hagyja üresen, ha nem</string>
|
||||
<string name="online_routing_example_hint">Az összes paraméterrel rendelkező URL így néz ki:</string>
|
||||
<string name="test_route_calculation">Útvonaltervezés kipróbálása</string>
|
||||
<string name="message_error_recheck_parameters">Hiba, ellenőrizze újra a paramétereket</string>
|
||||
</resources>
|
|
@ -2992,4 +2992,24 @@
|
|||
<string name="poi_traffic_signals_arrow">Freccia</string>
|
||||
<string name="poi_traffic_signals_vibration">Vibrazione</string>
|
||||
<string name="poi_fire_hydrant_pressure_filter">Pressione</string>
|
||||
<string name="poi_vending_elongated_coin">Moneta souvenir</string>
|
||||
<string name="poi_drive_through_no">Drive-through: no</string>
|
||||
<string name="poi_piste_grooming_mogul">Gobba</string>
|
||||
<string name="poi_piste_grooming_backcountry">Fuoripista</string>
|
||||
<string name="poi_piste_difficulty_freeride">Fuoripista</string>
|
||||
<string name="poi_board_type_notice">Bacheca</string>
|
||||
<string name="poi_information_trail_blaze">Segnaletica sentiero</string>
|
||||
<string name="poi_wiki_lang_gu">Wiki gujarati</string>
|
||||
<string name="poi_wiki_lang_yo">Wiki yoruba</string>
|
||||
<string name="poi_wiki_lang_cv">Wiki ciuvascio</string>
|
||||
<string name="poi_wiki_lang_ba">Wiki baschiro</string>
|
||||
<string name="poi_wiki_lang_tg">wiki tagico</string>
|
||||
<string name="poi_wiki_lang_ast">Wiki asturiano-leonese</string>
|
||||
<string name="poi_wiki_lang_ky">Wiki chirghisa</string>
|
||||
<string name="poi_wiki_lang_zhminnan">Wiki min meridionale</string>
|
||||
<string name="poi_wiki_lang_min">Wiki minangkabau</string>
|
||||
<string name="poi_wiki_lang_war">Wiki waray</string>
|
||||
<string name="poi_wiki_lang_mr">Wiki maratino</string>
|
||||
<string name="poi_wiki_lang_ml">Wiki malayalam</string>
|
||||
<string name="poi_wiki_lang_fy">Wiki frisone occidentale</string>
|
||||
</resources>
|
|
@ -3802,7 +3802,7 @@
|
|||
<string name="please_provide_point_name_error">נא לספק שם לנקודה</string>
|
||||
<string name="quick_action_remove_next_destination_descr">מוחק את נקודת היעד הבאה במסלול שלך. אם זו נקודת היעד, הניווט ייפסק.</string>
|
||||
<string name="search_download_wikipedia_maps">הורדת מפות ויקיפדיה</string>
|
||||
<string name="plugin_wikipedia_description">קבלת מידע על נקודות עניין מוויקיפדיה. מדריך הכיס הפרטי שלך - עליך פשוט להפעיל את התוסף של ויקיפדיה וליהנות מערכים על מה שסביבך.</string>
|
||||
<string name="plugin_wikipedia_description">קבלת מידע על נקודות עניין מוויקיפדיה, מדריך הכיס הפרטי שלך עם ערכים על מקומות ויעדים.</string>
|
||||
<string name="app_mode_enduro_motorcycle">אופנוע שטח</string>
|
||||
<string name="app_mode_motor_scooter">טוסטוס</string>
|
||||
<string name="app_mode_wheelchair">כסא גלגלים</string>
|
||||
|
@ -3982,7 +3982,7 @@
|
|||
<string name="shared_string_search_history">היסטוריית חיפוש</string>
|
||||
<string name="app_mode_kayak">קיאק</string>
|
||||
<string name="app_mode_motorboat">סירת מנוע</string>
|
||||
<string name="gpx_upload_identifiable_visibility_descr"/>
|
||||
<string name="gpx_upload_identifiable_visibility_descr">„ניתן לזיהוי” משמעו שהעקבות תופענה באופן ציבורי בעקבות ה־GPS וברישומי עקבות GPS ציבוריים, כלומר שמשתמשים אחרים יוכלו להוריד את העקבות הגולמיים ולשייך אותם עם שם המשתמש שלך. נתוני נקודות מעקב ציבורית עם חתימת זמן מה־API של ה־GPS שמוגשות דרך ה־API של נקודות המעקב יפנו אל עמוד המעקב המקורי שלך.</string>
|
||||
<string name="shared_string_resources">משאבים</string>
|
||||
<string name="approximate_file_size">גודל קובץ משוערך</string>
|
||||
<string name="select_data_to_export">נא לבחור את הנתונים שייוצאו לקובץ.</string>
|
||||
|
@ -4029,4 +4029,22 @@
|
|||
<string name="routing_attr_allow_streams_name">לאפשר נחלים וניקוזים</string>
|
||||
<string name="routing_attr_allow_intermittent_description">לאפשר מקטעים עם דרכי מים עונתיים</string>
|
||||
<string name="routing_attr_allow_intermittent_name">לאפשר מקטעים עם דרכי מים עונתיים</string>
|
||||
<string name="gpx_upload_public_visibility_descr">„ציבורי” משמעו שהעקבות מופיעים באופן ציבורי בעקבות ה־GPS שלך וברישומי עקבות GPS ציבוריים וברישומי מעקב ציבוריים עם חותמות זמן בתצורה גולמית. הנתונים שמוגשים דרך ה־API אינם מפנים אל עמוד העקבות שלך. חותמות הזמן של נקודות המעקב אינן זמינות דרך ה־API של ה־GPS ונקודות המעקב אינן מסודרות בהתאם לזמן שתועדו.</string>
|
||||
<string name="gpx_upload_private_visibility_descr">„פרטי” משמעות שהעקבות לא תופענה ברישומים ציבוריים אך נקודות מעקב ממתוכן תהיינה זמינות בסדר אקראי דרך ה־API הציבורי של ה־GPS ללא חותמות זמן.</string>
|
||||
<string name="voice_prompts_timetable">זמני הכרזות</string>
|
||||
<string name="add_online_routing_engine">הוספת מנוע ניווט מקוון</string>
|
||||
<string name="edit_online_routing_engine">עריכת מנוע הניווט המקוון</string>
|
||||
<string name="shared_string_subtype">תת־סוג</string>
|
||||
<string name="shared_string_vehicle">כלי רכב</string>
|
||||
<string name="shared_string_api_key">מפתח API</string>
|
||||
<string name="shared_string_server_url">כתובת השרת</string>
|
||||
<string name="shared_string_enter_param">נא למלא משתנים</string>
|
||||
<string name="keep_it_empty_if_not">להשאיר ריק אם לא</string>
|
||||
<string name="online_routing_example_hint">כתובת עם כל המשתנים נראית כך:</string>
|
||||
<string name="test_route_calculation">בדיקת חישוב מסלול</string>
|
||||
<string name="routing_engine_vehicle_type_driving">נהיגה</string>
|
||||
<string name="routing_engine_vehicle_type_foot">ברגל</string>
|
||||
<string name="routing_engine_vehicle_type_bike">אופנוע</string>
|
||||
<string name="routing_engine_vehicle_type_car">מכונית</string>
|
||||
<string name="message_error_recheck_parameters">שגיאה, נא לבדוק את המשתנים מחדש</string>
|
||||
</resources>
|
2
OsmAnd/res/values-ka/phrases.xml
Normal file
2
OsmAnd/res/values-ka/phrases.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources></resources>
|
File diff suppressed because it is too large
Load diff
|
@ -3943,4 +3943,7 @@
|
|||
<string name="shared_string_resources">Ressurser</string>
|
||||
<string name="profile_by_default_description">Velg profilen som skal brukes når programmet starter.</string>
|
||||
<string name="shared_string_last_used">Sist brukt</string>
|
||||
<string name="routing_attr_allow_streams_name">Tillat bekker og avløp</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Tillat periodiske vannveier</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Tillat periodiske vannveier</string>
|
||||
</resources>
|
|
@ -3745,8 +3745,8 @@
|
|||
<string name="route_between_points_add_track_desc">Selecteer een track waaraan je een nieuw segment wil toevoegen.</string>
|
||||
<string name="plan_route_select_track_file_for_open">Selecteer een trackbestand om te openen.</string>
|
||||
<string name="plan_route_exit_dialog_descr">Weet u zeker dat u alle wijzigingen in de geplande route wilt annuleren door deze te sluiten\?</string>
|
||||
<string name="plan_route_trim_before">Opsmukken voor</string>
|
||||
<string name="plan_route_trim_after">Opsmukken na</string>
|
||||
<string name="plan_route_trim_before">"Alles wegknippen voor dit punt"</string>
|
||||
<string name="plan_route_trim_after">Alles wegknippen na dit punt</string>
|
||||
<string name="plan_route_change_route_type_before">Wijzig het routetype voor</string>
|
||||
<string name="plan_route_change_route_type_after">Wijzig het routetype na</string>
|
||||
<string name="release_3_8">• Bijgewerkt Plan een route functie: maakt het mogelijk om verschillende navigatietypes per segment te gebruiken en tracks op te nemen
|
||||
|
@ -3925,4 +3925,19 @@
|
|||
<string name="register_on_openplacereviews_desc">Foto\'s zijn afkomstig van het open data-project OpenPlaceReviews.org. Om uw foto\'s te uploaden, moet u zich aanmelden op deze website.</string>
|
||||
<string name="register_opr_create_new_account">Maak een nieuw account aan</string>
|
||||
<string name="register_opr_have_account">Ik heb al een account</string>
|
||||
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>
|
||||
<string name="app_mode_light_aircraft">Licht vliegtuig</string>
|
||||
<string name="plan_route_join_segments">Segmenten samenvoegen</string>
|
||||
<string name="plan_route_split_before">Hiervoor splitsen</string>
|
||||
<string name="plan_route_split_after">Hierna splitsen</string>
|
||||
<string name="plan_route_add_new_segment">Nieuw segment toevoegen</string>
|
||||
<string name="profile_type_osmand_string">OsmAnd-profiel</string>
|
||||
<string name="profile_type_user_string">Gebruikersprofiel</string>
|
||||
<string name="reverse_all_points">Volgorde van alle punten omdraaien</string>
|
||||
<string name="shared_string_last_used">Laatst gebruikt</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_description">Voorkeur voor ongebaande wandelwegen</string>
|
||||
<string name="routing_attr_prefer_hiking_routes_name">Voorkeur voor Hike-routes</string>
|
||||
<string name="routing_attr_allow_streams_description">Beken en sloten gebruiken</string>
|
||||
<string name="routing_attr_allow_streams_name">Beken en sloten gebruiken</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Waterwegen die periodiek water voeren gebruiken</string>
|
||||
</resources>
|
|
@ -194,7 +194,7 @@
|
|||
<string name="poi_fuel_biogas">Biogás</string>
|
||||
<string name="poi_fuel_lh2">Hidrogênio líquido</string>
|
||||
<string name="poi_fuel_electricity">Eletricidade</string>
|
||||
<string name="poi_electricity_combined_charging">Eletroposto</string>
|
||||
<string name="poi_electricity_combined_charging">Eletroposto;Estação de carregamento de veículos elétricos; Estação de carregamento de VE; Ponto de recarga elétrica; Ponto de carga; Estação de recarga eletrônica; Equipamento de abastecimento de veículos elétricos</string>
|
||||
<string name="poi_vehicle_ramp">Rampa de veículo</string>
|
||||
<string name="poi_compressed_air">Ar comprimido</string>
|
||||
<string name="poi_parking">Estacionamento</string>
|
||||
|
@ -3898,4 +3898,8 @@
|
|||
<string name="poi_ranger_station">Posto de guarda florestal</string>
|
||||
<string name="poi_waste_transfer_station">Estação de transferência de resíduos</string>
|
||||
<string name="poi_lavoir">Lavandaria pública</string>
|
||||
<string name="poi_swimming_area">Área de natação</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Túnel para morcego</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Ponte para morcego</string>
|
||||
<string name="poi_wildlife_crossing">Travessia de vida selvagem</string>
|
||||
</resources>
|
|
@ -4022,4 +4022,20 @@
|
|||
<string name="routing_attr_allow_streams_name">Permitir riachos e drenos</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permitir vias de água intermitentes</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permitir vias de água intermitentes</string>
|
||||
<string name="voice_prompts_timetable">Horários de avisos de voz</string>
|
||||
<string name="add_online_routing_engine">Adicionar mecanismo de roteamento online</string>
|
||||
<string name="edit_online_routing_engine">Editar mecanismo de roteamento online</string>
|
||||
<string name="shared_string_subtype">Subtipo</string>
|
||||
<string name="shared_string_vehicle">Veículo</string>
|
||||
<string name="shared_string_api_key">Chave de API</string>
|
||||
<string name="shared_string_server_url">URL do servidor</string>
|
||||
<string name="shared_string_enter_param">Digite o parâmetro</string>
|
||||
<string name="keep_it_empty_if_not">Mantenha-o vazio se não</string>
|
||||
<string name="online_routing_example_hint">O URL com todos os parâmetros terá a seguinte aparência:</string>
|
||||
<string name="test_route_calculation">Cálculo da rota de teste</string>
|
||||
<string name="routing_engine_vehicle_type_driving">Dirigindo</string>
|
||||
<string name="routing_engine_vehicle_type_foot">Pé</string>
|
||||
<string name="routing_engine_vehicle_type_bike">Bicicleta</string>
|
||||
<string name="routing_engine_vehicle_type_car">Carro</string>
|
||||
<string name="message_error_recheck_parameters">Erro, verifique novamente os parâmetros</string>
|
||||
</resources>
|
|
@ -3886,4 +3886,5 @@
|
|||
<string name="poi_lavoir">Умывальник</string>
|
||||
<string name="poi_waste_transfer_station">Станция перекачки отходов</string>
|
||||
<string name="poi_ranger_station">Станция рейнджеров</string>
|
||||
<string name="poi_swimming_area">Место для купания</string>
|
||||
</resources>
|
|
@ -306,7 +306,7 @@
|
|||
<string name="poi_funicular">Funiculare</string>
|
||||
<string name="poi_military_naval_base">Base militare navale</string>
|
||||
<string name="poi_military_barracks">Caserma</string>
|
||||
<string name="poi_electricity_combined_charging">Istatzione de carrigamentu</string>
|
||||
<string name="poi_electricity_combined_charging">Istatzione de carrigamentu;Istatzione de carrigamentu de veìculos elètricos;Istatzione de càrriga elètrica;Puntu de càrriga;Istatzione de càrriga elètrica;Trastes pro s\'alimentatzione de veìculos elètricos</string>
|
||||
<string name="poi_vehicle_ramp">Rampa pro veìculos</string>
|
||||
<string name="poi_compressed_air">Àera cumpressa</string>
|
||||
<string name="poi_bicycle_rental">Nolu bitziclètas</string>
|
||||
|
@ -3894,4 +3894,8 @@
|
|||
<string name="poi_ranger_station">Istatzione de sos rangers</string>
|
||||
<string name="poi_lavoir">Sabunadòrgiu</string>
|
||||
<string name="poi_waste_transfer_station">Istatzione de tramudòngiu de s\'arga</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Gallerias pro tzintzimurreddos</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Pontes pro tzintzimurreddos</string>
|
||||
<string name="poi_wildlife_crossing">Logu de atraessamentu de sa fàuna areste</string>
|
||||
<string name="poi_swimming_area">Logu pro nadare</string>
|
||||
</resources>
|
|
@ -4024,4 +4024,5 @@
|
|||
<string name="routing_attr_allow_streams_name">Permite flussos e iscàrrigos</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Permite caminos de abba intermitentes</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Permite caminos de abba intermitentes</string>
|
||||
<string name="voice_prompts_timetable">Nùmeru de annùntzios vocales</string>
|
||||
</resources>
|
|
@ -4027,4 +4027,5 @@
|
|||
<string name="routing_attr_allow_streams_name">Povoliť potoky a odtokové kanály</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Povoliť dočasné vodné toky</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Povoliť dočasné vodné toky</string>
|
||||
<string name="voice_prompts_timetable">Časy hlasových pokynov</string>
|
||||
</resources>
|
|
@ -294,7 +294,7 @@ Du hittar din parkeringsplats och -tid på instrumentbrädan och i widgeten på
|
|||
<string name="global_app_settings">Globala app-inställningar</string>
|
||||
<string name="user_name">Ditt OSM-användarnamn</string>
|
||||
<string name="open_street_map_login_descr">Behövs för ändringar i openstreetmap.org.</string>
|
||||
<string name="user_password">Ditt OSM-lösenord</string>
|
||||
<string name="user_password">Lösenord</string>
|
||||
<string name="osmand_service">Bakgrundsläge</string>
|
||||
<string name="osmand_service_descr">OsmAnd körs i bakgrunden medan skärmen är avstängd.</string>
|
||||
<string name="download_files_not_enough_space">Det finns inte tillräckligt med ledigt utrymme för att hämta %1$s MB (ledigt: %2$s).</string>
|
||||
|
@ -805,7 +805,7 @@ Nyttjat utrymme är {1} MB.
|
|||
<string name="error_calculating_route_occured">Ett fel uppstod vid ruttberäkningen</string>
|
||||
<string name="empty_route_calculated">Fel: Den beräknade rutten är tom</string>
|
||||
<string name="new_route_calculated_dist">Ny rutt beräknad, avstånd</string>
|
||||
<string name="invalid_locations">Koordinaterna är ogiltiga!</string>
|
||||
<string name="invalid_locations">Ogiltiga koordinater</string>
|
||||
<string name="go_back_to_osmand">Tillbaka till OsmAnd-kartan</string>
|
||||
<string name="previous_run_crashed">Den senaste körningen av OsmAnd kraschade. Loggen finns i {0}. Rapportera felet och bifoga gärna loggfilen.</string>
|
||||
<string name="saving_gpx_tracks">Sparar GPX-spår till SD-kortet …</string>
|
||||
|
@ -857,8 +857,8 @@ Nyttjat utrymme är {1} MB.
|
|||
<string name="navigate_point_latitude">Latitud</string>
|
||||
<string name="navigate_point_longitude">Longitud</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="get_directions">Vägvisning</string>
|
||||
<string name="precise_routing_mode_descr">Aktivera exakt ruttning för beräkning utan småfel. Mycket begränsad av avståndet samt långsam.</string>
|
||||
<string name="route_descr_lat_lon">Lat %1$.3f, long %2$.3f</string>
|
||||
|
@ -902,7 +902,7 @@ Nyttjat utrymme är {1} MB.
|
|||
<string name="street_name">Gatunamn</string>
|
||||
<string name="hno">Husnummer</string>
|
||||
<string name="monitoring_settings_descr">Konfigurera inspelningen av dina resor.</string>
|
||||
<string name="monitoring_settings">Trippinspelning</string>
|
||||
<string name="monitoring_settings">Inspelning av resa</string>
|
||||
<string name="use_kalman_filter_compass_descr">Minskar kompassmissvisningen men blir trögare.</string>
|
||||
<string name="use_kalman_filter_compass">Använd Kalman-filter</string>
|
||||
<string name="choose_osmand_theme">App-tema</string>
|
||||
|
@ -1153,8 +1153,7 @@ Nyttjat utrymme är {1} MB.
|
|||
<string name="sort_by_name">Sortera efter namn</string>
|
||||
<string name="arrival_distance">Ankomstmeddelande</string>
|
||||
<string name="arrival_distance_descr">Hur tidigt vill du höra ankomstmeddelandet?</string>
|
||||
<string name="create_poi_link_to_osm_doc">
|
||||
<u>Online OSM</u>-kartklassificering med bilder.</string>
|
||||
<string name="create_poi_link_to_osm_doc"><u>Online OSM</u>-kartklassificering med bilder.</string>
|
||||
<string name="import_file_favourites">Spara data som GPX-fil eller importera waypoints till \"Favoriter\"?</string>
|
||||
<string name="share_fav_subject">Favoriter utdelade via OsmAnd</string>
|
||||
<string name="commiting_node">Skickar nod…</string>
|
||||
|
@ -1225,7 +1224,7 @@ Nyttjat utrymme är {1} MB.
|
|||
<string name="record_plugin_description">"Denna modul aktiverar funktionen att antingen spela in och spara dina spår genom att du trycker på widgeten GPX-loggning på kartskärmen eller att alla dina rutter sparas automatiskt i en GPX-fil.
|
||||
\n
|
||||
\nInspelade spår kan delas ut till vänner eller användas som bidrag till OSM. Idrottsmän kan använda inspelade spår för att följa sin träning. Viss grundläggande spåranalys kan göras direkt i OsmAnd, såsom varvtider, genomsnittshastighet o.s.v. och spår kan givetvis också analyseras i efterhand i speciella analysverktyg från tredje part. "</string>
|
||||
<string name="record_plugin_name">Inspelning av resor</string>
|
||||
<string name="record_plugin_name">Inspelning av resa</string>
|
||||
<string name="int_hour">h</string>
|
||||
<string name="duration">Längd</string>
|
||||
<string name="distance">Sträcka</string>
|
||||
|
@ -1402,7 +1401,7 @@ Nyttjat utrymme är {1} MB.
|
|||
<string name="shared_string_remember_my_choice">Kom ihåg mitt val</string>
|
||||
<string name="shared_string_refresh">Uppdatera</string>
|
||||
<string name="shared_string_download">Hämta</string>
|
||||
<string name="shared_string_downloading">Laddar ner</string>
|
||||
<string name="shared_string_downloading">Laddar ner…</string>
|
||||
<string name="shared_string_download_successful">Hämtningen lyckades</string>
|
||||
<string name="shared_string_unexpected_error">Ett oväntat fel uppstod</string>
|
||||
<string name="shared_string_action_template">Åtgärd {0}</string>
|
||||
|
@ -1486,7 +1485,7 @@ Long %2$s</string>
|
|||
<string name="routing_attr_avoid_borders_description">Undvik att korsa nationella gränser</string>
|
||||
<string name="routing_attr_height_name">Höjdgräns</string>
|
||||
<string name="use_fast_recalculation">Smart omräkning av rutt</string>
|
||||
<string name="use_fast_recalculation_desc">Räkna om endast början av rutten för långa resor.</string>
|
||||
<string name="use_fast_recalculation_desc">Räkna om endast början av färdvägen, användbart för längre resor.</string>
|
||||
<string name="routing_attr_height_description">Ange tillåten fordonshöjd på rutter.</string>
|
||||
<string name="shared_string_logoff">Logga ut</string>
|
||||
<string name="rendering_value_disabled_name">Inaktiverad</string>
|
||||
|
@ -1616,7 +1615,7 @@ Long %2$s</string>
|
|||
<string name="si_min_km">Minuter per kilometer</string>
|
||||
<string name="si_min_m">Minuter per engelsk mil</string>
|
||||
<string name="si_nm_h">Sjömil i timmen (knop)</string>
|
||||
<string name="shared_string_trip_recording">Trippinspelning</string>
|
||||
<string name="shared_string_trip_recording">Inspelning av resa</string>
|
||||
<string name="shared_string_navigation">Navigering</string>
|
||||
<string name="osmand_running_in_background">Körs i bakgrunden</string>
|
||||
<string name="favorite_category_add_new">Lägg till ny</string>
|
||||
|
@ -1835,7 +1834,8 @@ Tillgängligt utrymme är blott {2} MB.</string>
|
|||
<string name="osm_live_not_active">Inaktiv</string>
|
||||
<string name="osm_live_enter_email">Ange en giltig e-postadress</string>
|
||||
<string name="osm_live_enter_user_name">Ange publikt namn</string>
|
||||
<string name="osm_live_thanks">Tack för att du prenumererar på live-uppdateringar!</string>
|
||||
<string name="osm_live_thanks">Tack för att du stödjer OsmAnd!
|
||||
\nFör att aktivera alla nya funktioner behöver du starta om OsmAnd.</string>
|
||||
<string name="osm_live_region_desc">Delar av din donation kommer att skickas till OSM-användare som skickar in kartändringar i det området.</string>
|
||||
<string name="osm_live_subscription_settings">Prenumerationsinställningar</string>
|
||||
<string name="osm_live_ask_for_purchase">Köp en OsmAnd Live-prenumeration först</string>
|
||||
|
@ -2055,7 +2055,7 @@ Om du tycker om OsmAnd och OSM och vill stödja dem så är detta ett utmärkt s
|
|||
<string name="rendering_value_fine_name">Fin</string>
|
||||
<string name="navigate_point_olc">Öppna platskod</string>
|
||||
<string name="navigate_point_olc_info_invalid">Ogiltig OLC
|
||||
</string>
|
||||
\n</string>
|
||||
<string name="navigate_point_olc_info_short">Kort OLC
|
||||
Vänligen tillhandahåll fullständig kod</string>
|
||||
<string name="file_can_not_be_moved">Filen kan inte flyttas.</string>
|
||||
|
@ -2439,7 +2439,18 @@ Vänligen tillhandahåll fullständig kod</string>
|
|||
<string name="min_max">Min/Max</string>
|
||||
<string name="route_is_too_long_v2">Denna väg kan vara för lång tid att beräkna. Lägg till mellanliggande destinationer om inget resultat finns inom 10 minuter.</string>
|
||||
<string name="osmand_extended_description_part1">"OsmAnd (OSM Automated Navigation Directions) är en kartnavigationsapp med tillgång till gratis, världsomfattande OpenStreetMap (OSM)-data av hög kvalitet. Njut av röstnavigation eller visuell navigation, visning av POI (points of interest - nyttoplatser), att skapa och hantera GPX-spår, visa höjdkurvor och höjdinfo (via plugin), val mellan bil-, cykel-, fotgängar-lägen, OSM-redigering och mycket mer."</string>
|
||||
<string name="osmand_extended_description_part2">GPS-navigering • Du kan välja mellan offline (inga roaming-avgifter när du är utomlands) eller på online(snabbare)-läge • Turn-by-Turn röstguidning leder dig längs vägen (inspelade och genererade röster) • Rutten uppdateras om du avviker från den. • Filval och beräknad ankomsttid hjälper dig längs vägen • För att göra din resa säkrare, dag/natt-läge växlar automatiskt • Du kan välja att visa hastighetsbegränsningar och få påminnelser om du överskrider den • Kartzoomen anpassar sig till din hastighet. • Du kan söka destinationer efter adress eller efter typ (t.ex.: parkering, restaurang, hotell, bensinstation, museum), eller av geografiska koordinater • Stödjer mellanliggande punkter på din rutt • Du kan spela in dina egna eller ladda upp en GPX-spår och följa dem</string>
|
||||
<string name="osmand_extended_description_part2">GPS-navigering
|
||||
\n• Välj mellan offline- (inga roaming-avgifter när du är utomlands) eller online-läge a(snabbare)
|
||||
\n• Steg-för-steg röstguidning leder dig längs vägen (inspelade och genererade röster)
|
||||
\n• Färdvägen uppdateras närhellst du avviker från den.
|
||||
\n• Guidning vid val av filer, gatunamn och beräknad ankomsttid hjälper dig längs vägen
|
||||
\n• Dag-/natt-läge för appen växlas automatiskt för att göra din resa säkrare
|
||||
\n• Visa hastighetsbegränsningar och få påminnelser om du överskrider den
|
||||
\n• Kartzoomen anpassar sig till din hastighet
|
||||
\n• Sök destinationer genom adress, typ (t.ex.: parkering, restaurang, hotell, bensinstation, museum), eller geografiska koordinater
|
||||
\n• Stödjer användande av delmål på din resväg
|
||||
\n• Spela in dina egna, eller ladda upp en GPX-spår och följa dem
|
||||
\n</string>
|
||||
<string name="osmand_extended_description_part3">Karta
|
||||
\n • Visar Poi (point of interests) runt omkring dig
|
||||
\n • Justera kartan baserat på riktning (eller kompass)
|
||||
|
@ -2531,7 +2542,7 @@ Vänligen tillhandahåll fullständig kod</string>
|
|||
<string name="mapnik_render_descr">Gamla \"Mapnik\'-stil standardrendering. Viktiga funktioner: Färger som liknar \"Mapnik\" stil.</string>
|
||||
<string name="touring_view_render_descr">Högsdetaljsstil för turiständamål. Innehåller alla konfigurationsinställningar av standardstilen, dessutom: Visar så mycket detaljer som möjligt, i synnerhet alla vägar, stigar och andra sätt att resa. Tydliga visuella skillnader mellan olika vägtyper som påminner om många turistatlaser. Högkontrastfärger för utomhusbruk, dag- och nattläge.</string>
|
||||
<string name="default_render_descr">Stil för allmänna ändamål. Förenklad återgivning i tätbefolkade städer. Viktiga funktioner: höjdkurvor, rutter, ytkvalitet, tillträdeskontroll, farthinder, stigrendering enligt SAC-skala, vattensporter.</string>
|
||||
<string name="open_wikipedia_link_online">Öppna Wikipedia-länk på nätet</string>
|
||||
<string name="open_wikipedia_link_online">Öppna Wikipedia-länk på internet</string>
|
||||
<string name="open_wikipedia_link_online_description">Länken kommer att öppnas i en webbläsare.</string>
|
||||
<string name="read_wikipedia_offline_description">Skaffa OsmAnd Live-prenumeration för att läsa Wikipedia och Wikivoyage-artiklar frånkopplad.</string>
|
||||
<string name="how_to_open_link">Hur öppnar man länken?</string>
|
||||
|
@ -2601,7 +2612,12 @@ Vänligen tillhandahåll fullständig kod</string>
|
|||
\n• Kompakta offline vektorkartor som uppdateras minst en gång i månaden
|
||||
\n
|
||||
\n• Val mellan data för hela regionen och bara vägnätet (Exempel: Hela Japan är 700 MB eller endast vägnätet för 200 MB)</string>
|
||||
<string name="osmand_plus_extended_description_part5">Säkerhetsfunktioner • Valfri växling mellan dag-/nattläge • Valfri visning av hastighet, med en påminnelse om du överskrider den • Valfri hastighetsbaserad zoomning • Dela din position så att dina vänner kan hitta dig</string>
|
||||
<string name="osmand_plus_extended_description_part5">Säkerhetsfunktioner
|
||||
\n• Valfri växling mellan dag-/nattläge
|
||||
\n• Valfri visning av hastighet, med en påminnelse om du överskrider den
|
||||
\n• Valfri hastighetsbaserad zoomning
|
||||
\n• Dela din position så att dina vänner kan hitta dig
|
||||
\n</string>
|
||||
<string name="osmand_plus_extended_description_part6">Funktioner för cykel och gående • Se vägar för gående och cyklande samt vandringsstigar, utmärkta för utomhusaktiviteter • Speciella ruttval och visningsläge för cykel och gående • Valfria kollektivtrafiksplatser (buss, spårvagn, tåg) inklusive linjenamn • Valfri reseinspelning till lokal GPX-fil eller onlinetjänst • Valfri visning av hastighet och höjd • Visa konturlinjer och höjdreliefer (via separat plugin)</string>
|
||||
<string name="osmand_plus_extended_description_part7">Bidra direkt till OSM
|
||||
\n• Rapportera databuggar
|
||||
|
@ -2933,4 +2949,156 @@ Vänligen tillhandahåll fullständig kod</string>
|
|||
<string name="routing_attr_allow_streams_name">Tillåt strömmar och torrläggningar</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Tillåt vägar över vatten</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Tillåt vägar över vatten</string>
|
||||
<string name="gpx_upload_private_visibility_descr">\"Privat\" betyder att spåret inte visas i några offentliga listor, men spårpunkter från det i okronologisk ordning är tillgängliga via det offentliga GPS-API utan tidsstämplar.</string>
|
||||
<string name="gpx_upload_identifiable_visibility_descr">\"Identifierbart\" betyder att spårningen kommer att visas offentligt i dina GPS-spår och i offentliga GPS-spårningar, dvs. andra användare kommer att kunna komma åt grundata kring spårningen och associera den med ditt användarnamn. Offentliga tidsstämplade tracepoint-data från GPS-API som serveras via trackpoints API refererar till din ursprungliga spårningssida.</string>
|
||||
<string name="gpx_upload_trackable_visibility_descr">\"Spårbar\" betyder att spåret inte visas i några offentliga listor, men bearbetade spårpunkter tillsammans med respektive tidsstämplar (som inte kan kopplas direkt till dig) görs genom nedladdningar från det offentliga GPS-API: et.</string>
|
||||
<string name="osm_edit_close_note">Stäng OSM Anteckningar</string>
|
||||
<string name="osm_edit_comment_note">Kommentera OSM Anteckningar</string>
|
||||
<string name="osm_login_descr">Du kan logga in antingen med OAuth metoden (högre säkerhet) eller genom att använda ditt användarnamn och lösenord.</string>
|
||||
<string name="shared_string_add_photo">Lägg till bild</string>
|
||||
<string name="register_on_openplacereviews">Registrera dig hos
|
||||
\nOpenPlaceReviews.org</string>
|
||||
<string name="register_on_openplacereviews_desc">Bilder tillhandahålls av OpenPlaceReviews.org\'s öppen data projekt. För att kunna ladda upp dina bilder behöver du registrera dig på deras webbsida.</string>
|
||||
<string name="register_opr_create_new_account">Registrera ett nytt konto</string>
|
||||
<string name="register_opr_have_account">Jag har redan ett konto</string>
|
||||
<string name="shared_string_search_history">Sökhistorik</string>
|
||||
<string name="app_mode_kayak">Kajak</string>
|
||||
<string name="app_mode_motorboat">Motorbåt</string>
|
||||
<string name="cannot_upload_image">Uppladdning av bild misslyckades, vänligen försök igen senare</string>
|
||||
<string name="select_picture">Välj bild</string>
|
||||
<string name="shared_string_resources">Resurser</string>
|
||||
<string name="approximate_file_size">Uppskattad filstorlek</string>
|
||||
<string name="select_data_to_export">Vänligen välj vilken data som önskas exporteras till filen.</string>
|
||||
<string name="file_size_needed_for_import">Erfordras för importering</string>
|
||||
<string name="export_not_enough_space_descr">Din enhet har bara %1$s ledigt lagringsutrymme. Vänligen frigör utrymme alternativt avmarkera några föremål som skall exporteras.</string>
|
||||
<string name="export_not_enough_space">Det finns inte tillräckligt med lagringsutrymme</string>
|
||||
<string name="select_items_for_import">Välj vilka föremål som skall importeras.</string>
|
||||
<string name="select_groups_for_import">Välj vilka grupper som skall importeras.</string>
|
||||
<string name="add_to_mapillary">Lägg till Mapillary</string>
|
||||
<string name="add_to_opr">Lägg till ÖppnaPlattsRecensioner (OPR)</string>
|
||||
<string name="use_dev_url_descr">Byt till att använda dev.openstreetmap.org istället för openstreetmap.org för att testa uppladdning av OSM Anteckningar / Sevärdheter / GPX.</string>
|
||||
<string name="use_dev_url">Använd dev.openstreetmap.org</string>
|
||||
<string name="app_mode_light_aircraft">Mindre flyplan</string>
|
||||
<string name="add_photos_descr">OsmAnd visar bilder från flertalet källor:
|
||||
\nOpenPlaceReviews - Foton av sevärdheter;
|
||||
\nMapillary - Bilder på gatunivå;
|
||||
\nWeb/Wikimedia - Foton av sevärdheter enligt OpenStreetMap-data.</string>
|
||||
<string name="elevation_data">Du kan använda höjddata för att ta hänsyn till upp- / nedstigning på din resa</string>
|
||||
<string name="plan_route_join_segments">Sammanslå segment</string>
|
||||
<string name="plan_route_split_before">Dela innan</string>
|
||||
<string name="plan_route_split_after">Dela efter</string>
|
||||
<string name="plan_route_add_new_segment">Lägg till ett nytt segment</string>
|
||||
<string name="profile_type_osmand_string">OsmAnd profil</string>
|
||||
<string name="profile_type_user_string">Användarprofil</string>
|
||||
<string name="clear_confirmation_msg">Rensa %1$s\?</string>
|
||||
<string name="new_plugin_added">Nytt insticksprogram tillagd</string>
|
||||
<string name="shared_string_turn_off">Stäng av</string>
|
||||
<string name="added_profiles_descr">Profiler tillaggda av insticksprogram</string>
|
||||
<string name="added_profiles">Tillagda profiler</string>
|
||||
<string name="suggested_maps_descr">Dessa kartor erfordras av insticksprogrammet.</string>
|
||||
<string name="suggested_maps">Föreslagna kartor</string>
|
||||
<string name="dialogs_and_notifications_descr">Kontrollera vilka popups, dialoger och notifieringar som OsmAnd visar under användning.</string>
|
||||
<string name="dialogs_and_notifications_title">Dialoger och notifieringar</string>
|
||||
<string name="download_map_dialog">Kartnedladdningsdialog</string>
|
||||
<string name="join_segments">Slå ihop segment</string>
|
||||
<string name="rendering_attr_showCycleNodeNetworkRoutes_name">Visa cykelrutter längs nodnätverk</string>
|
||||
<string name="rendering_value_walkingRoutesOSMCNodes_name">Nodnätverk</string>
|
||||
<string name="save_heading">Inkludera rubrik</string>
|
||||
<string name="add_new_profile_q">Lägg till ny profil \'%1$s\'\?</string>
|
||||
<string name="personal_category_name">Personlig</string>
|
||||
<string name="shared_string_downloading_formatted">Laddar ned %s</string>
|
||||
<string name="desert_render_descr">För öknar och andra glesbefolkade områden. Mer detaljerad.</string>
|
||||
<string name="rendering_value_thick_name">Tät</string>
|
||||
<string name="empty_state_my_tracks_desc">Importera eller spela in spårfiler</string>
|
||||
<string name="gpx_monitoring_stop">Pausa inspelning av resa</string>
|
||||
<string name="gpx_monitoring_start">Återuppta inspelning av resa</string>
|
||||
<string name="development">Utveckling</string>
|
||||
<string name="use_live_public_transport">OsmAnd Live data</string>
|
||||
<string name="use_live_routing">OsmAnd Live data</string>
|
||||
<string name="complex_routing_descr">Dirigering i två steg för bilnavigation.</string>
|
||||
<string name="perform_oauth_authorization_description">Logga in med OAuth för att använda OsmEdit funktioner</string>
|
||||
<string name="perform_oauth_authorization">Logga in via OAuth</string>
|
||||
<string name="clear_osm_token">Rensa OpenStreetMap OAuth igenkänningstecken</string>
|
||||
<string name="osm_edit_logout_success">Utloggad</string>
|
||||
<string name="file_already_imported">Filen är redan importerad i OsmAnd</string>
|
||||
<string name="use_two_phase_routing">Använd en 2-fas A* dirigeringsalgoritm</string>
|
||||
<string name="shared_string_graph">Graf</string>
|
||||
<string name="message_need_calculate_route_before_show_graph">%1$s data tillgänglig enbart på vägar, räkna ut en färdväg genom att använda \"Färdväg mellan punkter\" för att se grafer.</string>
|
||||
<string name="message_graph_will_be_available_after_recalculation">Vänligen vänta.
|
||||
\nGrafen kommer bli tillgänglig efter att färdvägen omberäknats.</string>
|
||||
<string name="shared_string_local_maps">Lokala kartor</string>
|
||||
<string name="ltr_or_rtl_combine_via_dash">%1$s — %2$s</string>
|
||||
<string name="ltr_or_rtl_combine_via_star">%1$s * %2$s</string>
|
||||
<string name="icon_group_transport">Kollektivtrafik</string>
|
||||
<string name="app_mode_gap">Tomrum</string>
|
||||
<string name="icon_group_amenity">bekvämligheter</string>
|
||||
<string name="icon_group_special">Speciell</string>
|
||||
<string name="icon_group_symbols">Symboler</string>
|
||||
<string name="icon_group_travel">Resa</string>
|
||||
<string name="message_you_need_add_two_points_to_show_graphs">Lägg till minst 2 punkter</string>
|
||||
<string name="icon_group_sport">Idrott</string>
|
||||
<string name="icon_group_service">Service</string>
|
||||
<string name="icon_group_emergency">Nödsituation</string>
|
||||
<string name="plugin_global_prefs_info">Dessa inställningar för insticksmoduler är globala och appliceras för alla profiler</string>
|
||||
<string name="login_open_street_map">Logga in till OpenStreetMap</string>
|
||||
<string name="login_open_street_map_org">Logga in på OpenStreetMap.org</string>
|
||||
<string name="sign_in_with_open_street_map">Logga in på OpenStreetMap</string>
|
||||
<string name="use_login_password">Användarnamn och lösenord</string>
|
||||
<string name="login_account">Konto</string>
|
||||
<string name="markers_history">Markörhistorik</string>
|
||||
<string name="user_login">Inloggning</string>
|
||||
<string name="manage_subscription">Hantera prenumeration</string>
|
||||
<string name="subscription_payment_issue_title">Klicka på knappen för att registrera en betalningsplan på Google Play för att åtruppta prenumerationen.</string>
|
||||
<string name="subscription_expired_title">Prenumerationen på OsmAnd Live har</string>
|
||||
<string name="subscription_paused_title">Prenumerationen på OsmAnd Live är pausad</string>
|
||||
<string name="subscription_on_hold_title">Prenumerationen på OsmAnd Live är</string>
|
||||
<string name="send_files_to_openstreetmap">Skicka GPX fil till OpenStreetMap</string>
|
||||
<string name="enter_text_separated">Ange taggar sepparerade med komma (,).</string>
|
||||
<string name="select_track_width">Välj bredd</string>
|
||||
<string name="shared_string_custom">Anpassad</string>
|
||||
<string name="gpx_direction_arrows">Dirigeringspilar</string>
|
||||
<string name="plan_route_last_edited">Senast ändrad</string>
|
||||
<string name="shared_string_done">Klar</string>
|
||||
<string name="next_segment">Nästa segment</string>
|
||||
<string name="navigation_profile">Navigationsprofil</string>
|
||||
<string name="street_level_imagery">Bilder på gatunivå</string>
|
||||
<string name="plan_route_exit_dialog_descr">Är du säker på att du vill avfärda alla ändringar i den plannerade färdvägen\?</string>
|
||||
<string name="map_widget_monitoring">Inspelning av resa</string>
|
||||
<string name="follow_track">Följ färdväg</string>
|
||||
<string name="select_another_track">välj en annan färdväg</string>
|
||||
<string name="start_of_the_track">Början på färdvägen</string>
|
||||
<string name="nearest_point">Närmaste punkt</string>
|
||||
<string name="delete_address">Ta bort adress</string>
|
||||
<string name="add_address">Lägg till adress</string>
|
||||
<string name="access_hint_enter_address">Ange adress</string>
|
||||
<string name="plan_route_trim_before">Korta ner innan</string>
|
||||
<string name="plan_route_trim_after">Korta ner efter</string>
|
||||
<string name="plan_route_change_route_type_before">Ändra typ av färdväg innan</string>
|
||||
<string name="plan_route_change_route_type_after">Ändra typ av färdväg efter</string>
|
||||
<string name="simplified_track">Förenklad färdväg</string>
|
||||
<string name="simplified_track_description">Bara färdvägens linje kommer sparas, delmålen tas bort.</string>
|
||||
<string name="number_of_gpx_files_selected_pattern">%s GPX filer valda</string>
|
||||
<string name="shared_string_file_name">Filnamn</string>
|
||||
<string name="monitoring_control_start">Spela in</string>
|
||||
<string name="system_default_theme">Systemstandard</string>
|
||||
<string name="all_next_segments">Alla efterföljande delar</string>
|
||||
<string name="previous_segment">Tidigare delar</string>
|
||||
<string name="all_previous_segments">Alla tidigare delar</string>
|
||||
<string name="only_selected_segment_recalc">Bara valda delar kommer bli omräknad med vald profil.</string>
|
||||
<string name="all_next_segments_will_be_recalc">Alla kommande delar kommer bli omräknad med den valda profilen.</string>
|
||||
<string name="all_previous_segments_will_be_recalc">Alla tidigare delar kommer bli omräknade med den valda profilen.</string>
|
||||
<string name="open_saved_track">Öppna sparad färdväg</string>
|
||||
<string name="shared_string_is_saved">är sparad</string>
|
||||
<string name="shared_string_redo">Upprepa</string>
|
||||
<string name="one_point_error">Vänligen lägg till minst två punkter.</string>
|
||||
<string name="sort_last_modified">Senast ändrad</string>
|
||||
<string name="sort_name_ascending">Namn: A – Ö</string>
|
||||
<string name="sort_name_descending">Namn: Ö – A</string>
|
||||
<string name="start_finish_icons">Ikoner för start och mål</string>
|
||||
<string name="osm_live_payment_desc_hw">Betalningen för prenumerationen är i enlighet med vad som valts. Du kan avbryta den i AppGallery när som hellst.</string>
|
||||
<string name="routing_attr_avoid_footways_description">Undvik resor till fots</string>
|
||||
<string name="routing_attr_avoid_footways_name">Undvik resor till</string>
|
||||
<string name="search_download_wikipedia_maps">Ladda ner Wikipedia kartor</string>
|
||||
<string name="plugin_wikipedia_description">Få information om sevärdheter från Wikipedia, en inbunden samling av offline artiklar om ställen och destinationer.</string>
|
||||
<string name="track_show_start_finish_icons"></string>
|
||||
</resources>
|
|
@ -944,7 +944,7 @@
|
|||
<string name="poi_route_hiking_lwn_poi">Yerel yürüyüş güzergahı</string>
|
||||
<string name="poi_route_hiking_ref_poi">Yürüyüş yolu başvurusu</string>
|
||||
<string name="poi_opening_hours">Çalışma saatleri</string>
|
||||
<string name="poi_collection_times">Koleksiyon kez</string>
|
||||
<string name="poi_collection_times">Toplama zamanları</string>
|
||||
<string name="poi_description">Açıklama</string>
|
||||
<string name="poi_phone">Telefon</string>
|
||||
<string name="poi_website">İnternet sitesi</string>
|
||||
|
@ -3137,4 +3137,12 @@
|
|||
<string name="poi_diplomatic_services_non_immigrant_visas_filter">Göçmen olmayan vizeleri</string>
|
||||
<string name="poi_military_checkpoint">Askeri denetim noktası</string>
|
||||
<string name="poi_checkpoint_hiking">Yürüyüş denetim noktası</string>
|
||||
<string name="poi_street_cabinet_street_lighting">Dolap türü: sokak aydınlatması</string>
|
||||
<string name="poi_street_cabinet_water_management">Dolap türü: su yönetimi</string>
|
||||
<string name="poi_street_cabinet_waste">Dolap türü: atık</string>
|
||||
<string name="poi_street_cabinet_postal_service">Dolap türü: posta hizmeti</string>
|
||||
<string name="poi_street_cabinet_gas">Dolap türü: gaz</string>
|
||||
<string name="poi_street_cabinet_cable_tv">Dolap türü: kablo tv</string>
|
||||
<string name="poi_street_cabinet_telecom">Dolap türü: telefon</string>
|
||||
<string name="poi_street_cabinet_power">Dolap türü: elektrik</string>
|
||||
</resources>
|
|
@ -1701,7 +1701,7 @@
|
|||
<string name="remove_the_tag">Etiketi Kaldır</string>
|
||||
<string name="version_settings_descr">Gecelik derlemeleri indir.</string>
|
||||
<string name="version_settings">kurar</string>
|
||||
<string name="rendering_attr_streetLighting_name">Sokak Aydınlatma</string>
|
||||
<string name="rendering_attr_streetLighting_name">Sokak aydınlatma</string>
|
||||
<string name="proxy_pref_title">Vekil sunucu</string>
|
||||
<string name="proxy_pref_descr">Bir proxy sunucusu belirtin.</string>
|
||||
<string name="settings_privacy">Gizlilik</string>
|
||||
|
@ -3982,4 +3982,20 @@
|
|||
<string name="routing_attr_allow_streams_name">Dere ve kanalizasyonlara izin ver</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Aralıklı su yollarına izin verin</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Aralıklı su yollarına izin ver</string>
|
||||
<string name="voice_prompts_timetable">Sesli uyarı zamanları</string>
|
||||
<string name="add_online_routing_engine">Çevrim içi yönlendirme motoru ekle</string>
|
||||
<string name="edit_online_routing_engine">Çevrim içi yönlendirme motorunu düzenle</string>
|
||||
<string name="shared_string_subtype">Alt tür</string>
|
||||
<string name="shared_string_vehicle">Araç</string>
|
||||
<string name="shared_string_api_key">API anahtarı</string>
|
||||
<string name="shared_string_server_url">Sunucu URL\'si</string>
|
||||
<string name="shared_string_enter_param">Parametre gir</string>
|
||||
<string name="keep_it_empty_if_not">Değilse boş tut</string>
|
||||
<string name="online_routing_example_hint">Tüm parametreleri ile URL şu şekilde görünecektir:</string>
|
||||
<string name="test_route_calculation">Güzergah hesaplamayı test et</string>
|
||||
<string name="routing_engine_vehicle_type_driving">Araba sürme</string>
|
||||
<string name="routing_engine_vehicle_type_foot">Yürüme</string>
|
||||
<string name="routing_engine_vehicle_type_bike">Bisiklet</string>
|
||||
<string name="routing_engine_vehicle_type_car">Araba</string>
|
||||
<string name="message_error_recheck_parameters">Hata, parametreleri tekrar gözden geçirin</string>
|
||||
</resources>
|
|
@ -198,7 +198,7 @@
|
|||
<string name="poi_fuel_e85">85% Етанолу (Е85)</string>
|
||||
<string name="poi_fuel_lh2">Рідкий водень</string>
|
||||
<string name="poi_fuel_electricity">Електроенергія</string>
|
||||
<string name="poi_electricity_combined_charging">Станція зарядки</string>
|
||||
<string name="poi_electricity_combined_charging">Зарядна станція;Зарядна станція для електромобіля;Зарядна станція для електромобілів;точка підзарядки електроенергією;Точка зарядки; Електронна зарядна станція;Обладнання для електромобілів</string>
|
||||
<string name="poi_vehicle_ramp">Рампа для огляду/перевірки машин</string>
|
||||
<string name="poi_compressed_air">Стиснене повітря</string>
|
||||
<string name="poi_parking">Стоянка</string>
|
||||
|
@ -3886,4 +3886,8 @@
|
|||
<string name="poi_weightbridge">Автомобільні ваги</string>
|
||||
<string name="poi_lavoir">Громадська пральня</string>
|
||||
<string name="poi_waste_transfer_station">Станція перевезення відходів</string>
|
||||
<string name="poi_swimming_area">Плавальний майданчик</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Тунель кажанів</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Міст кажанів</string>
|
||||
<string name="poi_wildlife_crossing">Переправа диких тварин</string>
|
||||
</resources>
|
|
@ -4023,4 +4023,20 @@
|
|||
<string name="routing_attr_prefer_hiking_routes_name">Надавати перевагу пішохідним маршрутам</string>
|
||||
<string name="routing_attr_allow_streams_description">Дозволити потоки та стічні канали</string>
|
||||
<string name="routing_attr_allow_streams_name">Дозволити потоки та стічні канали</string>
|
||||
<string name="voice_prompts_timetable">Голосові підказки</string>
|
||||
<string name="add_online_routing_engine">Додати мережний рушій маршрутизації</string>
|
||||
<string name="edit_online_routing_engine">Змінити мережний рушій маршрутизації</string>
|
||||
<string name="shared_string_subtype">Підтип</string>
|
||||
<string name="shared_string_vehicle">Транспортний засіб</string>
|
||||
<string name="shared_string_api_key">Ключ API</string>
|
||||
<string name="shared_string_server_url">URL-адреса сервера</string>
|
||||
<string name="shared_string_enter_param">Введіть параметр</string>
|
||||
<string name="keep_it_empty_if_not">Залиште порожнім, якщо ні</string>
|
||||
<string name="online_routing_example_hint">URL-адреса з усіма параметрами виглядатиме так:</string>
|
||||
<string name="test_route_calculation">Тестове обчислення маршруту</string>
|
||||
<string name="routing_engine_vehicle_type_driving">Водіння</string>
|
||||
<string name="routing_engine_vehicle_type_foot">Пішки</string>
|
||||
<string name="routing_engine_vehicle_type_bike">Велосипед</string>
|
||||
<string name="routing_engine_vehicle_type_car">Автомобіль</string>
|
||||
<string name="message_error_recheck_parameters">Помилка, повторно перевірте параметри</string>
|
||||
</resources>
|
|
@ -3897,4 +3897,8 @@
|
|||
<string name="poi_ranger_station">護林員站</string>
|
||||
<string name="poi_lavoir">公共洗衣區</string>
|
||||
<string name="poi_waste_transfer_station">垃圾站</string>
|
||||
<string name="poi_swimming_area">游泳區</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">蝙蝠隧道</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">蝙蝠橋</string>
|
||||
<string name="poi_wildlife_crossing">野生動物穿越</string>
|
||||
</resources>
|
|
@ -4022,4 +4022,5 @@
|
|||
<string name="routing_attr_allow_streams_name">允許溪流與水溝</string>
|
||||
<string name="routing_attr_allow_intermittent_description">允許間歇水路</string>
|
||||
<string name="routing_attr_allow_intermittent_name">允許間歇水路</string>
|
||||
<string name="voice_prompts_timetable">語音提示時間</string>
|
||||
</resources>
|
|
@ -4328,6 +4328,9 @@
|
|||
|
||||
<string name="poi_swimming_area">Swimming area</string>
|
||||
|
||||
<string name="poi_wildlife_crossing">Wildlife crossing</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Bat bridge</string>
|
||||
<string name="poi_wildlife_crossing_bat_tunnel">Bat tunnel</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -11,7 +11,21 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
|
||||
<string name="message_error_recheck_parameters">Error, recheck parameters</string>
|
||||
<string name="routing_engine_vehicle_type_car">Car</string>
|
||||
<string name="routing_engine_vehicle_type_bike">Bike</string>
|
||||
<string name="routing_engine_vehicle_type_foot">Foot</string>
|
||||
<string name="routing_engine_vehicle_type_driving">Driving</string>
|
||||
<string name="test_route_calculation">Test route calculation</string>
|
||||
<string name="online_routing_example_hint">URL with all parameters will look like this:</string>
|
||||
<string name="keep_it_empty_if_not">Keep it empty if not</string>
|
||||
<string name="shared_string_enter_param">Enter param</string>
|
||||
<string name="shared_string_server_url">Server URL</string>
|
||||
<string name="shared_string_api_key">API key</string>
|
||||
<string name="shared_string_vehicle">Vehicle</string>
|
||||
<string name="shared_string_subtype">Subtype</string>
|
||||
<string name="edit_online_routing_engine">Edit online routing engine</string>
|
||||
<string name="add_online_routing_engine">Add online routing engine</string>
|
||||
<string name="routing_attr_allow_intermittent_name">Allow intermittent water ways</string>
|
||||
<string name="routing_attr_allow_intermittent_description">Allow intermittent water ways</string>
|
||||
<string name="routing_attr_allow_streams_name">Allow streams and drains</string>
|
||||
|
@ -4010,6 +4024,7 @@
|
|||
<string name="routing_attr_difficulty_preference_description">Prefer routes of this difficulty, although routing over harder or easier pistes is still possible if shorter.</string>
|
||||
<string name="routing_attr_freeride_policy_name">Off-piste</string>
|
||||
<string name="routing_attr_freeride_policy_description">\'Freeride\' and \'Off-piste\' are unofficial routes and passages. Typically ungroomed, unmaintained and not checked in the evening. Enter at your own risk.</string>
|
||||
<string name="voice_prompts_timetable">Voice prompts times</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -91,6 +91,12 @@
|
|||
android:layout="@layout/preference_with_descr"
|
||||
android:title="@string/arrival_distance" />
|
||||
|
||||
<Preference
|
||||
android:key="voice_prompts_timetable"
|
||||
android:layout="@layout/preference_with_descr"
|
||||
android:persistent="false"
|
||||
android:title="@string/voice_prompts_timetable" />
|
||||
|
||||
<Preference
|
||||
android:layout="@layout/simple_divider_item"
|
||||
android:selectable="false" />
|
||||
|
|
|
@ -44,6 +44,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
|
|||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||
import net.osmand.plus.monitoring.LiveMonitoringHelper;
|
||||
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
|
||||
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
||||
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
|
||||
import net.osmand.plus.poi.PoiFiltersHelper;
|
||||
import net.osmand.plus.quickaction.QuickActionRegistry;
|
||||
|
@ -467,6 +468,7 @@ public class AppInitializer implements IProgress {
|
|||
app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class);
|
||||
app.quickActionRegistry = startupInit(new QuickActionRegistry(app.getSettings()), QuickActionRegistry.class);
|
||||
app.osmOAuthHelper = startupInit(new OsmOAuthHelper(app), OsmOAuthHelper.class);
|
||||
app.onlineRoutingHelper = startupInit(new OnlineRoutingHelper(app), OnlineRoutingHelper.class);
|
||||
|
||||
initOpeningHoursParser();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDbHelper;
|
|||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||
import net.osmand.plus.measurementtool.MeasurementEditingContext;
|
||||
import net.osmand.plus.monitoring.LiveMonitoringHelper;
|
||||
import net.osmand.plus.onlinerouting.OnlineRoutingHelper;
|
||||
import net.osmand.plus.osmedit.oauth.OsmOAuthHelper;
|
||||
import net.osmand.plus.poi.PoiFiltersHelper;
|
||||
import net.osmand.plus.quickaction.QuickActionRegistry;
|
||||
|
@ -158,6 +159,7 @@ public class OsmandApplication extends MultiDexApplication {
|
|||
QuickActionRegistry quickActionRegistry;
|
||||
OsmOAuthHelper osmOAuthHelper;
|
||||
MeasurementEditingContext measurementEditingContext;
|
||||
OnlineRoutingHelper onlineRoutingHelper;
|
||||
|
||||
private Resources localizedResources;
|
||||
private Map<String, Builder> customRoutingConfigs = new ConcurrentHashMap<>();
|
||||
|
@ -475,6 +477,10 @@ public class OsmandApplication extends MultiDexApplication {
|
|||
this.measurementEditingContext = context;
|
||||
}
|
||||
|
||||
public OnlineRoutingHelper getOnlineRoutingHelper() {
|
||||
return onlineRoutingHelper;
|
||||
}
|
||||
|
||||
public TransportRoutingHelper getTransportRoutingHelper() {
|
||||
return transportRoutingHelper;
|
||||
}
|
||||
|
|
|
@ -519,10 +519,6 @@ public abstract class OsmandPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean destinationReached() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void registerLayerContextMenuActions(OsmandMapTileView mapView, ContextMenuAdapter adapter, MapActivity mapActivity) {
|
||||
}
|
||||
|
||||
|
@ -781,17 +777,6 @@ public abstract class OsmandPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean onDestinationReached() {
|
||||
boolean b = true;
|
||||
for (OsmandPlugin plugin : getEnabledPlugins()) {
|
||||
if (!plugin.destinationReached()) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
public static void createLayers(OsmandMapTileView mapView, MapActivity activity) {
|
||||
for (OsmandPlugin plugin : getEnabledPlugins()) {
|
||||
plugin.registerLayers(activity);
|
||||
|
|
|
@ -43,6 +43,7 @@ import net.osmand.plus.myplaces.TrackPointFragment;
|
|||
import net.osmand.plus.myplaces.TrackSegmentFragment;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -57,18 +58,14 @@ public class TrackActivity extends TabActivity {
|
|||
public static final String OPEN_TRACKS_LIST = "OPEN_TRACKS_LIST";
|
||||
public static final String CURRENT_RECORDING = "CURRENT_RECORDING";
|
||||
public static final String SHOW_TEMPORARILY = "SHOW_TEMPORARILY";
|
||||
protected List<WeakReference<Fragment>> fragList = new ArrayList<>();
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private TrackBitmapDrawer trackBitmapDrawer;
|
||||
|
||||
private File file = null;
|
||||
private GPXFile gpxFile;
|
||||
private GpxDataItem gpxDataItem;
|
||||
private LockableViewPager viewPager;
|
||||
private long modifiedTime = -1;
|
||||
private final List<WeakReference<Fragment>> fragList = new ArrayList<>();
|
||||
|
||||
private List<GpxDisplayGroup> displayGroups;
|
||||
private List<GpxDisplayGroup> originalGroups = new ArrayList<>();
|
||||
private boolean stopped = false;
|
||||
private boolean openPointsTab = false;
|
||||
private boolean openTracksList = false;
|
||||
|
@ -85,14 +82,15 @@ public class TrackActivity extends TabActivity {
|
|||
finish();
|
||||
return;
|
||||
}
|
||||
displayHelper = new TrackDisplayHelper(app);
|
||||
if (intent.hasExtra(TRACK_FILE_NAME)) {
|
||||
file = new File(intent.getStringExtra(TRACK_FILE_NAME));
|
||||
displayHelper.setFile(new File(intent.getStringExtra(TRACK_FILE_NAME)));
|
||||
}
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
if (file != null) {
|
||||
String fn = file.getName().replace(IndexConstants.GPX_FILE_EXT, "").replace("/", " ").replace("_", " ");
|
||||
if (getFile() != null) {
|
||||
String fn = getFile().getName().replace(IndexConstants.GPX_FILE_EXT, "").replace("/", " ").replace("_", " ");
|
||||
actionBar.setTitle(fn);
|
||||
} else {
|
||||
actionBar.setTitle(getString(R.string.shared_string_currently_recording_track));
|
||||
|
@ -109,11 +107,19 @@ public class TrackActivity extends TabActivity {
|
|||
setContentView(R.layout.track_content);
|
||||
}
|
||||
|
||||
public TrackDisplayHelper getDisplayHelper() {
|
||||
return displayHelper;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackBitmapDrawer getTrackBitmapDrawer() {
|
||||
return trackBitmapDrawer;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return displayHelper.getFile();
|
||||
}
|
||||
|
||||
public void addPoint(PointDescription pointDescription) {
|
||||
Intent currentIntent = getIntent();
|
||||
if (currentIntent != null) {
|
||||
|
@ -122,7 +128,7 @@ public class TrackActivity extends TabActivity {
|
|||
final OsmandSettings settings = app.getSettings();
|
||||
GPXFile gpx = getGpx();
|
||||
LatLon location = settings.getLastKnownMapLocation();
|
||||
QuadRect rect = getRect();
|
||||
QuadRect rect = displayHelper.getRect();
|
||||
NewGpxPoint newGpxPoint = new NewGpxPoint(gpx, pointDescription, rect);
|
||||
if (gpx != null && location != null) {
|
||||
settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(),
|
||||
|
@ -152,53 +158,20 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public QuadRect getRect() {
|
||||
if (getGpx() != null) {
|
||||
return getGpx().getRect();
|
||||
} else {
|
||||
return new QuadRect(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setGpxDataItem(GpxDataItem gpxDataItem) {
|
||||
this.gpxDataItem = gpxDataItem;
|
||||
displayHelper.setGpxDataItem(gpxDataItem);
|
||||
}
|
||||
|
||||
protected void setGpx(GPXFile result) {
|
||||
this.gpxFile = result;
|
||||
if (file == null) {
|
||||
this.gpxFile = getMyApplication().getSavingTrackHelper().getCurrentGpx();
|
||||
}
|
||||
displayHelper.setGpx(result);
|
||||
}
|
||||
|
||||
public List<GpxDisplayGroup> getGpxFile(boolean useDisplayGroups) {
|
||||
if (gpxFile == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
if (gpxFile.modifiedTime != modifiedTime) {
|
||||
modifiedTime = gpxFile.modifiedTime;
|
||||
GpxSelectionHelper selectedGpxHelper = ((OsmandApplication) getApplication()).getSelectedGpxHelper();
|
||||
displayGroups = selectedGpxHelper.collectDisplayGroups(gpxFile);
|
||||
originalGroups.clear();
|
||||
for (GpxDisplayGroup g : displayGroups) {
|
||||
originalGroups.add(g.cloneInstance());
|
||||
}
|
||||
if (file != null) {
|
||||
SelectedGpxFile sf = selectedGpxHelper.getSelectedFileByPath(gpxFile.path);
|
||||
if (sf != null && file != null && sf.getDisplayGroups(app) != null) {
|
||||
displayGroups = sf.getDisplayGroups(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useDisplayGroups) {
|
||||
return displayGroups;
|
||||
} else {
|
||||
return originalGroups;
|
||||
}
|
||||
return displayHelper.getGpxFile(useDisplayGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachFragment(Fragment fragment) {
|
||||
public void onAttachFragment(@NonNull Fragment fragment) {
|
||||
fragList.add(new WeakReference<>(fragment));
|
||||
if (trackBitmapDrawer != null && fragment instanceof TrackBitmapDrawerListener) {
|
||||
trackBitmapDrawer.addListener((TrackBitmapDrawerListener) fragment);
|
||||
|
@ -218,7 +191,7 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (viewPager.getCurrentItem() == 1) {
|
||||
outState.putBoolean(OPEN_POINTS_TAB, true);
|
||||
|
@ -266,15 +239,6 @@ public class TrackActivity extends TabActivity {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void updateSplitView() {
|
||||
for (WeakReference<Fragment> f : fragList) {
|
||||
Fragment frag = f.get();
|
||||
if (frag instanceof TrackSegmentFragment) {
|
||||
((TrackSegmentFragment) frag).updateSplitView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateHeader(Fragment sender) {
|
||||
for (WeakReference<Fragment> f : fragList) {
|
||||
Fragment frag = f.get();
|
||||
|
@ -323,23 +287,23 @@ public class TrackActivity extends TabActivity {
|
|||
|
||||
@Nullable
|
||||
public GPXFile getGpx() {
|
||||
return gpxFile;
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GpxDataItem getGpxDataItem() {
|
||||
return gpxDataItem;
|
||||
return displayHelper.getGpxDataItem();
|
||||
}
|
||||
|
||||
private void onGPXFileReady(@Nullable GPXFile gpxFile) {
|
||||
public void onGPXFileReady(@Nullable GPXFile gpxFile) {
|
||||
setGpx(gpxFile);
|
||||
setGpxDataItem(file != null ? app.getGpxDbHelper().getItem(file) : null);
|
||||
setGpxDataItem(getFile() != null ? app.getGpxDbHelper().getItem(getFile()) : null);
|
||||
|
||||
WindowManager mgr = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
|
||||
if (gpxFile != null && mgr != null) {
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
mgr.getDefaultDisplay().getMetrics(dm);
|
||||
trackBitmapDrawer = new TrackBitmapDrawer(app, gpxFile, getGpxDataItem(), getRect(), dm.density, dm.widthPixels, AndroidUtils.dpToPx(app, 152f));
|
||||
trackBitmapDrawer = new TrackBitmapDrawer(app, gpxFile, getGpxDataItem(), displayHelper.getRect(), dm.density, dm.widthPixels, AndroidUtils.dpToPx(app, 152f));
|
||||
}
|
||||
|
||||
for (WeakReference<Fragment> f : fragList) {
|
||||
|
@ -406,23 +370,6 @@ public class TrackActivity extends TabActivity {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean setJoinSegments(boolean joinSegments) {
|
||||
if (gpxDataItem != null) {
|
||||
boolean updated = app.getGpxDbHelper().updateJoinSegments(gpxDataItem, joinSegments);
|
||||
|
||||
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path);
|
||||
if (updated && selectedGpxFile != null) {
|
||||
selectedGpxFile.setJoinSegments(joinSegments);
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isJoinSegments() {
|
||||
return gpxDataItem != null && gpxDataItem.isJoinSegments();
|
||||
}
|
||||
|
||||
private static class GPXFileLoaderTask extends AsyncTask<Void, Void, GPXFile> {
|
||||
|
||||
private OsmandApplication app;
|
||||
|
@ -437,7 +384,7 @@ public class TrackActivity extends TabActivity {
|
|||
GPXFileLoaderTask(@NonNull TrackActivity activity) {
|
||||
this.activityRef = new WeakReference<>(activity);
|
||||
app = activity.getMyApplication();
|
||||
file = activity.file;
|
||||
file = activity.getDisplayHelper().getFile();
|
||||
}
|
||||
|
||||
protected void onPreExecute() {
|
||||
|
@ -486,11 +433,11 @@ public class TrackActivity extends TabActivity {
|
|||
if (activity != null) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(false);
|
||||
if (result != null) {
|
||||
final GpxSelectionHelper helper = app.getSelectedGpxHelper();
|
||||
GpxSelectionHelper helper = app.getSelectedGpxHelper();
|
||||
if (showTemporarily) {
|
||||
helper.selectGpxFile(result, false, false);
|
||||
} else {
|
||||
final SelectedGpxFile selectedGpx = helper.getSelectedFileByPath(result.path);
|
||||
SelectedGpxFile selectedGpx = helper.getSelectedFileByPath(result.path);
|
||||
if (selectedGpx != null && result.error == null) {
|
||||
selectedGpx.setGpxFile(result, app);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
private OnLayoutChangeListener containerLayoutListener;
|
||||
private View topShadow;
|
||||
private ViewGroup topView;
|
||||
private View bottomScrollView;
|
||||
private ViewGroup bottomScrollView;
|
||||
private LinearLayout cardsContainer;
|
||||
private FrameLayout bottomContainer;
|
||||
|
||||
|
@ -259,7 +259,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
|
|||
return bottomContainer;
|
||||
}
|
||||
|
||||
public View getBottomScrollView() {
|
||||
public ViewGroup getBottomScrollView() {
|
||||
return bottomScrollView;
|
||||
}
|
||||
|
||||
|
|
|
@ -576,7 +576,7 @@ public class DownloadIndexesThread {
|
|||
manager.indexVoiceFiles(this);
|
||||
manager.indexFontFiles(this);
|
||||
if (vectorMapsToReindex) {
|
||||
warnings = manager.indexingMaps(this);
|
||||
warnings = manager.indexingMaps(this, filesToReindex);
|
||||
}
|
||||
List<String> wns = manager.indexAdditionalMaps(this);
|
||||
if (wns != null) {
|
||||
|
|
|
@ -102,6 +102,14 @@ public class AndroidUiHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setVisibility(int visibility, View ... views) {
|
||||
for (View view : views) {
|
||||
if (view != null && view.getVisibility() != visibility) {
|
||||
view.setVisibility(visibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isXLargeDevice(@NonNull Activity ctx) {
|
||||
int lt = (ctx.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK);
|
||||
|
|
|
@ -90,7 +90,7 @@ public class IntentHelper {
|
|||
String zoom = data.getQueryParameter("z");
|
||||
int z = settings.getLastKnownMapZoom();
|
||||
if (zoom != null) {
|
||||
z = Integer.parseInt(zoom);
|
||||
z = (int) Double.parseDouble(zoom);
|
||||
}
|
||||
settings.setMapLocationToShow(lt, ln, z, new PointDescription(lt, ln));
|
||||
} catch (NumberFormatException e) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import net.osmand.plus.routing.AlarmInfo;
|
|||
import net.osmand.plus.routing.AlarmInfo.AlarmInfoType;
|
||||
import net.osmand.plus.routing.RouteCalculationResult;
|
||||
import net.osmand.plus.routing.VoiceRouter;
|
||||
import net.osmand.plus.routing.data.AnnounceTimeDistances;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
|
@ -46,6 +47,11 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_LONG_ALARM_ANNOUNCE;
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_LONG_PNT_APPROACH;
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_SHORT_ALARM_ANNOUNCE;
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_SHORT_PNT_APPROACH;
|
||||
|
||||
// import android.widget.Toast;
|
||||
|
||||
/**
|
||||
|
@ -57,10 +63,6 @@ public class WaypointHelper {
|
|||
|
||||
private int searchDeviationRadius = 500;
|
||||
private int poiSearchDeviationRadius = 100;
|
||||
private static final int LONG_ANNOUNCE_RADIUS = 700;
|
||||
private static final int SHORT_ANNOUNCE_RADIUS = 150;
|
||||
private static final int ALARMS_ANNOUNCE_RADIUS = 150;
|
||||
private static final int ALARMS_SHORT_ANNOUNCE_RADIUS = 100;
|
||||
|
||||
// don't annoy users by lots of announcements
|
||||
private static final int APPROACH_POI_LIMIT = 1;
|
||||
|
@ -167,6 +169,7 @@ public class WaypointHelper {
|
|||
list.clear();
|
||||
}
|
||||
LocationPointWrapper found = null;
|
||||
AnnounceTimeDistances atd = getVoiceRouter().getAnnounceTimeDistances();
|
||||
for (int type = 0; type < locationPoints.size(); type++) {
|
||||
if (type == ALARMS || type == TARGETS) {
|
||||
continue;
|
||||
|
@ -178,7 +181,8 @@ public class WaypointHelper {
|
|||
if (lp.get(kIterator).routeIndex < route.getCurrentRoute()) {
|
||||
// skip
|
||||
} else {
|
||||
if (route.getDistanceToPoint(lwp.routeIndex) <= LONG_ANNOUNCE_RADIUS) {
|
||||
if (atd.isTurnStateActive(0,
|
||||
route.getDistanceToPoint(lwp.routeIndex), STATE_LONG_PNT_APPROACH)) {
|
||||
if (found == null || found.routeIndex < lwp.routeIndex) {
|
||||
found = lwp;
|
||||
if (list != null) {
|
||||
|
@ -205,6 +209,7 @@ public class WaypointHelper {
|
|||
AlarmInfo mostImportant = speedAlarm;
|
||||
int value = speedAlarm != null ? speedAlarm.updateDistanceAndGetPriority(0, 0) : Integer.MAX_VALUE;
|
||||
float speed = lastProjection != null && lastProjection.hasSpeed() ? lastProjection.getSpeed() : 0;
|
||||
AnnounceTimeDistances atd = getVoiceRouter().getAnnounceTimeDistances();
|
||||
if (ALARMS < pointsProgress.size()) {
|
||||
int kIterator = pointsProgress.get(ALARMS);
|
||||
List<LocationPointWrapper> lp = locationPoints.get(ALARMS);
|
||||
|
@ -221,7 +226,7 @@ public class WaypointHelper {
|
|||
inf.setFloatValue(route.getDistanceToPoint(inf.getLastLocationIndex()));
|
||||
}
|
||||
int d = route.getDistanceToPoint(inf.getLocationIndex());
|
||||
if (d > LONG_ANNOUNCE_RADIUS) {
|
||||
if (!atd.isTurnStateActive(0, d, STATE_LONG_PNT_APPROACH)) {
|
||||
break;
|
||||
}
|
||||
float time = speed > 0 ? d / speed : Integer.MAX_VALUE;
|
||||
|
@ -371,6 +376,8 @@ public class WaypointHelper {
|
|||
pointsProgress.set(type, kIterator);
|
||||
|
||||
VoiceRouter voiceRouter = getVoiceRouter();
|
||||
AnnounceTimeDistances atd = voiceRouter.getAnnounceTimeDistances();
|
||||
float atdSpeed = atd.getSpeed(lastKnownLocation);
|
||||
while (kIterator < lp.size()) {
|
||||
LocationPointWrapper lwp = lp.get(kIterator);
|
||||
if (type == ALARMS && lwp.routeIndex < currentRoute) {
|
||||
|
@ -378,7 +385,8 @@ public class WaypointHelper {
|
|||
continue;
|
||||
}
|
||||
if (lwp.announce) {
|
||||
if (route.getDistanceToPoint(lwp.routeIndex) > LONG_ANNOUNCE_RADIUS * 2) {
|
||||
if (!atd.isTurnStateActive(atdSpeed,
|
||||
route.getDistanceToPoint(lwp.routeIndex) / 2, STATE_LONG_PNT_APPROACH)) {
|
||||
break;
|
||||
}
|
||||
LocationPoint point = lwp.point;
|
||||
|
@ -386,33 +394,33 @@ public class WaypointHelper {
|
|||
point.getLatitude(), point.getLongitude()) - lwp.getDeviationDistance());
|
||||
Integer state = locationPointsStates.get(point);
|
||||
if (state != null && state == ANNOUNCED_ONCE
|
||||
&& voiceRouter.isDistanceLess(lastKnownLocation.getSpeed(), d1, SHORT_ANNOUNCE_RADIUS)) {
|
||||
&& atd.isTurnStateActive(atdSpeed, d1, STATE_SHORT_PNT_APPROACH)) {
|
||||
locationPointsStates.put(point, ANNOUNCED_DONE);
|
||||
announcePoints.add(lwp);
|
||||
} else if (type != ALARMS && (state == null || state == NOT_ANNOUNCED)
|
||||
&& voiceRouter.isDistanceLess(lastKnownLocation.getSpeed(), d1, LONG_ANNOUNCE_RADIUS)) {
|
||||
&& atd.isTurnStateActive(atdSpeed, d1, STATE_LONG_PNT_APPROACH)) {
|
||||
locationPointsStates.put(point, ANNOUNCED_ONCE);
|
||||
approachPoints.add(lwp);
|
||||
} else if (type == ALARMS && (state == null || state == NOT_ANNOUNCED)) {
|
||||
AlarmInfo alarm = (AlarmInfo) point;
|
||||
AlarmInfoType t = alarm.getType();
|
||||
int announceRadius;
|
||||
boolean filter = false;
|
||||
boolean filterCloseAlarms = false;
|
||||
switch (t) {
|
||||
case TRAFFIC_CALMING:
|
||||
announceRadius = ALARMS_SHORT_ANNOUNCE_RADIUS;
|
||||
filter = true;
|
||||
announceRadius = STATE_SHORT_ALARM_ANNOUNCE;
|
||||
filterCloseAlarms = true;
|
||||
break;
|
||||
default:
|
||||
announceRadius = ALARMS_ANNOUNCE_RADIUS;
|
||||
announceRadius = STATE_LONG_ALARM_ANNOUNCE;
|
||||
break;
|
||||
}
|
||||
boolean proceed = voiceRouter.isDistanceLess(lastKnownLocation.getSpeed(), d1, announceRadius);
|
||||
if (proceed && filter) {
|
||||
boolean proceed = atd.isTurnStateActive(atdSpeed, d1, announceRadius);
|
||||
if (proceed && filterCloseAlarms) {
|
||||
AlarmInfo lastAlarm = lastAnnouncedAlarms.get(t);
|
||||
if (lastAlarm != null) {
|
||||
double dist = MapUtils.getDistance(lastAlarm.getLatitude(), lastAlarm.getLongitude(), alarm.getLatitude(), alarm.getLongitude());
|
||||
if (dist < ALARMS_SHORT_ANNOUNCE_RADIUS) {
|
||||
if (atd.isTurnStateActive(atdSpeed, dist, STATE_SHORT_ALARM_ANNOUNCE)) {
|
||||
locationPointsStates.put(point, ANNOUNCED_DONE);
|
||||
proceed = false;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import net.osmand.plus.GpxSelectionHelper;
|
|||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
|
@ -25,6 +26,7 @@ import net.osmand.plus.mapcontextmenu.builders.SelectedGpxMenuBuilder;
|
|||
import net.osmand.plus.myplaces.SaveCurrentTrackTask;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||
import net.osmand.plus.track.TrackMenuFragment;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -45,15 +47,21 @@ public class SelectedGpxMenuController extends MenuController {
|
|||
leftTitleButtonController = new TitleButtonController() {
|
||||
@Override
|
||||
public void buttonPressed() {
|
||||
Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
|
||||
OsmandApplication app = mapActivity.getMyApplication();
|
||||
SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile();
|
||||
if (selectedGpxFile.isShowCurrentTrack()) {
|
||||
intent.putExtra(TrackActivity.CURRENT_RECORDING, true);
|
||||
if (Version.isDeveloperVersion(app)) {
|
||||
mapActivity.getContextMenu().hide(false);
|
||||
TrackMenuFragment.showInstance(mapActivity, selectedGpxFile.getGpxFile().path, selectedGpxFile.isShowCurrentTrack());
|
||||
} else {
|
||||
intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path);
|
||||
Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
|
||||
if (selectedGpxFile.isShowCurrentTrack()) {
|
||||
intent.putExtra(TrackActivity.CURRENT_RECORDING, true);
|
||||
} else {
|
||||
intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path);
|
||||
}
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
mapActivity.startActivity(intent);
|
||||
}
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
mapActivity.startActivity(intent);
|
||||
}
|
||||
};
|
||||
leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track);
|
||||
|
|
|
@ -67,8 +67,9 @@ public class HorizontalSelectionAdapter extends RecyclerView.Adapter<HorizontalS
|
|||
textView.setPadding(innerPadding, 0, innerPadding, 0);
|
||||
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
||||
if (item.equals(selectedItem) && item.isEnabled()) {
|
||||
AndroidUtils.setBackground(holder.button, app.getUIUtilities().getPaintedIcon(
|
||||
R.drawable.bg_select_icon_group_button, ContextCompat.getColor(app, activeColorResId)));
|
||||
AndroidUtils.setBackground(holder.button, UiUtilities.createTintedDrawable(app,
|
||||
R.drawable.bg_select_icon_group_button,
|
||||
ContextCompat.getColor(app, activeColorResId)));
|
||||
textView.setTextColor(ContextCompat.getColor(app, R.color.color_white));
|
||||
} else {
|
||||
if (!item.isEnabled()) {
|
||||
|
|
|
@ -427,7 +427,7 @@ public class MapMarkersGroupsAdapter extends RecyclerView.Adapter<RecyclerView.V
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mapActivity.getSupportFragmentManager() != null) {
|
||||
WikivoyageArticleDialogFragment.showInstanceByTitle(app, mapActivity.getSupportFragmentManager(), article.getTitle(), article.getLang());
|
||||
WikivoyageArticleDialogFragment.showInstance(app, mapActivity.getSupportFragmentManager(), article.generateIdentifier(), article.getLang());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1211,7 +1211,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
|
|||
SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper()
|
||||
.getSelectedFileByPath(gpxFile.path);
|
||||
boolean showOnMap = selectedGpxFile != null;
|
||||
saveExistingGpx(gpxFile, showOnMap, false, true, FinalSaveAction.SHOW_TOAST);
|
||||
saveExistingGpx(gpxFile, showOnMap, false, true, FinalSaveAction.SHOW_IS_SAVED_FRAGMENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import net.osmand.GPXUtilities.Route;
|
|||
import net.osmand.GPXUtilities.Track;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.GPXUtilities.Metadata;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
|
@ -91,6 +92,10 @@ class SaveGpxRouteAsyncTask extends AsyncTask<Void, Void, Exception> {
|
|||
backupFile = FileUtils.backupFile(app, outFile);
|
||||
String trackName = Algorithms.getFileNameWithoutExtension(outFile);
|
||||
GPXFile gpx = generateGpxFile(measurementLayer, editingCtx, trackName, gpxFile);
|
||||
if (gpxFile.metadata != null) {
|
||||
gpx.metadata = new Metadata();
|
||||
gpx.metadata.getExtensionsToWrite().putAll(gpxFile.metadata.getExtensionsToRead());
|
||||
}
|
||||
if (!gpx.showCurrentTrack) {
|
||||
res = GPXUtilities.writeGpxFile(outFile, gpx);
|
||||
}
|
||||
|
|
88
OsmAnd/src/net/osmand/plus/myplaces/DeletePointsTask.java
Normal file
88
OsmAnd/src/net/osmand/plus/myplaces/DeletePointsTask.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.activities.SavingTrackHelper;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Set;
|
||||
|
||||
class DeletePointsTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private GPXFile gpx;
|
||||
private Set<GpxDisplayItem> selectedItems;
|
||||
private WeakReference<OnPointsDeleteListener> listenerRef;
|
||||
|
||||
DeletePointsTask(OsmandApplication app, GPXFile gpxFile, Set<GpxDisplayItem> selectedItems, OnPointsDeleteListener listener) {
|
||||
this.app = app;
|
||||
this.gpx = gpxFile;
|
||||
this.selectedItems = selectedItems;
|
||||
this.listenerRef = new WeakReference<>(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
OnPointsDeleteListener listener = listenerRef.get();
|
||||
if (listener != null) {
|
||||
listener.onPointsDeletionStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
SavingTrackHelper savingTrackHelper = app.getSavingTrackHelper();
|
||||
if (gpx != null) {
|
||||
for (GpxDisplayItem item : selectedItems) {
|
||||
if (gpx.showCurrentTrack) {
|
||||
savingTrackHelper.deletePointData(item.locationStart);
|
||||
} else {
|
||||
if (item.group.getType() == GpxDisplayItemType.TRACK_POINTS) {
|
||||
gpx.deleteWptPt(item.locationStart);
|
||||
} else if (item.group.getType() == GpxDisplayItemType.TRACK_ROUTE_POINTS) {
|
||||
gpx.deleteRtePt(item.locationStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gpx.showCurrentTrack) {
|
||||
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
|
||||
boolean selected = app.getSelectedGpxHelper().getSelectedFileByPath(gpx.path) != null;
|
||||
if (selected) {
|
||||
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
|
||||
}
|
||||
}
|
||||
syncGpx(gpx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void syncGpx(GPXFile gpxFile) {
|
||||
MapMarkersHelper helper = app.getMapMarkersHelper();
|
||||
MapMarkersGroup group = helper.getMarkersGroup(gpxFile);
|
||||
if (group != null) {
|
||||
helper.runSynchronization(group);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
OnPointsDeleteListener listener = listenerRef.get();
|
||||
if (listener != null) {
|
||||
listener.onPointsDeleted();
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnPointsDeleteListener {
|
||||
void onPointsDeletionStarted();
|
||||
|
||||
void onPointsDeleted();
|
||||
}
|
||||
}
|
695
OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java
Normal file
695
OsmAnd/src/net/osmand/plus/myplaces/GPXItemPagerAdapter.java
Normal file
|
@ -0,0 +1,695 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Matrix;
|
||||
import android.util.SparseArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture;
|
||||
import com.github.mikephil.charting.listener.OnChartGestureListener;
|
||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.GPXUtilities.Track;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.LineGraphType;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip.CustomTabProvider;
|
||||
import net.osmand.plus.views.controls.WrapContentHeightViewPager.ViewAtPositionInterface;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.ALTITUDE;
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SLOPE;
|
||||
import static net.osmand.plus.helpers.GpxUiHelper.LineGraphType.SPEED;
|
||||
|
||||
public class GPXItemPagerAdapter extends PagerAdapter implements CustomTabProvider, ViewAtPositionInterface {
|
||||
|
||||
private OsmandApplication app;
|
||||
private UiUtilities iconsCache;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private Map<GPXTabItemType, List<ILineDataSet>> dataSetsMap = new HashMap<>();
|
||||
|
||||
private WptPt selectedWpt;
|
||||
private TrkSegment segment;
|
||||
private GpxDisplayItem gpxItem;
|
||||
private GPXTabItemType[] tabTypes;
|
||||
|
||||
private PagerSlidingTabStrip tabs;
|
||||
private SparseArray<View> views = new SparseArray<>();
|
||||
private SegmentActionsListener actionsListener;
|
||||
|
||||
private boolean chartClicked;
|
||||
|
||||
|
||||
public GPXItemPagerAdapter(@NonNull PagerSlidingTabStrip tabs,
|
||||
@NonNull GpxDisplayItem gpxItem,
|
||||
@NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener actionsListener) {
|
||||
super();
|
||||
this.tabs = tabs;
|
||||
this.gpxItem = gpxItem;
|
||||
this.displayHelper = displayHelper;
|
||||
this.actionsListener = actionsListener;
|
||||
app = (OsmandApplication) tabs.getContext().getApplicationContext();
|
||||
iconsCache = app.getUIUtilities();
|
||||
fetchTabTypes();
|
||||
}
|
||||
|
||||
private void fetchTabTypes() {
|
||||
List<GPXTabItemType> tabTypeList = new ArrayList<>();
|
||||
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
|
||||
if (gpxItem != null && gpxItem.analysis != null) {
|
||||
if (gpxItem.analysis.hasElevationData) {
|
||||
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
|
||||
}
|
||||
if (gpxItem.analysis.isSpeedSpecified()) {
|
||||
tabTypeList.add(GPXTabItemType.GPX_TAB_ITEM_SPEED);
|
||||
}
|
||||
}
|
||||
tabTypes = tabTypeList.toArray(new GPXTabItemType[0]);
|
||||
}
|
||||
|
||||
private List<ILineDataSet> getDataSets(LineChart chart, GPXTabItemType tabType,
|
||||
LineGraphType firstType, LineGraphType secondType) {
|
||||
List<ILineDataSet> dataSets = dataSetsMap.get(tabType);
|
||||
if (dataSets == null && chart != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
GpxDataItem gpxDataItem = displayHelper.getGpxDataItem();
|
||||
boolean calcWithoutGaps = gpxItem.isGeneralTrack() && gpxDataItem != null && !gpxDataItem.isJoinSegments();
|
||||
dataSets = GpxUiHelper.getDataSets(chart, app, analysis, firstType, secondType, calcWithoutGaps);
|
||||
dataSetsMap.put(tabType, dataSets);
|
||||
}
|
||||
return dataSets;
|
||||
}
|
||||
|
||||
private TrkSegment getTrackSegment(LineChart chart) {
|
||||
if (segment == null) {
|
||||
LineData lineData = chart.getLineData();
|
||||
List<ILineDataSet> ds = lineData != null ? lineData.getDataSets() : null;
|
||||
if (ds != null && ds.size() > 0) {
|
||||
for (GPXUtilities.Track t : gpxItem.group.getGpx().tracks) {
|
||||
for (TrkSegment s : t.segments) {
|
||||
if (s.points.size() > 0 && s.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
||||
segment = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (segment != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return segment;
|
||||
}
|
||||
|
||||
private WptPt getPoint(LineChart chart, float pos) {
|
||||
WptPt wpt = null;
|
||||
LineData lineData = chart.getLineData();
|
||||
List<ILineDataSet> ds = lineData != null ? lineData.getDataSets() : null;
|
||||
if (ds != null && ds.size() > 0) {
|
||||
TrkSegment segment = getTrackSegment(chart);
|
||||
OrderedLineDataSet dataSet = (OrderedLineDataSet) ds.get(0);
|
||||
if (gpxItem.chartAxisType == GPXDataSetAxisType.TIME) {
|
||||
float time = pos * 1000;
|
||||
for (WptPt p : segment.points) {
|
||||
if (p.time - gpxItem.analysis.startTime >= time) {
|
||||
wpt = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float distance = pos * dataSet.getDivX();
|
||||
double totalDistance = 0;
|
||||
for (int i = 0; i < segment.points.size(); i++) {
|
||||
WptPt currentPoint = segment.points.get(i);
|
||||
if (i != 0) {
|
||||
WptPt previousPoint = segment.points.get(i - 1);
|
||||
totalDistance += MapUtils.getDistance(previousPoint.lat, previousPoint.lon, currentPoint.lat, currentPoint.lon);
|
||||
}
|
||||
if (currentPoint.distance >= distance || Math.abs(totalDistance - distance) < 0.1) {
|
||||
wpt = currentPoint;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return wpt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return tabTypes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return tabTypes[position].toHumanString(app);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object instantiateItem(@NonNull ViewGroup container, int position) {
|
||||
GPXTabItemType tabType = tabTypes[position];
|
||||
View view = getViewForTab(container, tabType);
|
||||
GPXFile gpxFile = displayHelper.getGpx();
|
||||
if (gpxFile != null && gpxItem != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
LineChart chart = view.findViewById(R.id.chart);
|
||||
setupChart(view, chart);
|
||||
|
||||
switch (tabType) {
|
||||
case GPX_TAB_ITEM_GENERAL:
|
||||
setupGeneralTab(view, chart, analysis, gpxFile, position);
|
||||
break;
|
||||
case GPX_TAB_ITEM_ALTITUDE:
|
||||
setupAltitudeTab(view, chart, analysis, gpxFile, position);
|
||||
break;
|
||||
case GPX_TAB_ITEM_SPEED:
|
||||
setupSpeedTab(view, chart, analysis, gpxFile, position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
container.addView(view, 0);
|
||||
views.put(position, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
private View getViewForTab(@NonNull ViewGroup container, @NonNull GPXTabItemType tabType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(container.getContext());
|
||||
switch (tabType) {
|
||||
case GPX_TAB_ITEM_ALTITUDE:
|
||||
return inflater.inflate(R.layout.gpx_item_altitude, container, false);
|
||||
case GPX_TAB_ITEM_SPEED:
|
||||
return inflater.inflate(R.layout.gpx_item_speed, container, false);
|
||||
case GPX_TAB_ITEM_GENERAL:
|
||||
default:
|
||||
return inflater.inflate(R.layout.gpx_item_general, container, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupSpeedTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
|
||||
if (analysis != null && analysis.isSpeedSpecified()) {
|
||||
if (analysis.hasSpeedData) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_SPEED, SPEED, null)));
|
||||
updateChart(chart);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
((ImageView) view.findViewById(R.id.average_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_speed));
|
||||
((ImageView) view.findViewById(R.id.max_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_max_speed));
|
||||
((ImageView) view.findViewById(R.id.time_moving_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
|
||||
((ImageView) view.findViewById(R.id.distance_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
|
||||
|
||||
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
|
||||
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
|
||||
|
||||
((TextView) view.findViewById(R.id.average_text)).setText(avg);
|
||||
((TextView) view.findViewById(R.id.max_text)).setText(max);
|
||||
|
||||
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View view = getViewAtPosition(i);
|
||||
updateJoinGapsInfo(view, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
view.findViewById(R.id.average_max).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.time_distance).setVisibility(View.GONE);
|
||||
}
|
||||
updateJoinGapsInfo(view, position);
|
||||
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_SPEED);
|
||||
}
|
||||
});
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
view.findViewById(R.id.split_interval).setVisibility(View.GONE);
|
||||
} else {
|
||||
view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openSplitIntervalScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
ImageView overflowMenu = view.findViewById(R.id.overflow_menu);
|
||||
if (!gpxItem.group.getTrack().generalTrack) {
|
||||
setupOptionsPopupMenu(overflowMenu, false);
|
||||
} else {
|
||||
overflowMenu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupOptionsPopupMenu(ImageView overflowMenu, final boolean confirmDeletion) {
|
||||
overflowMenu.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_overflow_menu_white));
|
||||
overflowMenu.setVisibility(View.VISIBLE);
|
||||
overflowMenu.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
actionsListener.showOptionsPopupMenu(view, getTrkSegment(), confirmDeletion);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupAltitudeTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
|
||||
if (analysis != null) {
|
||||
if (analysis.hasElevationData) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_ALTITUDE, ALTITUDE, SLOPE)));
|
||||
updateChart(chart);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
((ImageView) view.findViewById(R.id.average_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
|
||||
((ImageView) view.findViewById(R.id.range_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_average));
|
||||
((ImageView) view.findViewById(R.id.ascent_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_ascent));
|
||||
((ImageView) view.findViewById(R.id.descent_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_altitude_descent));
|
||||
|
||||
String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app);
|
||||
String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app);
|
||||
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
|
||||
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||
|
||||
((TextView) view.findViewById(R.id.average_text))
|
||||
.setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app));
|
||||
((TextView) view.findViewById(R.id.range_text)).setText(String.format("%s - %s", min, max));
|
||||
((TextView) view.findViewById(R.id.ascent_text)).setText(asc);
|
||||
((TextView) view.findViewById(R.id.descent_text)).setText(desc);
|
||||
|
||||
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View view = getViewAtPosition(i);
|
||||
updateJoinGapsInfo(view, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
view.findViewById(R.id.average_range).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.ascent_descent).setVisibility(View.GONE);
|
||||
}
|
||||
updateJoinGapsInfo(view, position);
|
||||
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_ALTITUDE);
|
||||
}
|
||||
});
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
view.findViewById(R.id.split_interval).setVisibility(View.GONE);
|
||||
} else {
|
||||
view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openSplitIntervalScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
ImageView overflowMenu = view.findViewById(R.id.overflow_menu);
|
||||
if (!gpxItem.group.getTrack().generalTrack) {
|
||||
setupOptionsPopupMenu(overflowMenu, false);
|
||||
} else {
|
||||
overflowMenu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupGeneralTab(View view, LineChart chart, GPXTrackAnalysis analysis, GPXFile gpxFile, int position) {
|
||||
if (analysis != null) {
|
||||
if (analysis.hasElevationData || analysis.hasSpeedData) {
|
||||
GpxUiHelper.setupGPXChart(app, chart, 4);
|
||||
chart.setData(new LineData(getDataSets(chart, GPXTabItemType.GPX_TAB_ITEM_GENERAL, ALTITUDE, SPEED)));
|
||||
updateChart(chart);
|
||||
chart.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
((ImageView) view.findViewById(R.id.distance_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_polygom_dark));
|
||||
((ImageView) view.findViewById(R.id.duration_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_span));
|
||||
((ImageView) view.findViewById(R.id.start_time_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_start));
|
||||
((ImageView) view.findViewById(R.id.end_time_icon))
|
||||
.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_time_end));
|
||||
|
||||
view.findViewById(R.id.gpx_join_gaps_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (displayHelper.setJoinSegments(!displayHelper.isJoinSegments())) {
|
||||
actionsListener.updateContent();
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View view = getViewAtPosition(i);
|
||||
updateJoinGapsInfo(view, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (analysis.timeSpan > 0) {
|
||||
DateFormat tf = SimpleDateFormat.getTimeInstance(DateFormat.SHORT);
|
||||
DateFormat df = SimpleDateFormat.getDateInstance(DateFormat.MEDIUM);
|
||||
|
||||
Date start = new Date(analysis.startTime);
|
||||
((TextView) view.findViewById(R.id.start_time_text)).setText(tf.format(start));
|
||||
((TextView) view.findViewById(R.id.start_date_text)).setText(df.format(start));
|
||||
Date end = new Date(analysis.endTime);
|
||||
((TextView) view.findViewById(R.id.end_time_text)).setText(tf.format(end));
|
||||
((TextView) view.findViewById(R.id.end_date_text)).setText(df.format(end));
|
||||
} else {
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
chart.setVisibility(View.GONE);
|
||||
view.findViewById(R.id.distance_time_span).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.list_divider).setVisibility(View.GONE);
|
||||
view.findViewById(R.id.start_end_time).setVisibility(View.GONE);
|
||||
}
|
||||
updateJoinGapsInfo(view, position);
|
||||
view.findViewById(R.id.analyze_on_map).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
openAnalyzeOnMap(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
|
||||
}
|
||||
});
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
view.findViewById(R.id.split_interval).setVisibility(View.GONE);
|
||||
} else {
|
||||
view.findViewById(R.id.split_interval).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
openSplitIntervalScreen();
|
||||
}
|
||||
});
|
||||
}
|
||||
ImageView overflowMenu = view.findViewById(R.id.overflow_menu);
|
||||
if (!gpxItem.group.getTrack().generalTrack) {
|
||||
setupOptionsPopupMenu(overflowMenu, true);
|
||||
} else {
|
||||
overflowMenu.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupChart(final View view, final LineChart chart) {
|
||||
chart.setHighlightPerDragEnabled(chartClicked);
|
||||
chart.setOnClickListener(new View.OnClickListener() {
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (!chartClicked) {
|
||||
chartClicked = true;
|
||||
if (selectedWpt != null) {
|
||||
actionsListener.onPointSelected(selectedWpt.lat, selectedWpt.lon);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
chart.setOnTouchListener(new View.OnTouchListener() {
|
||||
|
||||
private float listViewYPos;
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (chartClicked) {
|
||||
actionsListener.onChartTouch();
|
||||
if (!chart.isHighlightPerDragEnabled()) {
|
||||
chart.setHighlightPerDragEnabled(true);
|
||||
}
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
listViewYPos = event.getRawY();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
actionsListener.scrollBy(Math.round(listViewYPos - event.getRawY()));
|
||||
listViewYPos = event.getRawY();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
|
||||
@Override
|
||||
public void onValueSelected(Entry e, Highlight h) {
|
||||
WptPt wpt = getPoint(chart, h.getX());
|
||||
selectedWpt = wpt;
|
||||
if (chartClicked && wpt != null) {
|
||||
actionsListener.onPointSelected(wpt.lat, wpt.lon);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected() {
|
||||
|
||||
}
|
||||
});
|
||||
chart.setOnChartGestureListener(new OnChartGestureListener() {
|
||||
|
||||
float highlightDrawX = -1;
|
||||
|
||||
@Override
|
||||
public void onChartGestureStart(MotionEvent me, ChartGesture lastPerformedGesture) {
|
||||
if (chart.getHighlighted() != null && chart.getHighlighted().length > 0) {
|
||||
highlightDrawX = chart.getHighlighted()[0].getDrawX();
|
||||
} else {
|
||||
highlightDrawX = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartGestureEnd(MotionEvent me, ChartGesture lastPerformedGesture) {
|
||||
gpxItem.chartMatrix = new Matrix(chart.getViewPortHandler().getMatrixTouch());
|
||||
Highlight[] highlights = chart.getHighlighted();
|
||||
if (highlights != null && highlights.length > 0) {
|
||||
gpxItem.chartHighlightPos = highlights[0].getX();
|
||||
} else {
|
||||
gpxItem.chartHighlightPos = -1;
|
||||
}
|
||||
if (chartClicked) {
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
View v = getViewAtPosition(i);
|
||||
if (v != view) {
|
||||
updateChart(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartLongPressed(MotionEvent me) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartDoubleTapped(MotionEvent me) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartSingleTapped(MotionEvent me) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartScale(MotionEvent me, float scaleX, float scaleY) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChartTranslate(MotionEvent me, float dX, float dY) {
|
||||
if (chartClicked && highlightDrawX != -1) {
|
||||
Highlight h = chart.getHighlightByTouchPoint(highlightDrawX, 0f);
|
||||
if (h != null) {
|
||||
chart.highlightValue(h);
|
||||
WptPt wpt = getPoint(chart, h.getX());
|
||||
if (wpt != null) {
|
||||
actionsListener.onPointSelected(wpt.lat, wpt.lon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(@NonNull ViewGroup collection, int position, @NonNull Object view) {
|
||||
views.remove(position);
|
||||
collection.removeView((View) view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
|
||||
return view == object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getCustomTabView(@NonNull ViewGroup parent, int position) {
|
||||
View tab = LayoutInflater.from(parent.getContext()).inflate(R.layout.gpx_tab, parent, false);
|
||||
tab.setTag(tabTypes[position].name());
|
||||
deselect(tab);
|
||||
return tab;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void select(View tab) {
|
||||
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
|
||||
ImageView img = tab.findViewById(R.id.tab_image);
|
||||
switch (tabs.getTabSelectionType()) {
|
||||
case ALPHA:
|
||||
img.setAlpha(tabs.getTabTextSelectedAlpha());
|
||||
break;
|
||||
case SOLID_COLOR:
|
||||
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTextColor()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deselect(View tab) {
|
||||
GPXTabItemType tabType = GPXTabItemType.valueOf((String) tab.getTag());
|
||||
ImageView img = tab.findViewById(R.id.tab_image);
|
||||
switch (tabs.getTabSelectionType()) {
|
||||
case ALPHA:
|
||||
img.setAlpha(tabs.getTabTextAlpha());
|
||||
break;
|
||||
case SOLID_COLOR:
|
||||
img.setImageDrawable(iconsCache.getPaintedIcon(tabType.getIconId(), tabs.getTabInactiveTextColor()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getViewAtPosition(int position) {
|
||||
return views.get(position);
|
||||
}
|
||||
|
||||
void updateChart(int position) {
|
||||
View view = getViewAtPosition(position);
|
||||
if (view != null) {
|
||||
updateChart((LineChart) view.findViewById(R.id.chart));
|
||||
}
|
||||
}
|
||||
|
||||
void updateJoinGapsInfo(View view, int position) {
|
||||
if (view != null) {
|
||||
GPXTrackAnalysis analysis = gpxItem.analysis;
|
||||
GPXTabItemType tabType = tabTypes[position];
|
||||
boolean visible = gpxItem.isGeneralTrack() && analysis != null && tabType.equals(GPXTabItemType.GPX_TAB_ITEM_GENERAL);
|
||||
AndroidUiHelper.updateVisibility(view.findViewById(R.id.gpx_join_gaps_container), visible);
|
||||
boolean joinSegments = displayHelper.isJoinSegments();
|
||||
((SwitchCompat) view.findViewById(R.id.gpx_join_gaps_switch)).setChecked(joinSegments);
|
||||
if (analysis != null) {
|
||||
if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_GENERAL)) {
|
||||
float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
|
||||
float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
|
||||
|
||||
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistance, app));
|
||||
((TextView) view.findViewById(R.id.duration_text)).setText(Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()));
|
||||
} else if (tabType.equals(GPXTabItemType.GPX_TAB_ITEM_SPEED)) {
|
||||
long timeMoving = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeMovingWithoutGaps : analysis.timeMoving;
|
||||
float totalDistanceMoving = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceMovingWithoutGaps : analysis.totalDistanceMoving;
|
||||
|
||||
((TextView) view.findViewById(R.id.time_moving_text)).setText(Algorithms.formatDuration((int) (timeMoving / 1000), app.accessibilityEnabled()));
|
||||
((TextView) view.findViewById(R.id.distance_text)).setText(OsmAndFormatter.getFormattedDistance(totalDistanceMoving, app));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateChart(LineChart chart) {
|
||||
if (chart != null && !chart.isEmpty()) {
|
||||
if (gpxItem.chartMatrix != null) {
|
||||
chart.getViewPortHandler().refresh(new Matrix(gpxItem.chartMatrix), chart, true);
|
||||
}
|
||||
if (gpxItem.chartHighlightPos != -1) {
|
||||
chart.highlightValue(gpxItem.chartHighlightPos, 0);
|
||||
} else {
|
||||
chart.highlightValue(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TrkSegment getTrkSegment() {
|
||||
for (Track track : gpxItem.group.getGpx().tracks) {
|
||||
if (!track.generalTrack && !gpxItem.isGeneralTrack() || track.generalTrack && gpxItem.isGeneralTrack()) {
|
||||
for (TrkSegment segment : track.segments) {
|
||||
if (segment.points.size() > 0 && segment.points.get(0).equals(gpxItem.analysis.locationStart)) {
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void openAnalyzeOnMap(GPXTabItemType tabType) {
|
||||
List<ILineDataSet> ds = getDataSets(null, tabType, null, null);
|
||||
actionsListener.openAnalyzeOnMap(gpxItem, ds, tabType);
|
||||
}
|
||||
|
||||
private void openSplitIntervalScreen() {
|
||||
actionsListener.openSplitInterval(gpxItem, getTrkSegment());
|
||||
}
|
||||
}
|
32
OsmAnd/src/net/osmand/plus/myplaces/GPXTabItemType.java
Normal file
32
OsmAnd/src/net/osmand/plus/myplaces/GPXTabItemType.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
|
||||
public enum GPXTabItemType {
|
||||
|
||||
GPX_TAB_ITEM_GENERAL(R.string.shared_string_overview, R.drawable.ic_action_polygom_dark),
|
||||
GPX_TAB_ITEM_ALTITUDE(R.string.altitude, R.drawable.ic_action_altitude_average),
|
||||
GPX_TAB_ITEM_SPEED(R.string.map_widget_speed, R.drawable.ic_action_speed);
|
||||
|
||||
private final int iconId;
|
||||
private final int titleId;
|
||||
|
||||
GPXTabItemType(@StringRes int titleId, @DrawableRes int iconId) {
|
||||
this.iconId = iconId;
|
||||
this.titleId = titleId;
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public String toHumanString(Context ctx) {
|
||||
return ctx.getString(titleId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SegmentActionsListener {
|
||||
|
||||
void updateContent();
|
||||
|
||||
void onChartTouch();
|
||||
|
||||
void scrollBy(int px);
|
||||
|
||||
void onPointSelected(double lat, double lon);
|
||||
|
||||
void openSplitInterval(GpxDisplayItem gpxItem, TrkSegment trkSegment);
|
||||
|
||||
void showOptionsPopupMenu(View view, TrkSegment trkSegment, boolean confirmDeletion);
|
||||
|
||||
void openAnalyzeOnMap(GpxDisplayItem gpxItem, List<ILineDataSet> dataSets, GPXTabItemType tabType);
|
||||
}
|
91
OsmAnd/src/net/osmand/plus/myplaces/SegmentGPXAdapter.java
Normal file
91
OsmAnd/src/net/osmand/plus/myplaces/SegmentGPXAdapter.java
Normal file
|
@ -0,0 +1,91 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.plus.views.controls.WrapContentHeightViewPager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SegmentGPXAdapter extends ArrayAdapter<GpxDisplayItem> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
private SegmentActionsListener listener;
|
||||
private boolean nightMode;
|
||||
|
||||
public SegmentGPXAdapter(@NonNull Context context, @NonNull List<GpxDisplayItem> items,
|
||||
@NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener listener,
|
||||
boolean nightMode) {
|
||||
super(context, R.layout.gpx_list_item_tab_content, items);
|
||||
this.app = (OsmandApplication) context.getApplicationContext();
|
||||
this.displayHelper = displayHelper;
|
||||
this.listener = listener;
|
||||
this.nightMode = nightMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
View row = convertView;
|
||||
boolean create = false;
|
||||
if (row == null) {
|
||||
create = true;
|
||||
row = createGpxTabsView(displayHelper, parent, listener, nightMode);
|
||||
}
|
||||
GpxDisplayItem item = getItem(position);
|
||||
if (item != null) {
|
||||
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
|
||||
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
|
||||
|
||||
pager.setAdapter(new GPXItemPagerAdapter(tabLayout, item, displayHelper, listener));
|
||||
if (create) {
|
||||
tabLayout.setViewPager(pager);
|
||||
} else {
|
||||
tabLayout.notifyDataSetChanged(true);
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
public static View createGpxTabsView(TrackDisplayHelper displayHelper, ViewGroup root,
|
||||
SegmentActionsListener listener, boolean nightMode) {
|
||||
Context context = root.getContext();
|
||||
View row = UiUtilities.getInflater(context, nightMode).inflate(R.layout.gpx_list_item_tab_content, root, false);
|
||||
|
||||
PagerSlidingTabStrip tabLayout = row.findViewById(R.id.sliding_tabs);
|
||||
tabLayout.setTabBackground(R.color.color_transparent);
|
||||
tabLayout.setIndicatorColorResource(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
|
||||
tabLayout.setIndicatorBgColorResource(nightMode ? R.color.divider_color_dark : R.color.divider_color_light);
|
||||
tabLayout.setIndicatorHeight(AndroidUtils.dpToPx(context, 1f));
|
||||
if (!nightMode) {
|
||||
tabLayout.setTextColor(tabLayout.getIndicatorColor());
|
||||
tabLayout.setTabInactiveTextColor(ContextCompat.getColor(row.getContext(), R.color.text_color_secondary_light));
|
||||
}
|
||||
tabLayout.setTextSize(AndroidUtils.spToPx(context, 12f));
|
||||
tabLayout.setShouldExpand(true);
|
||||
WrapContentHeightViewPager pager = row.findViewById(R.id.pager);
|
||||
pager.setSwipeable(false);
|
||||
pager.setOffscreenPageLimit(2);
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package net.osmand.plus.myplaces;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
|
@ -24,14 +23,18 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.ListPopupWindow;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.GPXUtilities.TrkSegment;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
|
@ -40,8 +43,8 @@ import net.osmand.plus.OsmAndFormatter;
|
|||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
@ -55,7 +58,9 @@ import gnu.trove.list.array.TIntArrayList;
|
|||
public class SplitSegmentDialogFragment extends DialogFragment {
|
||||
|
||||
public final static String TAG = "SPLIT_SEGMENT_DIALOG_FRAGMENT";
|
||||
|
||||
private OsmandApplication app;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private SplitSegmentsAdapter adapter;
|
||||
private View headerView;
|
||||
|
@ -79,8 +84,8 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
app = trackActivity.getMyApplication();
|
||||
FragmentActivity activity = requireActivity();
|
||||
app = (OsmandApplication) activity.getApplication();
|
||||
ic = app.getUIUtilities();
|
||||
boolean isLightTheme = app.getSettings().isLightContent();
|
||||
int themeId = isLightTheme ? R.style.OsmandLightTheme : R.style.OsmandDarkTheme;
|
||||
|
@ -90,9 +95,8 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
listView.setBackgroundColor(getResources().getColor(
|
||||
trackActivity.getMyApplication().getSettings().isLightContent() ? R.color.activity_background_color_light
|
||||
app.getSettings().isLightContent() ? R.color.activity_background_color_light
|
||||
: R.color.activity_background_color_dark));
|
||||
}
|
||||
|
||||
|
@ -104,7 +108,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
minMaxSpeedPaint.setStyle(Paint.Style.FILL);
|
||||
minMaxSpeedTextBounds = new Rect();
|
||||
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
AppCompatActivity trackActivity = (AppCompatActivity) getActivity();
|
||||
final View view = trackActivity.getLayoutInflater().inflate(R.layout.split_segments_layout, container, false);
|
||||
|
||||
Toolbar toolbar = (Toolbar) view.findViewById(R.id.split_interval_toolbar);
|
||||
|
@ -251,7 +255,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
public void updateContent() {
|
||||
if (getTrackActivity() != null) {
|
||||
if (getActivity() != null) {
|
||||
adapter.clear();
|
||||
adapter.setNotifyOnChange(false);
|
||||
adapter.add(gpxItem);
|
||||
|
@ -298,18 +302,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
|
||||
@Nullable
|
||||
private GPXFile getGpx() {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
return trackActivity != null ? trackActivity.getGpx() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackActivity getTrackActivity() {
|
||||
return (TrackActivity) getActivity();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public TrackActivity requireTrackActivity() {
|
||||
return (TrackActivity) requireActivity();
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
private void prepareSplitIntervalAdapterData() {
|
||||
|
@ -347,7 +340,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> getDisplayGroups() {
|
||||
return filterGroups(true);
|
||||
return displayHelper.getDisplayGroups(filterTypes);
|
||||
}
|
||||
|
||||
private void addOptionSplit(int value, boolean distance, List<GpxDisplayGroup> model) {
|
||||
|
@ -375,32 +368,13 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> filterGroups(boolean useDisplayGroups) {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
if (getTrackActivity() != null) {
|
||||
List<GpxDisplayGroup> result = getTrackActivity().getGpxFile(useDisplayGroups);
|
||||
for (GpxDisplayGroup group : result) {
|
||||
boolean add = hasFilterType(group.getType());
|
||||
if (add) {
|
||||
groups.add(group);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayItem> getSplitSegments() {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
List<GpxDisplayItem> splitSegments = new ArrayList<>();
|
||||
if (trackActivity != null) {
|
||||
List<GpxDisplayGroup> result = trackActivity.getGpxFile(true);
|
||||
if (result != null && result.size() > 0 && trkSegment.points.size() > 0) {
|
||||
for (GpxDisplayGroup group : result) {
|
||||
splitSegments.addAll(collectDisplayItemsFromGroup(group));
|
||||
}
|
||||
List<GpxDisplayGroup> result = displayHelper.getGpxFile(true);
|
||||
if (result != null && result.size() > 0 && trkSegment.points.size() > 0) {
|
||||
for (GpxDisplayGroup group : result) {
|
||||
splitSegments.addAll(collectDisplayItemsFromGroup(group));
|
||||
}
|
||||
}
|
||||
return splitSegments;
|
||||
|
@ -434,24 +408,6 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
if (trackActivity != null) {
|
||||
trackActivity.updateSplitView();
|
||||
}
|
||||
super.dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
if (trackActivity != null) {
|
||||
trackActivity.updateSplitView();
|
||||
}
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
|
||||
private class SplitSegmentsAdapter extends ArrayAdapter<GpxDisplayItem> {
|
||||
|
||||
SplitSegmentsAdapter(List<GpxDisplayItem> items) {
|
||||
|
@ -464,7 +420,7 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
@Override
|
||||
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
|
||||
GpxDisplayItem currentGpxDisplayItem = getItem(position);
|
||||
TrackActivity trackActivity = requireTrackActivity();
|
||||
FragmentActivity trackActivity = requireActivity();
|
||||
if (convertView == null) {
|
||||
convertView = trackActivity.getLayoutInflater().inflate(R.layout.gpx_split_segment_fragment, parent, false);
|
||||
}
|
||||
|
@ -750,14 +706,15 @@ public class SplitSegmentDialogFragment extends DialogFragment {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(@NonNull TrackActivity trackActivity, @NonNull GpxDisplayItem gpxItem, GPXUtilities.TrkSegment trkSegment) {
|
||||
public static boolean showInstance(@NonNull FragmentManager fragmentManager, @NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull GpxDisplayItem gpxItem, @NonNull TrkSegment trkSegment) {
|
||||
try {
|
||||
SplitSegmentDialogFragment fragment = new SplitSegmentDialogFragment();
|
||||
fragment.setGpxItem(gpxItem);
|
||||
fragment.setTrkSegment(trkSegment);
|
||||
fragment.setRetainInstance(true);
|
||||
fragment.setJoinSegments(trackActivity.isJoinSegments());
|
||||
fragment.show(trackActivity.getSupportFragmentManager(), TAG);
|
||||
fragment.displayHelper = displayHelper;
|
||||
fragment.show(fragmentManager, TAG);
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.content.Intent;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
|
@ -14,9 +13,7 @@ import android.view.Gravity;
|
|||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
@ -39,16 +36,12 @@ import com.squareup.picasso.RequestCreator;
|
|||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.Metadata;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.PicassoUtils;
|
||||
import net.osmand.data.PointDescription;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.plus.GPXDatabase.GpxDataItem;
|
||||
import net.osmand.plus.GpxSelectionHelper;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
|
@ -57,9 +50,7 @@ import net.osmand.plus.dialogs.GpxAppearanceAdapter;
|
|||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.GpxSplitType;
|
||||
import net.osmand.plus.track.SplitTrackAsyncTask;
|
||||
import net.osmand.plus.track.SplitTrackAsyncTask.SplitTrackListener;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.widgets.tools.CropCircleTransformation;
|
||||
import net.osmand.plus.wikipedia.WikiArticleHelper;
|
||||
import net.osmand.plus.wikivoyage.WikivoyageUtils;
|
||||
|
@ -67,12 +58,8 @@ import net.osmand.plus.wikivoyage.article.WikivoyageArticleDialogFragment;
|
|||
import net.osmand.plus.wikivoyage.data.TravelArticle;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import gnu.trove.list.array.TIntArrayList;
|
||||
|
||||
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR;
|
||||
|
||||
public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
||||
|
@ -81,11 +68,8 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
private Fragment fragment;
|
||||
private ListView listView;
|
||||
private GpxDisplayItemType[] filterTypes;
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private List<String> options = new ArrayList<>();
|
||||
private List<Double> distanceSplit = new ArrayList<>();
|
||||
private TIntArrayList timeSplit = new TIntArrayList();
|
||||
private int selectedSplitInterval;
|
||||
private boolean updateEnable;
|
||||
private View headerView;
|
||||
private SwitchCompat vis;
|
||||
|
@ -108,17 +92,18 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
private View lineTextLayout;
|
||||
private View overlayView;
|
||||
|
||||
ListPopupWindow splitListPopupWindow;
|
||||
ListPopupWindow colorListPopupWindow;
|
||||
|
||||
TrackActivityFragmentAdapter(@NonNull OsmandApplication app,
|
||||
@NonNull Fragment fragment,
|
||||
@NonNull ListView listView,
|
||||
@NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull GpxDisplayItemType... filterTypes) {
|
||||
this.app = app;
|
||||
this.fragment = fragment;
|
||||
this.listView = listView;
|
||||
this.filterTypes = filterTypes;
|
||||
this.displayHelper = displayHelper;
|
||||
}
|
||||
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
|
@ -206,14 +191,12 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
|
||||
private GPXFile getGpx() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpx() : null;
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GpxDataItem getGpxDataItem() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpxDataItem() : null;
|
||||
return displayHelper.getGpxDataItem();
|
||||
}
|
||||
|
||||
private void showTrackBitmapProgress() {
|
||||
|
@ -265,17 +248,15 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
imageView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
showTemporaryObjectOnMap(getRect());
|
||||
showTemporaryObjectOnMap(displayHelper.getRect());
|
||||
}
|
||||
});
|
||||
final View splitColorView = headerView.findViewById(R.id.split_color_view);
|
||||
final View appearanceView = headerView.findViewById(R.id.appearance_view);
|
||||
final View divider = headerView.findViewById(R.id.divider);
|
||||
final View splitIntervalView = headerView.findViewById(R.id.split_interval_view);
|
||||
vis = (SwitchCompat) headerView.findViewById(R.id.showOnMapToggle);
|
||||
final View bottomDivider = headerView.findViewById(R.id.bottom_divider);
|
||||
GPXFile gpxFile = getGpx();
|
||||
boolean gpxFileSelected = isGpxFileSelected(gpxFile);
|
||||
boolean gpxFileSelected = isGpxFileSelected(app, gpxFile);
|
||||
|
||||
boolean hasPath = gpxFile != null && (gpxFile.tracks.size() > 0 || gpxFile.routes.size() > 0);
|
||||
TrackActivity activity = getTrackActivity();
|
||||
|
@ -297,13 +278,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
@Override
|
||||
public void onClick(View v) {
|
||||
vis.toggle();
|
||||
if (!vis.isChecked()) {
|
||||
selectedSplitInterval = 0;
|
||||
}
|
||||
setTrackVisibilityOnMap(vis.isChecked());
|
||||
if (!showMapOnly) {
|
||||
updateSplitIntervalView(splitIntervalView);
|
||||
}
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
if (trackActivity != null) {
|
||||
trackActivity.updateHeader(fragment);
|
||||
|
@ -312,45 +287,12 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
});
|
||||
|
||||
splitColorView.setVisibility(View.GONE);
|
||||
if (showMapOnly) {
|
||||
splitIntervalView.setVisibility(View.GONE);
|
||||
appearanceView.setVisibility(View.GONE);
|
||||
divider.setVisibility(View.GONE);
|
||||
bottomDivider.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
bottomDivider.setVisibility(View.GONE);
|
||||
|
||||
if (hasPath) {
|
||||
if (!gpxFile.showCurrentTrack && listItemsCount > 0) {
|
||||
prepareSplitIntervalAdapterData();
|
||||
setupSplitIntervalView(splitIntervalView);
|
||||
updateSplitIntervalView(splitIntervalView);
|
||||
splitIntervalView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
ListAdapter adapter = new ArrayAdapter<>(activity, R.layout.popup_list_text_item, options);
|
||||
OnItemClickListener itemClickListener = new OnItemClickListener() {
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
selectedSplitInterval = position;
|
||||
setTrackVisibilityOnMap(vis.isChecked());
|
||||
splitListPopupWindow.dismiss();
|
||||
updateSplitIntervalView(splitIntervalView);
|
||||
}
|
||||
};
|
||||
splitListPopupWindow = createPopupWindow(activity, splitIntervalView, adapter, itemClickListener);
|
||||
splitListPopupWindow.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
splitIntervalView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
splitIntervalView.setVisibility(View.GONE);
|
||||
}
|
||||
appearanceView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -363,6 +305,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
appearanceView.setVisibility(View.GONE);
|
||||
divider.setVisibility(View.GONE);
|
||||
}
|
||||
bottomDivider.setVisibility(View.GONE);
|
||||
}
|
||||
updateTrackColor();
|
||||
}
|
||||
|
@ -373,7 +316,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
GPXFile gpx = getGpx();
|
||||
WptPt pointToShow = gpx != null ? gpx.findPointToShow() : null;
|
||||
if (activity != null && pointToShow != null) {
|
||||
boolean gpxFileSelected = isGpxFileSelected(gpx);
|
||||
boolean gpxFileSelected = isGpxFileSelected(app, gpx);
|
||||
if (!gpxFileSelected) {
|
||||
Intent intent = activity.getIntent();
|
||||
if (intent != null) {
|
||||
|
@ -422,7 +365,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
return null;
|
||||
}
|
||||
|
||||
TravelArticle article = getTravelArticle(gpx.metadata);
|
||||
TravelArticle article = getTravelArticle(gpx);
|
||||
if (article != null) {
|
||||
return createTravelArticleCard(context, article);
|
||||
}
|
||||
|
@ -448,7 +391,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private String getMetadataDescription(@NonNull GPXUtilities.Metadata metadata) {
|
||||
private String getMetadataDescription(@NonNull Metadata metadata) {
|
||||
String descHtml = metadata.desc;
|
||||
if (TextUtils.isEmpty(descHtml)) {
|
||||
Map<String, String> extensions = metadata.getExtensionsToRead();
|
||||
|
@ -466,7 +409,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private String getMetadataImageLink(@NonNull GPXUtilities.Metadata metadata) {
|
||||
private String getMetadataImageLink(@NonNull Metadata metadata) {
|
||||
String link = metadata.link;
|
||||
if (!TextUtils.isEmpty(link)) {
|
||||
String lowerCaseLink = link.toLowerCase();
|
||||
|
@ -482,11 +425,12 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private TravelArticle getTravelArticle(@NonNull GPXUtilities.Metadata metadata) {
|
||||
private TravelArticle getTravelArticle(@NonNull GPXFile gpx) {
|
||||
Metadata metadata = gpx.metadata;
|
||||
String title = metadata.getArticleTitle();
|
||||
String lang = metadata.getArticleLang();
|
||||
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(lang)) {
|
||||
return app.getTravelHelper().getArticleByTitle(title, lang);
|
||||
return app.getTravelHelper().getArticleByTitle(title, gpx.getRect(), lang);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -506,8 +450,8 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
public void onClick(View v) {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
WikivoyageArticleDialogFragment.showInstance(app,
|
||||
activity.getSupportFragmentManager(), article.getRouteId(), article.getLang());
|
||||
WikivoyageArticleDialogFragment.showInstance(app, activity.getSupportFragmentManager(),
|
||||
article.generateIdentifier(), article.getLang());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -585,7 +529,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isGpxFileSelected(GPXFile gpxFile) {
|
||||
public static boolean isGpxFileSelected(OsmandApplication app, GPXFile gpxFile) {
|
||||
return gpxFile != null &&
|
||||
((gpxFile.showCurrentTrack && app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null) ||
|
||||
(gpxFile.path != null && app.getSelectedGpxHelper().getSelectedFileByPath(gpxFile.path) != null));
|
||||
|
@ -594,26 +538,10 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
private void setTrackVisibilityOnMap(boolean visible) {
|
||||
GPXFile gpxFile = getGpx();
|
||||
if (gpxFile != null) {
|
||||
GpxSelectionHelper gpxHelper = app.getSelectedGpxHelper();
|
||||
SelectedGpxFile sf = gpxHelper.selectGpxFile(gpxFile, visible, false);
|
||||
if (gpxFile.hasTrkPt()) {
|
||||
List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
if (groups.size() > 0) {
|
||||
updateSplit(groups, visible ? sf : null);
|
||||
if (getGpxDataItem() != null) {
|
||||
updateSplitInDatabase();
|
||||
}
|
||||
}
|
||||
}
|
||||
app.getSelectedGpxHelper().selectGpxFile(gpxFile, visible, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private QuadRect getRect() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getRect() : null;
|
||||
}
|
||||
|
||||
public boolean isShowOnMap() {
|
||||
return vis != null && vis.isChecked();
|
||||
}
|
||||
|
@ -629,88 +557,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
menuFab.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<GpxDisplayGroup> getOriginalGroups() {
|
||||
return filterGroups(false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<GpxDisplayGroup> getDisplayGroups() {
|
||||
return filterGroups(true);
|
||||
}
|
||||
|
||||
private boolean hasFilterType(GpxDisplayItemType filterType) {
|
||||
for (GpxDisplayItemType type : filterTypes) {
|
||||
if (type == filterType) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<GpxDisplayGroup> filterGroups(boolean useDisplayGroups) {
|
||||
List<GpxDisplayGroup> groups = new ArrayList<>();
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
List<GpxDisplayGroup> result = activity.getGpxFile(useDisplayGroups);
|
||||
for (GpxDisplayGroup group : result) {
|
||||
boolean add = hasFilterType(group.getType());
|
||||
if (add) {
|
||||
groups.add(group);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
private void setupSplitIntervalView(View view) {
|
||||
final TextView title = (TextView) view.findViewById(R.id.split_interval_title);
|
||||
final TextView text = (TextView) view.findViewById(R.id.split_interval_text);
|
||||
final ImageView img = (ImageView) view.findViewById(R.id.split_interval_arrow);
|
||||
int colorId;
|
||||
final List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
if (groups.size() > 0) {
|
||||
colorId = app.getSettings().isLightContent() ?
|
||||
R.color.text_color_primary_light : R.color.text_color_primary_dark;
|
||||
} else {
|
||||
colorId = app.getSettings().isLightContent() ?
|
||||
R.color.text_color_secondary_light : R.color.text_color_secondary_dark;
|
||||
}
|
||||
int color = app.getResources().getColor(colorId);
|
||||
title.setTextColor(color);
|
||||
text.setTextColor(color);
|
||||
img.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.ic_action_arrow_drop_down, colorId));
|
||||
}
|
||||
|
||||
private void updateSplitIntervalView(View view) {
|
||||
final TextView text = (TextView) view.findViewById(R.id.split_interval_text);
|
||||
selectedSplitInterval = getSelectedSplitInterval();
|
||||
if (selectedSplitInterval == 0) {
|
||||
text.setText(app.getString(R.string.shared_string_none));
|
||||
} else {
|
||||
text.setText(options.get(selectedSplitInterval));
|
||||
}
|
||||
}
|
||||
|
||||
private int getSelectedSplitInterval() {
|
||||
if (getGpxDataItem() == null) {
|
||||
return 0;
|
||||
}
|
||||
int splitType = getGpxDataItem().getSplitType();
|
||||
double splitInterval = getGpxDataItem().getSplitInterval();
|
||||
int position = 0;
|
||||
|
||||
if (splitType == GpxSplitType.DISTANCE.getType()) {
|
||||
position = distanceSplit.indexOf(splitInterval);
|
||||
} else if (splitType == GpxSplitType.TIME.getType()) {
|
||||
position = timeSplit.indexOf((int) splitInterval);
|
||||
}
|
||||
|
||||
return Math.max(position, 0);
|
||||
}
|
||||
|
||||
private void updateTrackColor() {
|
||||
int color = getGpxDataItem() != null ? getGpxDataItem().getColor() : 0;
|
||||
GPXFile gpxFile = getGpx();
|
||||
|
@ -732,154 +578,6 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
|
|||
}
|
||||
}
|
||||
|
||||
public List<GpxSelectionHelper.GpxDisplayItem> flatten(List<GpxDisplayGroup> groups) {
|
||||
ArrayList<GpxSelectionHelper.GpxDisplayItem> list = new ArrayList<>();
|
||||
for (GpxDisplayGroup g : groups) {
|
||||
list.addAll(g.getModifiableList());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void prepareSplitIntervalAdapterData() {
|
||||
final List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
|
||||
options.add(app.getString(R.string.shared_string_none));
|
||||
distanceSplit.add(-1d);
|
||||
timeSplit.add(-1);
|
||||
addOptionSplit(30, true, groups); // 50 feet, 20 yards, 20
|
||||
// m
|
||||
addOptionSplit(60, true, groups); // 100 feet, 50 yards,
|
||||
// 50 m
|
||||
addOptionSplit(150, true, groups); // 200 feet, 100 yards,
|
||||
// 100 m
|
||||
addOptionSplit(300, true, groups); // 500 feet, 200 yards,
|
||||
// 200 m
|
||||
addOptionSplit(600, true, groups); // 1000 feet, 500 yards,
|
||||
// 500 m
|
||||
addOptionSplit(1500, true, groups); // 2000 feet, 1000 yards, 1 km
|
||||
addOptionSplit(3000, true, groups); // 1 mi, 2 km
|
||||
addOptionSplit(6000, true, groups); // 2 mi, 5 km
|
||||
addOptionSplit(15000, true, groups); // 5 mi, 10 km
|
||||
|
||||
addOptionSplit(15, false, groups);
|
||||
addOptionSplit(30, false, groups);
|
||||
addOptionSplit(60, false, groups);
|
||||
addOptionSplit(120, false, groups);
|
||||
addOptionSplit(150, false, groups);
|
||||
addOptionSplit(300, false, groups);
|
||||
addOptionSplit(600, false, groups);
|
||||
addOptionSplit(900, false, groups);
|
||||
addOptionSplit(1800, false, groups);
|
||||
addOptionSplit(3600, false, groups);
|
||||
}
|
||||
|
||||
private void updateSplit(@NonNull List<GpxDisplayGroup> groups, @Nullable final SelectedGpxFile selectedGpx) {
|
||||
GPXFile gpxFile = getGpx();
|
||||
TrackActivity activity = getTrackActivity();
|
||||
GpxSplitType gpxSplitType = getGpxSplitType();
|
||||
if (activity != null && gpxSplitType != null && gpxFile != null) {
|
||||
int timeSplit = 0;
|
||||
double distanceSplit = 0;
|
||||
if (gpxSplitType != GpxSplitType.NO_SPLIT && !gpxFile.showCurrentTrack) {
|
||||
timeSplit = this.timeSplit.get(selectedSplitInterval);
|
||||
distanceSplit = this.distanceSplit.get(selectedSplitInterval);
|
||||
}
|
||||
SplitTrackListener splitTrackListener = new SplitTrackListener() {
|
||||
|
||||
@Override
|
||||
public void trackSplittingStarted() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trackSplittingFinished() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
if (activity != null) {
|
||||
if (AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||
activity.setSupportProgressBarIndeterminateVisibility(false);
|
||||
}
|
||||
if (selectedGpx != null) {
|
||||
List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
selectedGpx.setDisplayGroups(groups, app);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
new SplitTrackAsyncTask(app, gpxSplitType, groups, splitTrackListener, activity.isJoinSegments(),
|
||||
timeSplit, distanceSplit).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
}
|
||||
|
||||
private GpxSplitType getGpxSplitType() {
|
||||
if (selectedSplitInterval == 0) {
|
||||
return GpxSplitType.NO_SPLIT;
|
||||
} else if (distanceSplit.get(selectedSplitInterval) > 0) {
|
||||
return GpxSplitType.DISTANCE;
|
||||
} else if (timeSplit.get(selectedSplitInterval) > 0) {
|
||||
return GpxSplitType.TIME;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addOptionSplit(int value, boolean distance, @NonNull List<GpxDisplayGroup> model) {
|
||||
if (model.size() > 0) {
|
||||
if (distance) {
|
||||
double dvalue = OsmAndFormatter.calculateRoundedDist(value, app);
|
||||
options.add(OsmAndFormatter.getFormattedDistanceInterval(app, value));
|
||||
distanceSplit.add(dvalue);
|
||||
timeSplit.add(-1);
|
||||
if (Math.abs(model.get(0).getSplitDistance() - dvalue) < 1) {
|
||||
selectedSplitInterval = distanceSplit.size() - 1;
|
||||
}
|
||||
} else {
|
||||
options.add(OsmAndFormatter.getFormattedTimeInterval(app, value));
|
||||
distanceSplit.add(-1d);
|
||||
timeSplit.add(value);
|
||||
if (model.get(0).getSplitTime() == value) {
|
||||
selectedSplitInterval = distanceSplit.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSplitInDatabase() {
|
||||
double splitInterval = 0;
|
||||
GpxSplitType splitType = null;
|
||||
if (selectedSplitInterval == 0) {
|
||||
splitType = GpxSplitType.NO_SPLIT;
|
||||
splitInterval = 0;
|
||||
} else if (distanceSplit.get(selectedSplitInterval) > 0) {
|
||||
splitType = GpxSplitType.DISTANCE;
|
||||
splitInterval = distanceSplit.get(selectedSplitInterval);
|
||||
} else if (timeSplit.get(selectedSplitInterval) > 0) {
|
||||
splitType = GpxSplitType.TIME;
|
||||
splitInterval = timeSplit.get(selectedSplitInterval);
|
||||
}
|
||||
GpxDataItem item = getGpxDataItem();
|
||||
if (item != null && splitType != null) {
|
||||
app.getGpxDbHelper().updateSplit(item, splitType, splitInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSplitView() {
|
||||
GPXFile gpxFile = getGpx();
|
||||
if (gpxFile != null) {
|
||||
SelectedGpxFile sf = app.getSelectedGpxHelper().selectGpxFile(gpxFile,
|
||||
((SwitchCompat) headerView.findViewById(R.id.showOnMapToggle)).isChecked(), false);
|
||||
final List<GpxDisplayGroup> groups = getDisplayGroups();
|
||||
if (groups.size() > 0) {
|
||||
updateSplit(groups, ((SwitchCompat) headerView.findViewById(R.id.showOnMapToggle)).isChecked() ? sf : null);
|
||||
if (getGpxDataItem() != null) {
|
||||
updateSplitInDatabase();
|
||||
}
|
||||
}
|
||||
updateSplitIntervalView(headerView.findViewById(R.id.split_interval_view));
|
||||
}
|
||||
}
|
||||
|
||||
public void hideTransparentOverlay() {
|
||||
overlayView.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ import com.google.android.material.snackbar.Snackbar;
|
|||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.Collator;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.OsmAndCollator;
|
||||
|
@ -59,7 +58,6 @@ import net.osmand.plus.UiUtilities;
|
|||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.OsmandActionBarActivity;
|
||||
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
|
||||
import net.osmand.plus.activities.SavingTrackHelper;
|
||||
import net.osmand.plus.activities.TrackActivity;
|
||||
import net.osmand.plus.base.OsmandExpandableListFragment;
|
||||
import net.osmand.plus.base.PointImageDrawable;
|
||||
|
@ -67,14 +65,16 @@ import net.osmand.plus.helpers.GpxUiHelper;
|
|||
import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersHelper;
|
||||
import net.osmand.plus.myplaces.DeletePointsTask.OnPointsDeleteListener;
|
||||
import net.osmand.plus.myplaces.TrackBitmapDrawer.TrackBitmapDrawerListener;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
|
||||
import net.osmand.plus.track.TrackDisplayHelper;
|
||||
import net.osmand.plus.track.TrackMenuFragment;
|
||||
import net.osmand.plus.widgets.TextViewEx;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
@ -88,7 +88,7 @@ import java.util.Map.Entry;
|
|||
import java.util.Set;
|
||||
|
||||
|
||||
public class TrackPointFragment extends OsmandExpandableListFragment implements TrackBitmapDrawerListener {
|
||||
public class TrackPointFragment extends OsmandExpandableListFragment implements TrackBitmapDrawerListener, OnPointsDeleteListener {
|
||||
|
||||
public static final int SEARCH_ID = -1;
|
||||
public static final int DELETE_ID = 2;
|
||||
|
@ -105,6 +105,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
private OsmandApplication app;
|
||||
private TrackActivityFragmentAdapter fragmentAdapter;
|
||||
final private PointGPXAdapter adapter = new PointGPXAdapter();
|
||||
private GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_POINTS, GpxDisplayItemType.TRACK_ROUTE_POINTS};
|
||||
private TrackDisplayHelper displayHelper;
|
||||
|
||||
private boolean selectionMode;
|
||||
private LinkedHashMap<GpxDisplayItemType, Set<GpxDisplayItem>> selectedItems = new LinkedHashMap<>();
|
||||
|
@ -120,6 +122,13 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
this.app = getMyApplication();
|
||||
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof TrackActivity) {
|
||||
displayHelper = ((TrackActivity) activity).getDisplayHelper();
|
||||
} else if (getTargetFragment() instanceof TrackMenuFragment) {
|
||||
displayHelper = ((TrackMenuFragment) getTargetFragment()).getDisplayHelper();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -135,8 +144,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
mainView = inflater.inflate(R.layout.track_points_tree, container, false);
|
||||
ExpandableListView listView = (ExpandableListView) mainView.findViewById(android.R.id.list);
|
||||
|
||||
fragmentAdapter = new TrackActivityFragmentAdapter(app, this, listView,
|
||||
GpxDisplayItemType.TRACK_POINTS, GpxDisplayItemType.TRACK_ROUTE_POINTS);
|
||||
fragmentAdapter = new TrackActivityFragmentAdapter(app, this, listView, displayHelper, filterTypes);
|
||||
fragmentAdapter.setShowMapOnly(true);
|
||||
fragmentAdapter.setTrackBitmapSelectionSupported(false);
|
||||
fragmentAdapter.setShowDescriptionCard(true);
|
||||
|
@ -165,13 +173,8 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
if (optionsMenu != null) {
|
||||
optionsMenu.close();
|
||||
}
|
||||
if (fragmentAdapter != null) {
|
||||
if (fragmentAdapter.splitListPopupWindow != null) {
|
||||
fragmentAdapter.splitListPopupWindow.dismiss();
|
||||
}
|
||||
if (fragmentAdapter.colorListPopupWindow != null) {
|
||||
fragmentAdapter.colorListPopupWindow.dismiss();
|
||||
}
|
||||
if (fragmentAdapter != null && fragmentAdapter.colorListPopupWindow != null) {
|
||||
fragmentAdapter.colorListPopupWindow.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +195,6 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private int getSelectedItemsCount() {
|
||||
int count = 0;
|
||||
for (Set<GpxDisplayItem> set : selectedItems.values()) {
|
||||
|
@ -213,21 +215,14 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackActivity getTrackActivity() {
|
||||
return (TrackActivity) getActivity();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GPXFile getGpx() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpx() : null;
|
||||
return displayHelper.getGpx();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GpxDataItem getGpxDataItem() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
return activity != null ? activity.getGpxDataItem() : null;
|
||||
return displayHelper.getGpxDataItem();
|
||||
}
|
||||
|
||||
private void expandAllGroups() {
|
||||
|
@ -250,7 +245,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
|
||||
@Nullable
|
||||
private List<GpxDisplayGroup> getOriginalGroups() {
|
||||
return fragmentAdapter != null ? fragmentAdapter.getOriginalGroups() : null;
|
||||
return displayHelper.getOriginalGroups(filterTypes);
|
||||
}
|
||||
|
||||
public void setContent() {
|
||||
|
@ -348,7 +343,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
menu.clear();
|
||||
|
@ -495,13 +490,13 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
|
||||
private void deleteItems() {
|
||||
new DeletePointsTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
new DeletePointsTask(app, getGpx(), getSelectedItems(), this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void addOrRemoveMapMarkersSyncGroup() {
|
||||
final MapMarkersHelper markersHelper = app.getMapMarkersHelper();
|
||||
|
||||
TrackActivity activity = getTrackActivity();
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -536,7 +531,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
.setAction(R.string.shared_string_undo, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
FragmentActivity trackActivity = getActivity();
|
||||
if (trackActivity != null) {
|
||||
if (markersRemoved) {
|
||||
if (gpxFile != null) {
|
||||
|
@ -606,7 +601,7 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
|
||||
private void selectFavoritesImpl() {
|
||||
TrackActivity activity = getTrackActivity();
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null && getSelectedItemsCount() > 0) {
|
||||
AlertDialog.Builder b = new AlertDialog.Builder(activity);
|
||||
final EditText editText = new EditText(activity);
|
||||
|
@ -684,14 +679,11 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
} else {
|
||||
GPXFile gpx = item.group.getGpx();
|
||||
if (gpx != null) {
|
||||
TrackActivity trackActivity = getTrackActivity();
|
||||
if (trackActivity != null && fragmentAdapter != null) {
|
||||
boolean gpxFileSelected = fragmentAdapter.isGpxFileSelected(gpx);
|
||||
if (!gpxFileSelected) {
|
||||
Intent intent = trackActivity.getIntent();
|
||||
if (intent != null) {
|
||||
intent.putExtra(TrackActivity.SHOW_TEMPORARILY, true);
|
||||
}
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null && !TrackActivityFragmentAdapter.isGpxFileSelected(app, gpx)) {
|
||||
Intent intent = activity.getIntent();
|
||||
if (intent != null) {
|
||||
intent.putExtra(TrackActivity.SHOW_TEMPORARILY, true);
|
||||
}
|
||||
}
|
||||
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
|
||||
|
@ -741,6 +733,23 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointsDeletionStarted() {
|
||||
showProgressBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointsDeleted() {
|
||||
selectedItems.clear();
|
||||
selectedGroups.clear();
|
||||
|
||||
hideProgressBar();
|
||||
List<GpxDisplayGroup> groups = getOriginalGroups();
|
||||
if (groups != null) {
|
||||
adapter.synchronizeGroups(groups);
|
||||
}
|
||||
}
|
||||
|
||||
class PointGPXAdapter extends OsmandBaseExpandableListAdapter implements Filterable {
|
||||
|
||||
Map<GpxDisplayGroup, List<GpxDisplayItem>> itemGroups = new LinkedHashMap<>();
|
||||
|
@ -1199,9 +1208,6 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
|
||||
public class PointsFilter extends Filter {
|
||||
|
||||
PointsFilter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
FilterResults results = new FilterResults();
|
||||
|
@ -1243,77 +1249,4 @@ public class TrackPointFragment extends OsmandExpandableListFragment implements
|
|||
expandAllGroups();
|
||||
}
|
||||
}
|
||||
|
||||
private static class DeletePointsTask extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private OsmandApplication app;
|
||||
private WeakReference<TrackPointFragment> fragmentRef;
|
||||
private GPXFile gpx;
|
||||
private Set<GpxDisplayItem> selectedItems;
|
||||
|
||||
DeletePointsTask(TrackPointFragment fragment) {
|
||||
this.app = fragment.getMyApplication();
|
||||
this.fragmentRef = new WeakReference<>(fragment);
|
||||
this.gpx = fragment.getGpx();
|
||||
this.selectedItems = fragment.getSelectedItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
TrackPointFragment fragment = fragmentRef.get();
|
||||
if (fragment != null) {
|
||||
fragment.showProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
SavingTrackHelper savingTrackHelper = app.getSavingTrackHelper();
|
||||
if (gpx != null) {
|
||||
for (GpxDisplayItem item : selectedItems) {
|
||||
if (gpx.showCurrentTrack) {
|
||||
savingTrackHelper.deletePointData(item.locationStart);
|
||||
} else {
|
||||
if (item.group.getType() == GpxDisplayItemType.TRACK_POINTS) {
|
||||
gpx.deleteWptPt(item.locationStart);
|
||||
} else if (item.group.getType() == GpxDisplayItemType.TRACK_ROUTE_POINTS) {
|
||||
gpx.deleteRtePt(item.locationStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gpx.showCurrentTrack) {
|
||||
GPXUtilities.writeGpxFile(new File(gpx.path), gpx);
|
||||
boolean selected = app.getSelectedGpxHelper().getSelectedFileByPath(gpx.path) != null;
|
||||
if (selected) {
|
||||
app.getSelectedGpxHelper().setGpxFileToDisplay(gpx);
|
||||
}
|
||||
}
|
||||
syncGpx(gpx);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
TrackPointFragment fragment = fragmentRef.get();
|
||||
if (fragment != null) {
|
||||
fragment.selectedItems.clear();
|
||||
fragment.selectedGroups.clear();
|
||||
|
||||
fragment.hideProgressBar();
|
||||
List<GpxDisplayGroup> groups = fragment.getOriginalGroups();
|
||||
if (groups != null) {
|
||||
fragment.adapter.synchronizeGroups(groups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void syncGpx(GPXFile gpxFile) {
|
||||
MapMarkersHelper helper = app.getMapMarkersHelper();
|
||||
MapMarkersGroup group = helper.getMarkersGroup(gpxFile);
|
||||
if (group != null) {
|
||||
helper.runSynchronization(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
196
OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingCard.java
Normal file
196
OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingCard.java
Normal file
|
@ -0,0 +1,196 @@
|
|||
package net.osmand.plus.onlinerouting;
|
||||
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter;
|
||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionAdapterListener;
|
||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OnlineRoutingCard extends BaseCard {
|
||||
|
||||
private View headerContainer;
|
||||
private TextView tvHeaderTitle;
|
||||
private TextView tvHeaderSubtitle;
|
||||
private RecyclerView rvSelectionMenu;
|
||||
private HorizontalSelectionAdapter adapter;
|
||||
private TextView tvDescription;
|
||||
private View fieldBoxContainer;
|
||||
private OsmandTextFieldBoxes textFieldBoxes;
|
||||
private EditText editText;
|
||||
private TextView tvHelperText;
|
||||
private View bottomDivider;
|
||||
private View button;
|
||||
private OnTextChangedListener onTextChangedListener;
|
||||
|
||||
public OnlineRoutingCard(@NonNull MapActivity mapActivity, boolean nightMode) {
|
||||
super(mapActivity);
|
||||
this.nightMode = nightMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardLayoutId() {
|
||||
return R.layout.online_routing_preference_segment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateContent() {
|
||||
headerContainer = view.findViewById(R.id.header);
|
||||
tvHeaderTitle = view.findViewById(R.id.title);
|
||||
tvHeaderSubtitle = view.findViewById(R.id.subtitle);
|
||||
rvSelectionMenu = view.findViewById(R.id.selection_menu);
|
||||
tvDescription = view.findViewById(R.id.description);
|
||||
fieldBoxContainer = view.findViewById(R.id.field_box_container);
|
||||
textFieldBoxes = view.findViewById(R.id.field_box);
|
||||
editText = view.findViewById(R.id.edit_text);
|
||||
tvHelperText = view.findViewById(R.id.helper_text);
|
||||
bottomDivider = view.findViewById(R.id.bottom_divider);
|
||||
button = view.findViewById(R.id.button);
|
||||
|
||||
editText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (onTextChangedListener != null) {
|
||||
boolean editedByUser = editText.getTag() == null;
|
||||
String text = editText.getText().toString();
|
||||
onTextChangedListener.onTextChanged(editedByUser, text);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
editText.setSelection(editText.getText().length());
|
||||
AndroidUtils.showSoftKeyboard(getMapActivity(), editText);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setHeaderTitle(@NonNull String title) {
|
||||
showElements(headerContainer, tvHeaderTitle);
|
||||
tvHeaderTitle.setText(title);
|
||||
}
|
||||
|
||||
public void setHeaderSubtitle(@NonNull String subtitle) {
|
||||
showElements(headerContainer, tvHeaderSubtitle);
|
||||
tvHeaderSubtitle.setText(subtitle);
|
||||
}
|
||||
|
||||
public void setSelectionMenu(List<HorizontalSelectionItem> items,
|
||||
String selectedItemTitle,
|
||||
final CallbackWithObject<HorizontalSelectionItem> callback) {
|
||||
showElements(rvSelectionMenu);
|
||||
rvSelectionMenu.setLayoutManager(
|
||||
new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
|
||||
adapter = new HorizontalSelectionAdapter(app, nightMode);
|
||||
adapter.setItems(items);
|
||||
adapter.setSelectedItemByTitle(selectedItemTitle);
|
||||
adapter.setListener(new HorizontalSelectionAdapterListener() {
|
||||
@Override
|
||||
public void onItemSelected(HorizontalSelectionItem item) {
|
||||
if (callback.processResult(item)) {
|
||||
adapter.setSelectedItem(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
rvSelectionMenu.setAdapter(adapter);
|
||||
}
|
||||
|
||||
public void setDescription(@NonNull String description) {
|
||||
showElements(tvDescription);
|
||||
tvDescription.setText(description);
|
||||
}
|
||||
|
||||
public void setFieldBoxLabelText(@NonNull String labelText) {
|
||||
showElements(fieldBoxContainer);
|
||||
textFieldBoxes.setLabelText(labelText);
|
||||
}
|
||||
|
||||
public void setFieldBoxHelperText(@NonNull String helperText) {
|
||||
showElements(fieldBoxContainer, tvHelperText);
|
||||
tvHelperText.setText(helperText);
|
||||
}
|
||||
|
||||
public void setEditedText(@NonNull String text) {
|
||||
editText.setTag(""); // needed to indicate that the text was edited programmatically
|
||||
editText.setText(text);
|
||||
editText.setTag(null);
|
||||
}
|
||||
|
||||
public String getEditedText() {
|
||||
return editText.getText().toString();
|
||||
}
|
||||
|
||||
public void showDivider() {
|
||||
showElements(bottomDivider);
|
||||
}
|
||||
|
||||
public void setButton(String title, OnClickListener listener) {
|
||||
showElements(button);
|
||||
button.setOnClickListener(listener);
|
||||
UiUtilities.setupDialogButton(nightMode, button, DialogButtonType.PRIMARY, title);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
showElements(view);
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
hideElements(view);
|
||||
}
|
||||
|
||||
public void showFieldBox() {
|
||||
showElements(fieldBoxContainer);
|
||||
}
|
||||
|
||||
public void hideFieldBox() {
|
||||
hideElements(fieldBoxContainer);
|
||||
}
|
||||
|
||||
private void showElements(View... views) {
|
||||
AndroidUiHelper.setVisibility(View.VISIBLE, views);
|
||||
}
|
||||
|
||||
private void hideElements(View... views) {
|
||||
AndroidUiHelper.setVisibility(View.GONE, views);
|
||||
}
|
||||
|
||||
public void setOnTextChangedListener(OnTextChangedListener onTextChangedListener) {
|
||||
this.onTextChangedListener = onTextChangedListener;
|
||||
}
|
||||
|
||||
public interface OnTextChangedListener {
|
||||
void onTextChanged(boolean editedByUser, String text);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package net.osmand.plus.onlinerouting;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class OnlineRoutingEngine {
|
||||
|
||||
public final static String ONLINE_ROUTING_ENGINE_PREFIX = "online_routing_engine_";
|
||||
|
||||
public enum EngineParameterType {
|
||||
CUSTOM_SERVER_URL,
|
||||
CUSTOM_NAME,
|
||||
API_KEY
|
||||
}
|
||||
|
||||
private String stringKey;
|
||||
private ServerType serverType;
|
||||
private String vehicleKey;
|
||||
private Map<String, String> params = new HashMap<>();
|
||||
|
||||
public OnlineRoutingEngine(@NonNull String stringKey,
|
||||
@NonNull ServerType serverType,
|
||||
@NonNull String vehicleKey,
|
||||
Map<String, String> params) {
|
||||
this(stringKey, serverType, vehicleKey);
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public OnlineRoutingEngine(@NonNull String stringKey,
|
||||
@NonNull ServerType serverType,
|
||||
@NonNull String vehicleKey) {
|
||||
this.stringKey = stringKey;
|
||||
this.serverType = serverType;
|
||||
this.vehicleKey = vehicleKey;
|
||||
}
|
||||
|
||||
public String getStringKey() {
|
||||
return stringKey;
|
||||
}
|
||||
|
||||
public ServerType getServerType() {
|
||||
return serverType;
|
||||
}
|
||||
|
||||
public String getVehicleKey() {
|
||||
return vehicleKey;
|
||||
}
|
||||
|
||||
public Map<String, String> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
String customServerUrl = getParameter(EngineParameterType.CUSTOM_SERVER_URL);
|
||||
if (!Algorithms.isEmpty(customServerUrl)) {
|
||||
return customServerUrl;
|
||||
} else {
|
||||
return serverType.getBaseUrl();
|
||||
}
|
||||
}
|
||||
|
||||
public String getParameter(EngineParameterType paramType) {
|
||||
return params.get(paramType.name());
|
||||
}
|
||||
|
||||
public void putParameter(EngineParameterType paramType, String paramValue) {
|
||||
params.put(paramType.name(), paramValue);
|
||||
}
|
||||
|
||||
public String getName(@NonNull Context ctx) {
|
||||
String customName = getParameter(EngineParameterType.CUSTOM_NAME);
|
||||
if (customName != null) {
|
||||
return customName;
|
||||
} else {
|
||||
return getStandardName(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private String getStandardName(@NonNull Context ctx) {
|
||||
return getStandardName(ctx, serverType, vehicleKey);
|
||||
}
|
||||
|
||||
public static String getStandardName(@NonNull Context ctx,
|
||||
@NonNull ServerType serverType,
|
||||
@NonNull String vehicleKey) {
|
||||
String vehicleTitle = VehicleType.toHumanString(ctx, vehicleKey);
|
||||
String pattern = ctx.getString(R.string.ltr_or_rtl_combine_via_dash);
|
||||
return String.format(pattern, serverType.getTitle(), vehicleTitle);
|
||||
}
|
||||
|
||||
public static OnlineRoutingEngine createNewEngine(@NonNull ServerType serverType,
|
||||
@NonNull String vehicleKey) {
|
||||
return new OnlineRoutingEngine(generateKey(), serverType, vehicleKey);
|
||||
}
|
||||
|
||||
private static String generateKey() {
|
||||
return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,610 @@
|
|||
package net.osmand.plus.onlinerouting;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidNetworkUtils;
|
||||
import net.osmand.AndroidNetworkUtils.OnRequestResultListener;
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.mapcontextmenu.other.HorizontalSelectionAdapter.HorizontalSelectionItem;
|
||||
import net.osmand.plus.onlinerouting.OnlineRoutingCard.OnTextChangedListener;
|
||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine.EngineParameterType;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class OnlineRoutingEngineFragment extends BaseOsmAndFragment {
|
||||
|
||||
public static final String TAG = OnlineRoutingEngineFragment.class.getSimpleName();
|
||||
|
||||
private static final String ENGINE_NAME_KEY = "engine_name";
|
||||
private static final String ENGINE_SERVER_KEY = "engine_server";
|
||||
private static final String ENGINE_SERVER_URL_KEY = "engine_server_url";
|
||||
private static final String ENGINE_VEHICLE_TYPE_KEY = "engine_vehicle_type";
|
||||
private static final String ENGINE_CUSTOM_VEHICLE_KEY = "engine_custom_vehicle";
|
||||
private static final String ENGINE_API_KEY_KEY = "engine_api_key";
|
||||
private static final String EXAMPLE_LOCATION_KEY = "example_location";
|
||||
private static final String APP_MODE_KEY = "app_mode";
|
||||
private static final String EDITED_ENGINE_KEY = "edited_engine_key";
|
||||
|
||||
private OsmandApplication app;
|
||||
private MapActivity mapActivity;
|
||||
private OnlineRoutingHelper helper;
|
||||
|
||||
private View view;
|
||||
private ViewGroup segmentsContainer;
|
||||
private OnlineRoutingCard nameCard;
|
||||
private OnlineRoutingCard serverCard;
|
||||
private OnlineRoutingCard vehicleCard;
|
||||
private OnlineRoutingCard apiKeyCard;
|
||||
private OnlineRoutingCard exampleCard;
|
||||
private View testResultsContainer;
|
||||
|
||||
private ApplicationMode appMode;
|
||||
|
||||
private OnlineRoutingEngineObject engine;
|
||||
private ExampleLocation selectedLocation;
|
||||
private String editedEngineKey;
|
||||
|
||||
private enum ExampleLocation {
|
||||
|
||||
AMSTERDAM("Amsterdam",
|
||||
new LatLon(52.379189, 4.899431),
|
||||
new LatLon(52.308056, 4.764167)),
|
||||
|
||||
BERLIN("Berlin",
|
||||
new LatLon(52.520008, 13.404954),
|
||||
new LatLon(52.3666652, 13.501997992)),
|
||||
|
||||
NEW_YORK("New York",
|
||||
new LatLon(43.000000, -75.000000),
|
||||
new LatLon(40.641766, -73.780968)),
|
||||
|
||||
PARIS("Paris",
|
||||
new LatLon(48.864716, 2.349014),
|
||||
new LatLon(48.948437, 2.434931));
|
||||
|
||||
ExampleLocation(String name, LatLon cityCenterLatLon, LatLon cityAirportLatLon) {
|
||||
this.name = name;
|
||||
this.cityCenterLatLon = cityCenterLatLon;
|
||||
this.cityAirportLatLon = cityAirportLatLon;
|
||||
}
|
||||
|
||||
private String name;
|
||||
private LatLon cityCenterLatLon;
|
||||
private LatLon cityAirportLatLon;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public LatLon getCityCenterLatLon() {
|
||||
return cityCenterLatLon;
|
||||
}
|
||||
|
||||
public LatLon getCityAirportLatLon() {
|
||||
return cityAirportLatLon;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = requireMyApplication();
|
||||
mapActivity = getMapActivity();
|
||||
helper = app.getOnlineRoutingHelper();
|
||||
engine = new OnlineRoutingEngineObject();
|
||||
if (savedInstanceState != null) {
|
||||
restoreState(savedInstanceState);
|
||||
} else {
|
||||
initState();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
@Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
view = getInflater().inflate(
|
||||
R.layout.online_routing_engine_fragment, container, false);
|
||||
segmentsContainer = (ViewGroup) view.findViewById(R.id.segments_container);
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
AndroidUtils.addStatusBarPadding21v(getContext(), view);
|
||||
}
|
||||
setupToolbar((Toolbar) view.findViewById(R.id.toolbar));
|
||||
|
||||
setupNameCard();
|
||||
setupServerCard();
|
||||
setupVehicleCard();
|
||||
setupApiKeyCard();
|
||||
setupExampleCard();
|
||||
setupResultsContainer();
|
||||
addSpaceSegment();
|
||||
|
||||
setupButtons();
|
||||
|
||||
updateCardViews(nameCard, serverCard, vehicleCard, exampleCard);
|
||||
return view;
|
||||
}
|
||||
|
||||
private void setupNameCard() {
|
||||
nameCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
||||
nameCard.build(mapActivity);
|
||||
nameCard.setDescription(getString(R.string.select_nav_profile_dialog_message));
|
||||
nameCard.setEditedText(engine.getName(app));
|
||||
nameCard.setFieldBoxLabelText(getString(R.string.shared_string_name));
|
||||
nameCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||
@Override
|
||||
public void onTextChanged(boolean changedByUser, String text) {
|
||||
if (changedByUser) {
|
||||
engine.customName = text;
|
||||
}
|
||||
}
|
||||
});
|
||||
nameCard.showDivider();
|
||||
segmentsContainer.addView(nameCard.getView());
|
||||
}
|
||||
|
||||
private void setupServerCard() {
|
||||
serverCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
||||
serverCard.build(mapActivity);
|
||||
serverCard.setHeaderTitle(getString(R.string.shared_string_type));
|
||||
List<HorizontalSelectionItem> serverItems = new ArrayList<>();
|
||||
for (ServerType server : ServerType.values()) {
|
||||
serverItems.add(new HorizontalSelectionItem(server.getTitle(), server));
|
||||
}
|
||||
serverCard.setSelectionMenu(serverItems, engine.serverType.getTitle(),
|
||||
new CallbackWithObject<HorizontalSelectionItem>() {
|
||||
@Override
|
||||
public boolean processResult(HorizontalSelectionItem result) {
|
||||
ServerType server = (ServerType) result.getObject();
|
||||
if (engine.serverType != server) {
|
||||
engine.serverType = server;
|
||||
updateCardViews(nameCard, serverCard, exampleCard);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
serverCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||
@Override
|
||||
public void onTextChanged(boolean editedByUser, String text) {
|
||||
if (editedByUser) {
|
||||
engine.customServerUrl = text;
|
||||
}
|
||||
}
|
||||
});
|
||||
serverCard.setFieldBoxLabelText(getString(R.string.shared_string_server_url));
|
||||
serverCard.showDivider();
|
||||
segmentsContainer.addView(serverCard.getView());
|
||||
}
|
||||
|
||||
private void setupVehicleCard() {
|
||||
vehicleCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
||||
vehicleCard.build(mapActivity);
|
||||
vehicleCard.setHeaderTitle(getString(R.string.shared_string_vehicle));
|
||||
List<HorizontalSelectionItem> vehicleItems = new ArrayList<>();
|
||||
for (VehicleType vehicle : VehicleType.values()) {
|
||||
vehicleItems.add(new HorizontalSelectionItem(vehicle.getTitle(app), vehicle));
|
||||
}
|
||||
vehicleCard.setSelectionMenu(vehicleItems, engine.vehicleType.getTitle(app),
|
||||
new CallbackWithObject<HorizontalSelectionItem>() {
|
||||
@Override
|
||||
public boolean processResult(HorizontalSelectionItem result) {
|
||||
VehicleType vehicle = (VehicleType) result.getObject();
|
||||
if (engine.vehicleType != vehicle) {
|
||||
engine.vehicleType = vehicle;
|
||||
updateCardViews(nameCard, vehicleCard, exampleCard);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
vehicleCard.setFieldBoxLabelText(getString(R.string.shared_string_custom));
|
||||
vehicleCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||
@Override
|
||||
public void onTextChanged(boolean editedByUser, String text) {
|
||||
if (editedByUser) {
|
||||
engine.customVehicleKey = text;
|
||||
updateCardViews(nameCard, exampleCard);
|
||||
}
|
||||
}
|
||||
});
|
||||
vehicleCard.setEditedText(engine.customVehicleKey);
|
||||
vehicleCard.setFieldBoxHelperText(getString(R.string.shared_string_enter_param));
|
||||
vehicleCard.showDivider();
|
||||
segmentsContainer.addView(vehicleCard.getView());
|
||||
}
|
||||
|
||||
private void setupApiKeyCard() {
|
||||
apiKeyCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
||||
apiKeyCard.build(mapActivity);
|
||||
apiKeyCard.setHeaderTitle(getString(R.string.shared_string_api_key));
|
||||
apiKeyCard.setFieldBoxLabelText(getString(R.string.keep_it_empty_if_not));
|
||||
apiKeyCard.setEditedText(engine.apiKey);
|
||||
apiKeyCard.showDivider();
|
||||
apiKeyCard.setOnTextChangedListener(new OnTextChangedListener() {
|
||||
@Override
|
||||
public void onTextChanged(boolean editedByUser, String text) {
|
||||
engine.apiKey = text;
|
||||
updateCardViews(exampleCard);
|
||||
}
|
||||
});
|
||||
segmentsContainer.addView(apiKeyCard.getView());
|
||||
}
|
||||
|
||||
private void setupExampleCard() {
|
||||
exampleCard = new OnlineRoutingCard(mapActivity, isNightMode());
|
||||
exampleCard.build(mapActivity);
|
||||
exampleCard.setHeaderTitle(getString(R.string.shared_string_example));
|
||||
List<HorizontalSelectionItem> locationItems = new ArrayList<>();
|
||||
for (ExampleLocation location : ExampleLocation.values()) {
|
||||
locationItems.add(new HorizontalSelectionItem(location.getName(), location));
|
||||
}
|
||||
exampleCard.setSelectionMenu(locationItems, selectedLocation.getName(),
|
||||
new CallbackWithObject<HorizontalSelectionItem>() {
|
||||
@Override
|
||||
public boolean processResult(HorizontalSelectionItem result) {
|
||||
ExampleLocation location = (ExampleLocation) result.getObject();
|
||||
if (selectedLocation != location) {
|
||||
selectedLocation = location;
|
||||
updateCardViews(exampleCard);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
exampleCard.setFieldBoxHelperText(getString(R.string.online_routing_example_hint));
|
||||
exampleCard.setButton(getString(R.string.test_route_calculation), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
testEngineWork();
|
||||
}
|
||||
});
|
||||
segmentsContainer.addView(exampleCard.getView());
|
||||
}
|
||||
|
||||
private void setupResultsContainer() {
|
||||
testResultsContainer = getInflater().inflate(
|
||||
R.layout.bottom_sheet_item_with_descr_64dp, segmentsContainer, false);
|
||||
testResultsContainer.setVisibility(View.GONE);
|
||||
segmentsContainer.addView(testResultsContainer);
|
||||
}
|
||||
|
||||
private void addSpaceSegment() {
|
||||
int space = (int) getResources().getDimension(R.dimen.empty_state_text_button_padding_top);
|
||||
View bottomSpaceView = new View(app);
|
||||
bottomSpaceView.setLayoutParams(
|
||||
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, space));
|
||||
segmentsContainer.addView(bottomSpaceView);
|
||||
}
|
||||
|
||||
private void setupToolbar(Toolbar toolbar) {
|
||||
ImageView navigationIcon = toolbar.findViewById(R.id.close_button);
|
||||
navigationIcon.setImageResource(R.drawable.ic_action_close);
|
||||
navigationIcon.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
TextView title = toolbar.findViewById(R.id.toolbar_title);
|
||||
toolbar.findViewById(R.id.toolbar_subtitle).setVisibility(View.GONE);
|
||||
View actionBtn = toolbar.findViewById(R.id.action_button);
|
||||
if (isEditingMode()) {
|
||||
title.setText(getString(R.string.edit_online_routing_engine));
|
||||
ImageView ivBtn = toolbar.findViewById(R.id.action_button_icon);
|
||||
ivBtn.setImageDrawable(
|
||||
getIcon(R.drawable.ic_action_delete_dark, R.color.color_osm_edit_delete));
|
||||
actionBtn.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
deleteEngine();
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
title.setText(getString(R.string.add_online_routing_engine));
|
||||
actionBtn.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateCardViews(BaseCard... cardsToUpdate) {
|
||||
for (BaseCard card : cardsToUpdate) {
|
||||
if (nameCard.equals(card)) {
|
||||
if (Algorithms.isEmpty(engine.customName)) {
|
||||
String name = OnlineRoutingEngine.getStandardName(app, engine.serverType, engine.getVehicleKey());
|
||||
nameCard.setEditedText(name);
|
||||
}
|
||||
|
||||
} else if (serverCard.equals(card)) {
|
||||
serverCard.setHeaderSubtitle(engine.serverType.getTitle());
|
||||
serverCard.setEditedText(engine.getBaseUrl());
|
||||
if (engine.serverType == ServerType.GRAPHHOPER) {
|
||||
apiKeyCard.show();
|
||||
} else {
|
||||
apiKeyCard.hide();
|
||||
}
|
||||
|
||||
} else if (vehicleCard.equals(card)) {
|
||||
vehicleCard.setHeaderSubtitle(engine.vehicleType.getTitle(app));
|
||||
if (engine.vehicleType == VehicleType.CUSTOM) {
|
||||
vehicleCard.showFieldBox();
|
||||
vehicleCard.setEditedText(engine.getVehicleKey());
|
||||
} else {
|
||||
vehicleCard.hideFieldBox();
|
||||
}
|
||||
|
||||
} else if (exampleCard.equals(card)) {
|
||||
exampleCard.setEditedText(getTestUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupButtons() {
|
||||
boolean nightMode = isNightMode();
|
||||
View cancelButton = view.findViewById(R.id.dismiss_button);
|
||||
UiUtilities.setupDialogButton(nightMode, cancelButton,
|
||||
DialogButtonType.SECONDARY, R.string.shared_string_cancel);
|
||||
cancelButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
view.findViewById(R.id.buttons_divider).setVisibility(View.VISIBLE);
|
||||
|
||||
View saveButton = view.findViewById(R.id.right_bottom_button);
|
||||
UiUtilities.setupDialogButton(nightMode, saveButton,
|
||||
UiUtilities.DialogButtonType.PRIMARY, R.string.shared_string_save);
|
||||
saveButton.setVisibility(View.VISIBLE);
|
||||
saveButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
saveChanges();
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveChanges() {
|
||||
OnlineRoutingEngine engineToSave;
|
||||
if (isEditingMode()) {
|
||||
engineToSave = new OnlineRoutingEngine(editedEngineKey, engine.serverType, engine.getVehicleKey());
|
||||
} else {
|
||||
engineToSave = OnlineRoutingEngine.createNewEngine(engine.serverType, engine.getVehicleKey());
|
||||
}
|
||||
|
||||
engineToSave.putParameter(EngineParameterType.CUSTOM_SERVER_URL, engine.customServerUrl);
|
||||
engineToSave.putParameter(EngineParameterType.CUSTOM_NAME, engine.customName);
|
||||
if (engine.serverType == ServerType.GRAPHHOPER) {
|
||||
engineToSave.putParameter(EngineParameterType.API_KEY, engine.apiKey);
|
||||
}
|
||||
|
||||
helper.saveEngine(engineToSave);
|
||||
}
|
||||
|
||||
private void deleteEngine() {
|
||||
helper.deleteEngine(editedEngineKey);
|
||||
}
|
||||
|
||||
private String getTestUrl() {
|
||||
String baseUrl = engine.serverType.getBaseUrl();
|
||||
String vehicle = engine.getVehicleKey();
|
||||
|
||||
LatLon startPoint = selectedLocation.getCityCenterLatLon();
|
||||
LatLon endPoint = selectedLocation.getCityAirportLatLon();
|
||||
|
||||
if (engine.serverType == ServerType.GRAPHHOPER) {
|
||||
return baseUrl + "?" + "point=" + startPoint.getLatitude()
|
||||
+ "," + startPoint.getLongitude()
|
||||
+ "&" + "point=" + endPoint.getLatitude()
|
||||
+ "," + endPoint.getLongitude()
|
||||
+ "&" + "vehicle=" + vehicle
|
||||
+ (!Algorithms.isEmpty(engine.apiKey) ? ("&" + "key=" + engine.apiKey) : "");
|
||||
} else {
|
||||
return baseUrl + vehicle + "/" + startPoint.getLatitude()
|
||||
+ "," + startPoint.getLongitude()
|
||||
+ ";" + endPoint.getLatitude()
|
||||
+ "," + endPoint.getLongitude()
|
||||
+ "?" + "geometries=geojson";
|
||||
}
|
||||
}
|
||||
|
||||
private void testEngineWork() {
|
||||
final ServerType server = engine.serverType;
|
||||
final ExampleLocation location = selectedLocation;
|
||||
AndroidNetworkUtils.sendRequestAsync(app, exampleCard.getEditedText(), null,
|
||||
null, false, false, new OnRequestResultListener() {
|
||||
@Override
|
||||
public void onResult(String response) {
|
||||
boolean resultOk = false;
|
||||
if (response != null) {
|
||||
try {
|
||||
JSONObject obj = new JSONObject(response);
|
||||
|
||||
if (server == ServerType.GRAPHHOPER) {
|
||||
resultOk = obj.has("paths");
|
||||
} else if (server == ServerType.OSRM) {
|
||||
resultOk = obj.has("routes");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
|
||||
}
|
||||
}
|
||||
showTestResults(resultOk, location);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void showTestResults(boolean resultOk, ExampleLocation location) {
|
||||
testResultsContainer.setVisibility(View.VISIBLE);
|
||||
ImageView ivImage = testResultsContainer.findViewById(R.id.icon);
|
||||
TextView tvTitle = testResultsContainer.findViewById(R.id.title);
|
||||
TextView tvDescription = testResultsContainer.findViewById(R.id.description);
|
||||
if (resultOk) {
|
||||
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_gdirections_dark));
|
||||
tvTitle.setText(getString(R.string.shared_string_ok));
|
||||
} else {
|
||||
ivImage.setImageDrawable(getContentIcon(R.drawable.ic_action_alert));
|
||||
tvTitle.setText(getString(R.string.message_error_recheck_parameters));
|
||||
}
|
||||
tvDescription.setText(location.getName());
|
||||
}
|
||||
|
||||
private boolean isEditingMode() {
|
||||
return editedEngineKey != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
saveState(outState);
|
||||
}
|
||||
|
||||
private void saveState(Bundle outState) {
|
||||
outState.putString(ENGINE_NAME_KEY, engine.customName);
|
||||
outState.putString(ENGINE_SERVER_KEY, engine.serverType.name());
|
||||
outState.putString(ENGINE_SERVER_URL_KEY, engine.customServerUrl);
|
||||
outState.putString(ENGINE_VEHICLE_TYPE_KEY, engine.vehicleType.name());
|
||||
outState.putString(ENGINE_CUSTOM_VEHICLE_KEY, engine.customVehicleKey);
|
||||
outState.putString(ENGINE_API_KEY_KEY, engine.apiKey);
|
||||
outState.putString(EXAMPLE_LOCATION_KEY, selectedLocation.name());
|
||||
if (appMode != null) {
|
||||
outState.putString(APP_MODE_KEY, appMode.getStringKey());
|
||||
}
|
||||
outState.putString(EDITED_ENGINE_KEY, editedEngineKey);
|
||||
}
|
||||
|
||||
private void restoreState(Bundle savedState) {
|
||||
engine.customName = savedState.getString(ENGINE_NAME_KEY);
|
||||
engine.serverType = ServerType.valueOf(savedState.getString(ENGINE_SERVER_KEY));
|
||||
engine.customServerUrl = savedState.getString(ENGINE_SERVER_URL_KEY);
|
||||
engine.vehicleType = VehicleType.valueOf(savedState.getString(ENGINE_VEHICLE_TYPE_KEY));
|
||||
engine.customVehicleKey = savedState.getString(ENGINE_CUSTOM_VEHICLE_KEY);
|
||||
engine.apiKey = savedState.getString(ENGINE_API_KEY_KEY);
|
||||
selectedLocation = ExampleLocation.valueOf(savedState.getString(EXAMPLE_LOCATION_KEY));
|
||||
appMode = ApplicationMode.valueOfStringKey(savedState.getString(APP_MODE_KEY), null);
|
||||
editedEngineKey = savedState.getString(EDITED_ENGINE_KEY);
|
||||
}
|
||||
|
||||
private void initState() {
|
||||
engine.serverType = ServerType.values()[0];
|
||||
engine.vehicleType = VehicleType.values()[0];
|
||||
selectedLocation = ExampleLocation.values()[0];
|
||||
|
||||
if (isEditingMode()) {
|
||||
OnlineRoutingEngine editedEngine = helper.getEngineByKey(editedEngineKey);
|
||||
if (editedEngine != null) {
|
||||
engine.customName = editedEngine.getParameter(EngineParameterType.CUSTOM_NAME);
|
||||
engine.serverType = editedEngine.getServerType();
|
||||
engine.customServerUrl = editedEngine.getParameter(EngineParameterType.CUSTOM_SERVER_URL);
|
||||
String vehicleKey = editedEngine.getVehicleKey();
|
||||
if (vehicleKey != null) {
|
||||
VehicleType vehicleType = VehicleType.getVehicleByKey(vehicleKey);
|
||||
if (vehicleType == VehicleType.CUSTOM) {
|
||||
engine.customVehicleKey = vehicleKey;
|
||||
}
|
||||
engine.vehicleType = vehicleType;
|
||||
}
|
||||
engine.apiKey = editedEngine.getParameter(EngineParameterType.API_KEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dismiss() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity != null) {
|
||||
activity.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNightMode() {
|
||||
return !app.getSettings().isLightContentForMode(appMode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MapActivity getMapActivity() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (activity instanceof MapActivity) {
|
||||
return (MapActivity) activity;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private LayoutInflater getInflater() {
|
||||
return UiUtilities.getInflater(mapActivity, isNightMode());
|
||||
}
|
||||
|
||||
public static void showInstance(@NonNull FragmentActivity activity,
|
||||
@NonNull ApplicationMode appMode,
|
||||
String editedEngineKey) {
|
||||
FragmentManager fm = activity.getSupportFragmentManager();
|
||||
if (!fm.isStateSaved() && fm.findFragmentByTag(OnlineRoutingEngineFragment.TAG) == null) {
|
||||
OnlineRoutingEngineFragment fragment = new OnlineRoutingEngineFragment();
|
||||
fragment.appMode = appMode;
|
||||
fragment.editedEngineKey = editedEngineKey;
|
||||
fm.beginTransaction()
|
||||
.add(R.id.fragmentContainer, fragment, TAG)
|
||||
.addToBackStack(TAG).commitAllowingStateLoss();
|
||||
}
|
||||
}
|
||||
|
||||
private static class OnlineRoutingEngineObject {
|
||||
private String customName;
|
||||
private ServerType serverType;
|
||||
private String customServerUrl;
|
||||
private VehicleType vehicleType;
|
||||
private String customVehicleKey;
|
||||
private String apiKey;
|
||||
|
||||
public String getVehicleKey() {
|
||||
if (vehicleType == VehicleType.CUSTOM) {
|
||||
return customVehicleKey;
|
||||
}
|
||||
return vehicleType.getKey();
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return customServerUrl != null ? customServerUrl : serverType.getBaseUrl();
|
||||
}
|
||||
|
||||
public String getName(Context ctx) {
|
||||
if (customName != null) {
|
||||
return customName;
|
||||
}
|
||||
return OnlineRoutingEngine.getStandardName(ctx, serverType, getVehicleKey());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
package net.osmand.plus.onlinerouting;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class OnlineRoutingHelper {
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(OnlineRoutingHelper.class);
|
||||
|
||||
private OsmandApplication app;
|
||||
private OsmandSettings settings;
|
||||
private List<OnlineRoutingEngine> cachedEngines;
|
||||
private Map<String, OnlineRoutingEngine> cachedEnginesMap;
|
||||
|
||||
public OnlineRoutingHelper(OsmandApplication app) {
|
||||
this.app = app;
|
||||
this.settings = app.getSettings();
|
||||
loadFromSettings();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<OnlineRoutingEngine> getEngines() {
|
||||
return cachedEngines;
|
||||
}
|
||||
|
||||
public OnlineRoutingEngine getEngineByKey(String stringKey) {
|
||||
return cachedEnginesMap.get(stringKey);
|
||||
}
|
||||
|
||||
public void saveEngine(@NonNull OnlineRoutingEngine engine) {
|
||||
String stringKey = engine.getStringKey();
|
||||
OnlineRoutingEngine existedEngine = cachedEnginesMap.get(stringKey);
|
||||
if (existedEngine != null) {
|
||||
int index = cachedEngines.indexOf(existedEngine);
|
||||
cachedEngines.set(index, engine);
|
||||
} else {
|
||||
cachedEngines.add(engine);
|
||||
}
|
||||
cachedEnginesMap.put(stringKey, engine);
|
||||
saveToSettings();
|
||||
}
|
||||
|
||||
public void deleteEngine(@NonNull String stringKey) {
|
||||
OnlineRoutingEngine engine = getEngineByKey(stringKey);
|
||||
if (engine != null) {
|
||||
deleteEngine(engine);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteEngine(@NonNull OnlineRoutingEngine engine) {
|
||||
String stringKey = engine.getStringKey();
|
||||
if (cachedEnginesMap.containsKey(stringKey)) {
|
||||
OnlineRoutingEngine existedEngine = cachedEnginesMap.remove(stringKey);
|
||||
cachedEngines.remove(existedEngine);
|
||||
saveToSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromSettings() {
|
||||
cachedEngines = readFromSettings();
|
||||
cachedEnginesMap = new HashMap<>();
|
||||
for (OnlineRoutingEngine engine : cachedEngines) {
|
||||
cachedEnginesMap.put(engine.getStringKey(), engine);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<OnlineRoutingEngine> readFromSettings() {
|
||||
List<OnlineRoutingEngine> engines = new ArrayList<>();
|
||||
String jsonString = settings.ONLINE_ROUTING_ENGINES.get();
|
||||
if (!Algorithms.isEmpty(jsonString)) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(jsonString);
|
||||
readFromJson(json, engines);
|
||||
} catch (JSONException e) {
|
||||
LOG.debug("Error when create a new JSONObject: " + e.toString());
|
||||
}
|
||||
}
|
||||
return engines;
|
||||
}
|
||||
|
||||
private void saveToSettings() {
|
||||
if (!Algorithms.isEmpty(cachedEngines)) {
|
||||
JSONObject json = new JSONObject();
|
||||
if (writeToJson(json, cachedEngines)) {
|
||||
settings.ONLINE_ROUTING_ENGINES.set(json.toString());
|
||||
}
|
||||
} else {
|
||||
settings.ONLINE_ROUTING_ENGINES.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
private static void readFromJson(JSONObject json, List<OnlineRoutingEngine> engines) {
|
||||
try {
|
||||
if (!json.has("items")) {
|
||||
return;
|
||||
}
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<HashMap<String, String>>() {
|
||||
}.getType();
|
||||
JSONArray itemsJson = json.getJSONArray("items");
|
||||
for (int i = 0; i < itemsJson.length(); i++) {
|
||||
JSONObject object = itemsJson.getJSONObject(i);
|
||||
String key = object.getString("key");
|
||||
String vehicleKey = object.getString("vehicle");
|
||||
ServerType serverType = ServerType.valueOf(object.getString("serverType"));
|
||||
String paramsString = object.getString("params");
|
||||
HashMap<String, String> params = gson.fromJson(paramsString, type);
|
||||
engines.add(new OnlineRoutingEngine(key, serverType, vehicleKey, params));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
LOG.debug("Error when reading engines from JSON: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean writeToJson(JSONObject json, List<OnlineRoutingEngine> engines) {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
Gson gson = new Gson();
|
||||
Type type = new TypeToken<HashMap<String, String>>() {
|
||||
}.getType();
|
||||
try {
|
||||
for (OnlineRoutingEngine engine : engines) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("key", engine.getStringKey());
|
||||
jsonObject.put("serverType", engine.getServerType().name());
|
||||
jsonObject.put("vehicle", engine.getVehicleKey());
|
||||
jsonObject.put("params", gson.toJson(engine.getParams(), type));
|
||||
jsonArray.put(jsonObject);
|
||||
}
|
||||
json.put("items", jsonArray);
|
||||
return true;
|
||||
} catch (JSONException e) {
|
||||
LOG.debug("Error when writing engines to JSON: " + e.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
22
OsmAnd/src/net/osmand/plus/onlinerouting/ServerType.java
Normal file
22
OsmAnd/src/net/osmand/plus/onlinerouting/ServerType.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
package net.osmand.plus.onlinerouting;
|
||||
|
||||
public enum ServerType {
|
||||
GRAPHHOPER("Graphhoper", "https://graphhopper.com/api/1/route"),
|
||||
OSRM("OSRM", "https://zlzk.biz/route/v1/");
|
||||
|
||||
ServerType(String title, String baseUrl) {
|
||||
this.title = title;
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
private String title;
|
||||
private String baseUrl;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
}
|
50
OsmAnd/src/net/osmand/plus/onlinerouting/VehicleType.java
Normal file
50
OsmAnd/src/net/osmand/plus/onlinerouting/VehicleType.java
Normal file
|
@ -0,0 +1,50 @@
|
|||
package net.osmand.plus.onlinerouting;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
public enum VehicleType {
|
||||
CAR("car", R.string.routing_engine_vehicle_type_car),
|
||||
BIKE("bike", R.string.routing_engine_vehicle_type_bike),
|
||||
FOOT("foot", R.string.routing_engine_vehicle_type_foot),
|
||||
DRIVING("driving", R.string.routing_engine_vehicle_type_driving),
|
||||
CUSTOM("", R.string.shared_string_custom);
|
||||
|
||||
VehicleType(String key, int titleId) {
|
||||
this.key = key;
|
||||
this.titleId = titleId;
|
||||
}
|
||||
|
||||
private String key;
|
||||
private int titleId;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getTitle(Context ctx) {
|
||||
return ctx.getString(titleId);
|
||||
}
|
||||
|
||||
public static String toHumanString(@NonNull Context ctx,
|
||||
@NonNull String key) {
|
||||
VehicleType vehicleType = getVehicleByKey(key);
|
||||
if (vehicleType == CUSTOM) {
|
||||
return Algorithms.capitalizeFirstLetter(key);
|
||||
}
|
||||
return vehicleType.getTitle(ctx);
|
||||
}
|
||||
|
||||
public static VehicleType getVehicleByKey(String key) {
|
||||
for (VehicleType v : values()) {
|
||||
if (Algorithms.objectEquals(v.getKey(), key)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return CUSTOM;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package net.osmand.plus.profiles;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
|
||||
public class OnlineRoutingEngineDataObject extends ProfileDataObject {
|
||||
|
||||
public OnlineRoutingEngineDataObject(String name,
|
||||
String description,
|
||||
String stringKey) {
|
||||
super(name, description, stringKey, R.drawable.ic_world_globe_dark, false, null);
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@ import android.content.Context;
|
|||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngine;
|
||||
import net.osmand.plus.profiles.RoutingProfileDataObject.RoutingProfilesResources;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.router.GeneralRouter;
|
||||
import net.osmand.router.RoutingConfiguration;
|
||||
|
@ -66,6 +68,15 @@ public class ProfileDataUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static List<OnlineRoutingEngineDataObject> getOnlineRoutingProfiles(OsmandApplication app) {
|
||||
List<OnlineRoutingEngineDataObject> objects = new ArrayList<>();
|
||||
for (OnlineRoutingEngine engine : app.getOnlineRoutingHelper().getEngines()) {
|
||||
objects.add(new OnlineRoutingEngineDataObject(
|
||||
engine.getName(app), engine.getBaseUrl(), engine.getStringKey()));
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
|
||||
public static Map<String, List<RoutingProfileDataObject>> getRoutingProfilesByFileNames(OsmandApplication app) {
|
||||
Map<String, List<RoutingProfileDataObject>> result = new HashMap<>();
|
||||
for (final RoutingProfileDataObject profile : getRoutingProfiles(app).values()) {
|
||||
|
@ -83,24 +94,24 @@ public class ProfileDataUtils {
|
|||
|
||||
public static Map<String, RoutingProfileDataObject> getRoutingProfiles(OsmandApplication context) {
|
||||
Map<String, RoutingProfileDataObject> profilesObjects = new HashMap<>();
|
||||
profilesObjects.put(RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.name(), new RoutingProfileDataObject(
|
||||
RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.name(),
|
||||
context.getString(RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.getStringRes()),
|
||||
profilesObjects.put(RoutingProfilesResources.STRAIGHT_LINE_MODE.name(), new RoutingProfileDataObject(
|
||||
RoutingProfilesResources.STRAIGHT_LINE_MODE.name(),
|
||||
context.getString(RoutingProfilesResources.STRAIGHT_LINE_MODE.getStringRes()),
|
||||
context.getString(R.string.special_routing_type),
|
||||
RoutingProfileDataObject.RoutingProfilesResources.STRAIGHT_LINE_MODE.getIconRes(),
|
||||
RoutingProfilesResources.STRAIGHT_LINE_MODE.getIconRes(),
|
||||
false, null));
|
||||
profilesObjects.put(RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.name(), new RoutingProfileDataObject(
|
||||
RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.name(),
|
||||
context.getString(RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.getStringRes()),
|
||||
profilesObjects.put(RoutingProfilesResources.DIRECT_TO_MODE.name(), new RoutingProfileDataObject(
|
||||
RoutingProfilesResources.DIRECT_TO_MODE.name(),
|
||||
context.getString(RoutingProfilesResources.DIRECT_TO_MODE.getStringRes()),
|
||||
context.getString(R.string.special_routing_type),
|
||||
RoutingProfileDataObject.RoutingProfilesResources.DIRECT_TO_MODE.getIconRes(),
|
||||
RoutingProfilesResources.DIRECT_TO_MODE.getIconRes(),
|
||||
false, null));
|
||||
if (context.getBRouterService() != null) {
|
||||
profilesObjects.put(RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.name(), new RoutingProfileDataObject(
|
||||
RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.name(),
|
||||
context.getString(RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.getStringRes()),
|
||||
profilesObjects.put(RoutingProfilesResources.BROUTER_MODE.name(), new RoutingProfileDataObject(
|
||||
RoutingProfilesResources.BROUTER_MODE.name(),
|
||||
context.getString(RoutingProfilesResources.BROUTER_MODE.getStringRes()),
|
||||
context.getString(R.string.third_party_routing_type),
|
||||
RoutingProfileDataObject.RoutingProfilesResources.BROUTER_MODE.getIconRes(),
|
||||
RoutingProfilesResources.BROUTER_MODE.getIconRes(),
|
||||
false, null));
|
||||
}
|
||||
|
||||
|
@ -123,9 +134,9 @@ public class ProfileDataUtils {
|
|||
String fileName = router.getFilename();
|
||||
if (!Algorithms.isEmpty(fileName)) {
|
||||
description = fileName;
|
||||
} else if (RoutingProfileDataObject.RoutingProfilesResources.isRpValue(name.toUpperCase())) {
|
||||
iconRes = RoutingProfileDataObject.RoutingProfilesResources.valueOf(name.toUpperCase()).getIconRes();
|
||||
name = app.getString(RoutingProfileDataObject.RoutingProfilesResources.valueOf(name.toUpperCase()).getStringRes());
|
||||
} else if (RoutingProfilesResources.isRpValue(name.toUpperCase())) {
|
||||
iconRes = RoutingProfilesResources.valueOf(name.toUpperCase()).getIconRes();
|
||||
name = app.getString(RoutingProfilesResources.valueOf(name.toUpperCase()).getStringRes());
|
||||
}
|
||||
profilesObjects.put(routerKey, new RoutingProfileDataObject(routerKey, name, description,
|
||||
iconRes, false, fileName));
|
||||
|
|
|
@ -22,7 +22,6 @@ import androidx.annotation.Nullable;
|
|||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.CallbackWithObject;
|
||||
|
@ -39,6 +38,7 @@ import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
|||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
|
||||
import net.osmand.plus.onlinerouting.OnlineRoutingEngineFragment;
|
||||
import net.osmand.router.RoutingConfiguration;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -149,17 +149,23 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
items.add(new TitleItem(getString(R.string.select_nav_profile_dialog_title)));
|
||||
items.add(new LongDescriptionItem(getString(R.string.select_nav_profile_dialog_message)));
|
||||
for (int i = 0; i < profiles.size(); i++) {
|
||||
final RoutingProfileDataObject profile = (RoutingProfileDataObject) profiles.get(i);
|
||||
boolean showBottomDivider = false;
|
||||
if (i < profiles.size() - 1) {
|
||||
RoutingProfileDataObject nextProfile = (RoutingProfileDataObject) profiles.get(i + 1);
|
||||
if (profile.getFileName() == null) {
|
||||
showBottomDivider = nextProfile.getFileName() != null;
|
||||
} else {
|
||||
showBottomDivider = !profile.getFileName().equals(nextProfile.getFileName());
|
||||
if (profiles.get(i) instanceof RoutingProfileDataObject) {
|
||||
final RoutingProfileDataObject profile = (RoutingProfileDataObject) profiles.get(i);
|
||||
if (i < profiles.size() - 1) {
|
||||
if (profiles.get(i + 1) instanceof RoutingProfileDataObject) {
|
||||
RoutingProfileDataObject nextProfile = (RoutingProfileDataObject) profiles.get(i + 1);
|
||||
if (profile.getFileName() == null) {
|
||||
showBottomDivider = nextProfile.getFileName() != null;
|
||||
} else {
|
||||
showBottomDivider = !profile.getFileName().equals(nextProfile.getFileName());
|
||||
}
|
||||
} else {
|
||||
showBottomDivider = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
addProfileItem(profile, showBottomDivider);
|
||||
addProfileItem(profiles.get(i), showBottomDivider);
|
||||
}
|
||||
items.add(new DividerItem(app));
|
||||
items.add(new LongDescriptionItem(app.getString(R.string.osmand_routing_promo)));
|
||||
|
@ -179,6 +185,15 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
});
|
||||
}
|
||||
});
|
||||
addButtonItem(R.string.add_online_routing_engine, R.drawable.ic_world_globe_dark, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (getActivity() != null) {
|
||||
OnlineRoutingEngineFragment.showInstance(getActivity(), getAppMode(), null);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
items.add(new BaseBottomSheetItem.Builder()
|
||||
.setCustomView(bottomSpaceView)
|
||||
.create());
|
||||
|
@ -220,7 +235,10 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
int activeColorResId = nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
|
||||
int iconDefaultColorResId = nightMode ? R.color.icon_color_default_dark : R.color.icon_color_default_light;
|
||||
|
||||
View itemView = UiUtilities.getInflater(getContext(), nightMode).inflate(R.layout.bottom_sheet_item_with_descr_and_radio_btn, null);
|
||||
View itemView = UiUtilities.getInflater(getContext(), nightMode).inflate(
|
||||
profile instanceof OnlineRoutingEngineDataObject ?
|
||||
R.layout.bottom_sheet_item_with_descr_radio_and_icon_btn :
|
||||
R.layout.bottom_sheet_item_with_descr_and_radio_btn, null);
|
||||
TextView tvTitle = itemView.findViewById(R.id.title);
|
||||
TextView tvDescription = itemView.findViewById(R.id.description);
|
||||
ImageView ivIcon = itemView.findViewById(R.id.icon);
|
||||
|
@ -253,7 +271,14 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
args.putString(PROFILE_KEY_ARG, profile.getStringKey());
|
||||
Fragment target = getTargetFragment();
|
||||
if (target instanceof OnSelectProfileCallback) {
|
||||
((OnSelectProfileCallback) target).onProfileSelected(args);
|
||||
if (profile instanceof OnlineRoutingEngineDataObject) {
|
||||
if (getActivity() != null) {
|
||||
OnlineRoutingEngineFragment.showInstance(getActivity(), getAppMode(), profile.getStringKey());
|
||||
}
|
||||
dismiss();
|
||||
} else {
|
||||
((OnSelectProfileCallback) target).onProfileSelected(args);
|
||||
}
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
@ -338,6 +363,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
|
||||
case NAVIGATION_PROFILE:
|
||||
profiles.addAll(ProfileDataUtils.getSortedRoutingProfiles(app));
|
||||
profiles.addAll(ProfileDataUtils.getOnlineRoutingProfiles(app));
|
||||
break;
|
||||
|
||||
case DEFAULT_PROFILE:
|
||||
|
@ -358,6 +384,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
public static void showInstance(@NonNull FragmentActivity activity,
|
||||
@NonNull DialogMode dialogMode,
|
||||
@Nullable Fragment target,
|
||||
ApplicationMode appMode,
|
||||
String selectedItemKey,
|
||||
boolean usedOnMap) {
|
||||
SelectProfileBottomSheet fragment = new SelectProfileBottomSheet();
|
||||
|
@ -366,6 +393,7 @@ public class SelectProfileBottomSheet extends BasePreferenceBottomSheet {
|
|||
args.putString(SELECTED_KEY, selectedItemKey);
|
||||
fragment.setArguments(args);
|
||||
fragment.setUsedOnMap(usedOnMap);
|
||||
fragment.setAppMode(appMode);
|
||||
fragment.setTargetFragment(target, 0);
|
||||
fragment.show(activity.getSupportFragmentManager(), TAG);
|
||||
}
|
||||
|
|
|
@ -621,7 +621,11 @@ public class ResourceManager {
|
|||
}
|
||||
}
|
||||
|
||||
public List<String> indexingMaps(final IProgress progress) {
|
||||
public List<String> indexingMaps(IProgress progress) {
|
||||
return indexingMaps(progress, Collections.<File>emptyList());
|
||||
}
|
||||
|
||||
public List<String> indexingMaps(final IProgress progress, List<File> filesToReindex) {
|
||||
long val = System.currentTimeMillis();
|
||||
ArrayList<File> files = new ArrayList<File>();
|
||||
File appPath = context.getAppPath(null);
|
||||
|
@ -688,7 +692,7 @@ public class ResourceManager {
|
|||
try {
|
||||
BinaryMapIndexReader mapReader = null;
|
||||
try {
|
||||
mapReader = cachedOsmandIndexes.getReader(f);
|
||||
mapReader = cachedOsmandIndexes.getReader(f, !filesToReindex.contains(f));
|
||||
if (mapReader.getVersion() != IndexConstants.BINARY_MAP_VERSION) {
|
||||
mapReader = null;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import androidx.annotation.NonNull;
|
|||
import net.osmand.Location;
|
||||
import net.osmand.binary.RouteDataObject;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.plus.routing.data.AnnounceTimeDistances;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.router.RouteSegmentResult;
|
||||
import net.osmand.router.TurnType;
|
||||
|
@ -35,15 +36,16 @@ public class CurrentStreetName {
|
|||
if (l != null && l.hasSpeed()) {
|
||||
speed = l.getSpeed();
|
||||
}
|
||||
AnnounceTimeDistances adt = routingHelper.getVoiceRouter().getAnnounceTimeDistances();
|
||||
boolean isSet = false;
|
||||
// 1. turn is imminent
|
||||
if (n.distanceTo > 0 && n.directionInfo != null && !n.directionInfo.getTurnType().isSkipToSpeak() &&
|
||||
routingHelper.getVoiceRouter().isDistanceLess(speed, n.distanceTo, routingHelper.getVoiceRouter().PREPARE_DISTANCE * 0.75f)) {
|
||||
adt.isTurnStateActive(adt.getSpeed(l), n.distanceTo * 1.3, AnnounceTimeDistances.STATE_PREPARE_TURN)) {
|
||||
String nm = n.directionInfo.getStreetName();
|
||||
String rf = n.directionInfo.getRef();
|
||||
String dn = n.directionInfo.getDestinationName();
|
||||
isSet = !(Algorithms.isEmpty(nm) && Algorithms.isEmpty(rf) && Algorithms.isEmpty(dn));
|
||||
streetName.text = RoutingHelperUtils.formatStreetName(nm, null, dn, "»");
|
||||
streetName.text = RoutingHelperUtils.formatStreetName(nm, rf, dn, "»");
|
||||
streetName.turnType = n.directionInfo.getTurnType();
|
||||
streetName.shieldObject = n.directionInfo.getRouteDataObject();
|
||||
if (streetName.turnType == null) {
|
||||
|
@ -62,7 +64,8 @@ public class CurrentStreetName {
|
|||
if (rs != null) {
|
||||
streetName.text = getRouteSegmentStreetName(routingHelper, rs, false);
|
||||
if (Algorithms.isEmpty(streetName.text)) {
|
||||
isSet = !Algorithms.isEmpty(getRouteSegmentStreetName(routingHelper, rs, true));
|
||||
streetName.text = getRouteSegmentStreetName(routingHelper, rs, true);
|
||||
isSet = !Algorithms.isEmpty(streetName.text);
|
||||
} else {
|
||||
isSet = true;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import net.osmand.plus.OsmandPlugin;
|
|||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.TargetPointsHelper;
|
||||
import net.osmand.plus.TargetPointsHelper.TargetPoint;
|
||||
import net.osmand.plus.helpers.enums.MetricsConstants;
|
||||
import net.osmand.plus.notifications.OsmandNotification.NotificationType;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.plus.routing.RouteProvider.GPXRouteParamsBuilder;
|
||||
|
@ -29,7 +30,6 @@ import net.osmand.router.RouteExporter;
|
|||
import net.osmand.router.RoutePlannerFrontEnd.GpxPoint;
|
||||
import net.osmand.router.RoutePlannerFrontEnd.GpxRouteApproximation;
|
||||
import net.osmand.router.RouteSegmentResult;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -43,12 +43,12 @@ public class RoutingHelper {
|
|||
|
||||
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(RoutingHelper.class);
|
||||
|
||||
public static final float ALLOWED_DEVIATION = 2;
|
||||
|
||||
// This should be correlated with RoutingHelper.updateCurrentRouteStatus ( when processed turn now is not announced)
|
||||
private static final int DEFAULT_GPS_TOLERANCE = 12;
|
||||
public static int GPS_TOLERANCE = DEFAULT_GPS_TOLERANCE;
|
||||
public static float ARRIVAL_DISTANCE_FACTOR = 1;
|
||||
// POS_TOLERANCE
|
||||
// 1) calculate current closest segment of the route during navigation
|
||||
// 2) identify u-turn, projected distance
|
||||
// 3) calculate max allowed deviation before route recalculation * multiplier
|
||||
private static final float POS_TOLERANCE = 60; // 60m or 30m + accuracy
|
||||
private static final float POS_TOLERANCE_DEVIATION_MULTIPLIER = 2;
|
||||
|
||||
private List<WeakReference<IRouteInformationListener>> listeners = new LinkedList<>();
|
||||
private List<WeakReference<IRoutingDataUpdateListener>> updateListeners = new LinkedList<>();
|
||||
|
@ -299,8 +299,6 @@ public class RoutingHelper {
|
|||
|
||||
public void setAppMode(ApplicationMode mode) {
|
||||
this.mode = mode;
|
||||
ARRIVAL_DISTANCE_FACTOR = Math.max(settings.ARRIVAL_DISTANCE_FACTOR.getModeValue(mode), 0.1f);
|
||||
GPS_TOLERANCE = (int) (DEFAULT_GPS_TOLERANCE * ARRIVAL_DISTANCE_FACTOR);
|
||||
voiceRouter.updateAppMode();
|
||||
}
|
||||
|
||||
|
@ -413,7 +411,7 @@ public class RoutingHelper {
|
|||
isDeviatedFromRoute = false;
|
||||
return locationProjection;
|
||||
}
|
||||
float posTolerance = RoutingHelperUtils.getPosTolerance(currentLocation.hasAccuracy() ? currentLocation.getAccuracy() : 0);
|
||||
float posTolerance = getPosTolerance(currentLocation.hasAccuracy() ? currentLocation.getAccuracy() : 0);
|
||||
boolean calculateRoute = false;
|
||||
synchronized (this) {
|
||||
isDeviatedFromRoute = false;
|
||||
|
@ -432,7 +430,7 @@ public class RoutingHelper {
|
|||
int currentRoute = route.currentRoute;
|
||||
double allowableDeviation = route.getRouteRecalcDistance();
|
||||
if (allowableDeviation == 0) {
|
||||
allowableDeviation = RoutingHelperUtils.getDefaultAllowedDeviation(settings, route.getAppMode(), posTolerance);
|
||||
allowableDeviation = RoutingHelper.getDefaultAllowedDeviation(settings, route.getAppMode(), posTolerance);
|
||||
}
|
||||
|
||||
// 2. Analyze if we need to recalculate route
|
||||
|
@ -471,22 +469,12 @@ public class RoutingHelper {
|
|||
voiceRouter.interruptRouteCommands();
|
||||
voiceRouterStopped = true; // Prevents excessive execution of stop() code
|
||||
}
|
||||
if (distOrth > mode.getOffRouteDistance() * ARRIVAL_DISTANCE_FACTOR && !settings.DISABLE_OFFROUTE_RECALC.get()) {
|
||||
voiceRouter.announceOffRoute(distOrth);
|
||||
}
|
||||
voiceRouter.announceOffRoute(distOrth);
|
||||
}
|
||||
|
||||
// calculate projection of current location
|
||||
if (currentRoute > 0) {
|
||||
locationProjection = new Location(currentLocation);
|
||||
Location nextLocation = routeNodes.get(currentRoute);
|
||||
LatLon project = RoutingHelperUtils.getProject(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
|
||||
|
||||
locationProjection.setLatitude(project.getLatitude());
|
||||
locationProjection.setLongitude(project.getLongitude());
|
||||
// we need to update bearing too
|
||||
float bearingTo = locationProjection.bearingTo(nextLocation);
|
||||
locationProjection.setBearing(bearingTo);
|
||||
locationProjection = RoutingHelperUtils.getProject(currentLocation, routeNodes.get(currentRoute - 1), routeNodes.get(currentRoute));
|
||||
}
|
||||
}
|
||||
lastFixedLocation = currentLocation;
|
||||
|
@ -532,8 +520,8 @@ public class RoutingHelper {
|
|||
}
|
||||
processed = true;
|
||||
}
|
||||
} else if (newDist < dist || newDist < GPS_TOLERANCE / 2) {
|
||||
// newDist < GPS_TOLERANCE (avoid distance 0 till next turn)
|
||||
} else if (newDist < dist || newDist < posTolerance / 8) {
|
||||
// newDist < posTolerance / 8 - 4-8 m (avoid distance 0 till next turn)
|
||||
if (dist > posTolerance) {
|
||||
processed = true;
|
||||
if (log.isDebugEnabled()) {
|
||||
|
@ -571,7 +559,7 @@ public class RoutingHelper {
|
|||
|
||||
// 2. check if intermediate found
|
||||
if (route.getIntermediatePointsToPass() > 0
|
||||
&& route.getDistanceToNextIntermediate(lastFixedLocation) < RoutingHelperUtils.getArrivalDistance(mode, settings) * 2f && !isRoutePlanningMode) {
|
||||
&& route.getDistanceToNextIntermediate(lastFixedLocation) < voiceRouter.getArrivalDistance() && !isRoutePlanningMode) {
|
||||
showMessage(app.getString(R.string.arrived_at_intermediate_point));
|
||||
route.passIntermediatePoint();
|
||||
TargetPointsHelper targets = app.getTargetPointsHelper();
|
||||
|
@ -603,7 +591,7 @@ public class RoutingHelper {
|
|||
// 3. check if destination found
|
||||
Location lastPoint = routeNodes.get(routeNodes.size() - 1);
|
||||
if (currentRoute > routeNodes.size() - 3
|
||||
&& currentLocation.distanceTo(lastPoint) < RoutingHelperUtils.getArrivalDistance(mode, settings)
|
||||
&& currentLocation.distanceTo(lastPoint) < voiceRouter.getArrivalDistance()
|
||||
&& !isRoutePlanningMode) {
|
||||
//showMessage(app.getString(R.string.arrived_at_destination));
|
||||
TargetPointsHelper targets = app.getTargetPointsHelper();
|
||||
|
@ -612,8 +600,7 @@ public class RoutingHelper {
|
|||
if (isFollowingMode) {
|
||||
voiceRouter.arrivedDestinationPoint(description);
|
||||
}
|
||||
boolean onDestinationReached = OsmandPlugin.onDestinationReached();
|
||||
onDestinationReached &= app.getAppCustomization().onDestinationReached();
|
||||
boolean onDestinationReached = true;
|
||||
if (onDestinationReached) {
|
||||
clearCurrentRoute(null, null);
|
||||
setRoutePlanningMode(false);
|
||||
|
@ -672,6 +659,37 @@ public class RoutingHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static float getPosTolerance(float accuracy) {
|
||||
if (accuracy > 0) {
|
||||
return POS_TOLERANCE / 2 + accuracy;
|
||||
}
|
||||
return POS_TOLERANCE;
|
||||
}
|
||||
|
||||
private static float getDefaultAllowedDeviation(OsmandSettings settings, ApplicationMode mode, float posTolerance) {
|
||||
if (settings.DISABLE_OFFROUTE_RECALC.getModeValue(mode)) {
|
||||
return -1.0f;
|
||||
} else if (mode.getRouteService() == RouteProvider.RouteService.DIRECT_TO) {
|
||||
return -1.0f;
|
||||
} else if (mode.getRouteService() == RouteProvider.RouteService.STRAIGHT) {
|
||||
MetricsConstants mc = settings.METRIC_SYSTEM.getModeValue(mode);
|
||||
if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == MetricsConstants.MILES_AND_METERS) {
|
||||
return 500.f;
|
||||
} else {
|
||||
// 1/4 mile
|
||||
return 482.f;
|
||||
}
|
||||
}
|
||||
return posTolerance * POS_TOLERANCE_DEVIATION_MULTIPLIER;
|
||||
}
|
||||
|
||||
public static float getDefaultAllowedDeviation(OsmandSettings settings, ApplicationMode mode) {
|
||||
return getDefaultAllowedDeviation(settings, mode, getPosTolerance(0));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void fireRoutingDataUpdateEvent() {
|
||||
if (!updateListeners.isEmpty()) {
|
||||
ArrayList<WeakReference<IRoutingDataUpdateListener>> tmp = new ArrayList<>(updateListeners);
|
||||
|
|
|
@ -17,7 +17,6 @@ import java.util.List;
|
|||
|
||||
public class RoutingHelperUtils {
|
||||
|
||||
private static final float POSITION_TOLERANCE = 60;
|
||||
private static final int CACHE_RADIUS = 100000;
|
||||
|
||||
@NonNull
|
||||
|
@ -66,10 +65,17 @@ public class RoutingHelperUtils {
|
|||
return rect.left == 0 && rect.right == 0 ? null : rect;
|
||||
}
|
||||
|
||||
static LatLon getProject(Location loc, Location from, Location to) {
|
||||
return MapUtils.getProjection(loc.getLatitude(),
|
||||
static Location getProject(Location loc, Location from, Location to) {
|
||||
LatLon project = MapUtils.getProjection(loc.getLatitude(),
|
||||
loc.getLongitude(), from.getLatitude(), from.getLongitude(),
|
||||
to.getLatitude(), to.getLongitude());
|
||||
Location locationProjection = new Location(loc);
|
||||
locationProjection.setLatitude(project.getLatitude());
|
||||
locationProjection.setLongitude(project.getLongitude());
|
||||
// we need to update bearing too
|
||||
float bearingTo = locationProjection.bearingTo(to);
|
||||
locationProjection.setBearing(bearingTo);
|
||||
return locationProjection;
|
||||
}
|
||||
|
||||
static double getOrthogonalDistance(Location loc, Location from, Location to) {
|
||||
|
@ -94,30 +100,6 @@ public class RoutingHelperUtils {
|
|||
return index;
|
||||
}
|
||||
|
||||
public static float getPosTolerance(float accuracy) {
|
||||
if (accuracy > 0) {
|
||||
return POSITION_TOLERANCE / 2 + accuracy;
|
||||
}
|
||||
return POSITION_TOLERANCE;
|
||||
}
|
||||
|
||||
public static float getDefaultAllowedDeviation(OsmandSettings settings, ApplicationMode mode, float posTolerance) {
|
||||
if (settings.DISABLE_OFFROUTE_RECALC.getModeValue(mode)) {
|
||||
return -1.0f;
|
||||
} else if (mode.getRouteService() == RouteProvider.RouteService.DIRECT_TO) {
|
||||
return -1.0f;
|
||||
} else if (mode.getRouteService() == RouteProvider.RouteService.STRAIGHT) {
|
||||
MetricsConstants mc = settings.METRIC_SYSTEM.getModeValue(mode);
|
||||
if (mc == MetricsConstants.KILOMETERS_AND_METERS || mc == MetricsConstants.MILES_AND_METERS) {
|
||||
return 500.f;
|
||||
} else {
|
||||
// 1/4 mile
|
||||
return 482.f;
|
||||
}
|
||||
}
|
||||
return posTolerance * RoutingHelper.ALLOWED_DEVIATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrong movement direction is considered when between
|
||||
* current location bearing (determines by 2 last fixed position or provided)
|
||||
|
@ -181,16 +163,6 @@ public class RoutingHelperUtils {
|
|||
return isOffRoute;
|
||||
}
|
||||
|
||||
static float getArrivalDistance(ApplicationMode mode, OsmandSettings settings) {
|
||||
ApplicationMode m = mode == null ? settings.getApplicationMode() : mode;
|
||||
float defaultSpeed = Math.max(0.3f, m.getDefaultSpeed());
|
||||
|
||||
/// Used to be: car - 90 m, bicycle - 50 m, pedestrian - 20 m
|
||||
// return ((float)settings.getApplicationMode().getArrivalDistance()) * settings.ARRIVAL_DISTANCE_FACTOR.getModeValue(m);
|
||||
// GPS_TOLERANCE - 12 m
|
||||
// 5 seconds: car - 80 m @ 50 kmh, bicyle - 45 m @ 25 km/h, bicyle - 25 m @ 10 km/h, pedestrian - 18 m @ 4 km/h,
|
||||
return RoutingHelper.GPS_TOLERANCE + defaultSpeed * 5 * RoutingHelper.ARRIVAL_DISTANCE_FACTOR;
|
||||
}
|
||||
|
||||
public static void checkAndUpdateStartLocation(@NonNull OsmandApplication app, LatLon newStartLocation) {
|
||||
if (newStartLocation != null) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import net.osmand.plus.OsmandApplication;
|
|||
import net.osmand.plus.helpers.WaypointHelper.LocationPointWrapper;
|
||||
import net.osmand.plus.routing.AlarmInfo.AlarmInfoType;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.plus.routing.data.AnnounceTimeDistances;
|
||||
import net.osmand.plus.routing.data.StreetName;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmAndAppCustomization.OsmAndAppCustomizationListener;
|
||||
|
@ -35,6 +36,11 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_LONG_PREPARE_TURN;
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_PREPARE_TURN;
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_TURN_IN;
|
||||
import static net.osmand.plus.routing.data.AnnounceTimeDistances.STATE_TURN_NOW;
|
||||
|
||||
|
||||
public class VoiceRouter {
|
||||
private static final int STATUS_UTWP_TOLD = -1;
|
||||
|
@ -57,6 +63,8 @@ public class VoiceRouter {
|
|||
protected final OsmandApplication app;
|
||||
protected final RoutingHelper router;
|
||||
protected OsmandSettings settings;
|
||||
private ApplicationMode appMode;
|
||||
private AnnounceTimeDistances atd;
|
||||
|
||||
private int currentStatus = STATUS_UNKNOWN;
|
||||
private boolean playedAndArriveAtTarget = false;
|
||||
|
@ -69,19 +77,8 @@ public class VoiceRouter {
|
|||
private boolean announceBackOnRoute = false;
|
||||
// private long lastTimeRouteRecalcAnnounced = 0;
|
||||
// Remember when last announcement was made
|
||||
private long lastAnnouncement = 0;
|
||||
private long lastAnnouncement = 0;
|
||||
|
||||
// Default speed to have comfortable announcements (Speed in m/s)
|
||||
private float DEFAULT_SPEED = 12;
|
||||
private float TURN_NOW_SPEED;
|
||||
|
||||
private int PREPARE_LONG_DISTANCE;
|
||||
private int PREPARE_LONG_DISTANCE_END;
|
||||
protected int PREPARE_DISTANCE;
|
||||
private int PREPARE_DISTANCE_END;
|
||||
private int TURN_IN_DISTANCE;
|
||||
private int TURN_IN_DISTANCE_END;
|
||||
private int TURN_NOW_DISTANCE;
|
||||
|
||||
private SoundPool soundPool;
|
||||
private int soundClick = -1;
|
||||
|
@ -89,6 +86,7 @@ public class VoiceRouter {
|
|||
private VoiceCommandPending pendingCommand = null;
|
||||
private RouteDirectionInfo nextRouteDirection;
|
||||
|
||||
|
||||
public interface VoiceMessageListener {
|
||||
void onVoiceMessage(List<String> listCommands, List<String> played);
|
||||
}
|
||||
|
@ -179,103 +177,12 @@ public class VoiceRouter {
|
|||
|
||||
|
||||
public void updateAppMode() {
|
||||
ApplicationMode appMode = router.getAppMode() == null ? settings.getApplicationMode() : router.getAppMode();
|
||||
if (appMode.isDerivedRoutingFrom(ApplicationMode.CAR)) {
|
||||
// could be changed in future as others by default in settings is 45 kmh
|
||||
DEFAULT_SPEED = 14; // ~50 km/h
|
||||
//DEFAULT speed is configurable
|
||||
// } else if (router.getAppMode().isDerivedRoutingFrom(ApplicationMode.BICYCLE)) {
|
||||
// DEFAULT_SPEED = 2.77f; // 10 km/h
|
||||
// } else if (router.getAppMode().isDerivedRoutingFrom(ApplicationMode.PEDESTRIAN)) {
|
||||
// DEFAULT_SPEED = 1.11f; //4 km/h 2f; // 7,2 km/h
|
||||
} else {
|
||||
// minimal is 1 meter for turn now
|
||||
DEFAULT_SPEED = (float) Math.max(0.3, appMode.getDefaultSpeed());
|
||||
}
|
||||
|
||||
|
||||
// Do not play [issue 1411]: prepare_long_distance warning not needed, used only for goAhead prompt
|
||||
// 300 sec: 4 200 - 3 500 m - car [ 115 - 95 sec @ 120 km/h]
|
||||
PREPARE_LONG_DISTANCE = (int) (DEFAULT_SPEED * 300);
|
||||
PREPARE_LONG_DISTANCE_END = (int) (DEFAULT_SPEED * 250) ;
|
||||
|
||||
if (DEFAULT_SPEED < 30) {
|
||||
// if (PREPARE_LONG_DISTANCE_END - PREPARE_DISTANCE < 4000) {
|
||||
// Play only for high speed vehicle with speed > 110 km/h
|
||||
PREPARE_DISTANCE_END = PREPARE_DISTANCE * 2;
|
||||
}
|
||||
|
||||
// *#8749: Here the change for bicycle: 40-30 sec, 200-150 m -> 115-90 sec, 320-250m [ need to be tested ]
|
||||
// 115 sec: 1 500 m - car [45 sec @ 120 km/h], 320 m - bicycle [45 sec @ 25 km/h], 230 m - pedestrian
|
||||
PREPARE_DISTANCE = (int) (DEFAULT_SPEED * 115);
|
||||
// 90 sec: 1 200 m - car, 250 m - bicycle [36 sec @ 25 km/h],
|
||||
PREPARE_DISTANCE_END = (int) (DEFAULT_SPEED * 90);
|
||||
|
||||
// 22 sec: 310 m - car, 60 m - bicycle, 50m - pedestrian
|
||||
TURN_IN_DISTANCE = (int) (DEFAULT_SPEED * 22);
|
||||
// 15 sec: 210 m - car, 40 m - bicycle, 30 m - pedestrian
|
||||
TURN_IN_DISTANCE_END = (int) (DEFAULT_SPEED * 15);
|
||||
|
||||
// same as speed < 150/(90-22) m/s = 2.2 m/s = 8 km/h
|
||||
if (PREPARE_DISTANCE_END - TURN_IN_DISTANCE < 150) {
|
||||
// Do not play: for pedestrian and slow transport
|
||||
PREPARE_DISTANCE_END = PREPARE_DISTANCE * 2;
|
||||
}
|
||||
|
||||
// Turn now: 3.5 sec normal speed, 7 second for halfspeed (default)
|
||||
// float TURN_NOW_TIME = 7;
|
||||
|
||||
// ** #8749 to keep 1m / 1 sec precision (GPS_TOLERANCE - 12 m)
|
||||
// 1 kmh - 1 m, 4 kmh - 4 m (pedestrian), 10 kmh - 10 m (bicycle), 50 kmh - 50 m (car)
|
||||
// TURN_NOW_DISTANCE = (int) (DEFAULT_SPEED * 3.6); // 3.6 sec
|
||||
// 50 kmh - 48 m (car), 10 kmh - 20 m, 4 kmh - 15 m, 1 kmh - 12 m
|
||||
TURN_NOW_DISTANCE = (int) (RoutingHelper.GPS_TOLERANCE + DEFAULT_SPEED * 2.5 * RoutingHelper.ARRIVAL_DISTANCE_FACTOR); // 3.6 sec
|
||||
// 1 kmh - 1 sec, 4 kmh - 2 sec (pedestrian), 10 kmh - 3 sec (*bicycle), 50 kmh - 7 sec (car)
|
||||
float TURN_NOW_TIME = (float) Math.min(Math.sqrt(DEFAULT_SPEED * 3.6), 8);
|
||||
|
||||
TURN_NOW_SPEED = TURN_NOW_DISTANCE / TURN_NOW_TIME;
|
||||
}
|
||||
|
||||
private double voicePromptDelayDistance = 0;
|
||||
|
||||
public boolean isDistanceLess(float currentSpeed, double dist, double etalon) {
|
||||
return isDistanceLess(currentSpeed, dist, etalon, DEFAULT_SPEED);
|
||||
}
|
||||
|
||||
|
||||
private boolean isDistanceLess(float currentSpeed, double dist, double etalon, float defSpeed) {
|
||||
if (currentSpeed <= 0) {
|
||||
currentSpeed = DEFAULT_SPEED;
|
||||
}
|
||||
// Trigger close prompts earlier to allow BT SCO link being established, or when VOICE_PROMPT_DELAY is set >0 for the other stream types
|
||||
int ams = settings.AUDIO_MANAGER_STREAM.getModeValue(router.getAppMode());
|
||||
if ((ams == 0 && !AbstractPrologCommandPlayer.btScoStatus) || ams > 0) {
|
||||
if (settings.VOICE_PROMPT_DELAY[ams] != null) {
|
||||
voicePromptDelayDistance = currentSpeed * (double) settings.VOICE_PROMPT_DELAY[ams].get() / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (dist - voicePromptDelayDistance < etalon ||
|
||||
(dist - voicePromptDelayDistance) / currentSpeed < etalon / defSpeed) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
appMode = router.getAppMode() == null ? settings.getApplicationMode() : router.getAppMode();
|
||||
atd = new AnnounceTimeDistances(appMode, settings);
|
||||
}
|
||||
|
||||
public int calculateImminent(float dist, Location loc) {
|
||||
float speed = DEFAULT_SPEED;
|
||||
if (loc != null && loc.hasSpeed()) {
|
||||
speed = loc.getSpeed();
|
||||
}
|
||||
if (isDistanceLess(speed, dist, TURN_NOW_DISTANCE)) {
|
||||
return 0;
|
||||
} else if (dist <= PREPARE_DISTANCE) {
|
||||
return 1;
|
||||
} else if (dist <= PREPARE_LONG_DISTANCE) {
|
||||
return 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return atd.getImminentTurnStatus(dist, loc);
|
||||
}
|
||||
|
||||
private void nextStatusAfter(int previousStatus) {
|
||||
|
@ -290,22 +197,32 @@ public class VoiceRouter {
|
|||
private boolean statusNotPassed(int statusToCheck) {
|
||||
return currentStatus <= statusToCheck;
|
||||
}
|
||||
|
||||
|
||||
public AnnounceTimeDistances getAnnounceTimeDistances() {
|
||||
return atd;
|
||||
}
|
||||
|
||||
public float getArrivalDistance() {
|
||||
return atd.getArrivalDistance();
|
||||
}
|
||||
|
||||
public void announceOffRoute(double dist) {
|
||||
long ms = System.currentTimeMillis();
|
||||
if (waitAnnouncedOffRoute == 0 || ms - lastAnnouncedOffRoute > waitAnnouncedOffRoute) {
|
||||
CommandBuilder p = getNewCommandPlayerToPlay();
|
||||
if (p != null) {
|
||||
p.offRoute(dist);
|
||||
announceBackOnRoute = true;
|
||||
if (dist > atd.getOffRouteDistance() && !settings.DISABLE_OFFROUTE_RECALC.get()) {
|
||||
long ms = System.currentTimeMillis();
|
||||
if (waitAnnouncedOffRoute == 0 || ms - lastAnnouncedOffRoute > waitAnnouncedOffRoute) {
|
||||
CommandBuilder p = getNewCommandPlayerToPlay();
|
||||
if (p != null) {
|
||||
p.offRoute(dist);
|
||||
announceBackOnRoute = true;
|
||||
}
|
||||
play(p);
|
||||
if (waitAnnouncedOffRoute == 0) {
|
||||
waitAnnouncedOffRoute = 60000;
|
||||
} else {
|
||||
waitAnnouncedOffRoute *= 2.5;
|
||||
}
|
||||
lastAnnouncedOffRoute = ms;
|
||||
}
|
||||
play(p);
|
||||
if (waitAnnouncedOffRoute == 0) {
|
||||
waitAnnouncedOffRoute = 60000;
|
||||
} else {
|
||||
waitAnnouncedOffRoute *= 2.5;
|
||||
}
|
||||
lastAnnouncedOffRoute = ms;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,15 +403,7 @@ public class VoiceRouter {
|
|||
* @param currentLocation
|
||||
*/
|
||||
protected void updateStatus(Location currentLocation, boolean repeat) {
|
||||
// Directly after turn: goAhead (dist), unless:
|
||||
// < PREPARE_LONG_DISTANCE (e.g. 3500m): playPrepareTurn (-not played any more-)
|
||||
// < PREPARE_DISTANCE (e.g. 1500m): playPrepareTurn ("Turn after ...")
|
||||
// < TURN_IN_DISTANCE (e.g. 390m or 30sec): playMakeTurnIn ("Turn in ...")
|
||||
// < TURN_NOW_DISTANCE (e.g. 50m or 7sec): playMakeTurn ("Turn ...")
|
||||
float speed = DEFAULT_SPEED;
|
||||
if (currentLocation != null && currentLocation.hasSpeed()) {
|
||||
speed = Math.max(currentLocation.getSpeed(), speed);
|
||||
}
|
||||
float speed = atd.getSpeed(currentLocation);
|
||||
|
||||
NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new NextDirectionInfo(), true);
|
||||
RouteSegmentResult currentSegment = router.getCurrentSegmentResult();
|
||||
|
@ -531,23 +440,24 @@ public class VoiceRouter {
|
|||
|
||||
if (currentStatus == STATUS_UNKNOWN) {
|
||||
// Play "Continue for ..." if (1) after route calculation if no other prompt is due, or (2) after a turn if next turn is more than PREPARE_LONG_DISTANCE away
|
||||
if ((playGoAheadDist == -1) || (dist > PREPARE_LONG_DISTANCE)) {
|
||||
playGoAheadDist = dist - 3 * TURN_NOW_DISTANCE;
|
||||
if ((playGoAheadDist == -1) || !atd.isTurnStateActive(0, dist, STATE_LONG_PREPARE_TURN)) {
|
||||
// 10 seconds
|
||||
playGoAheadDist = dist - 10 * speed;
|
||||
}
|
||||
}
|
||||
|
||||
NextDirectionInfo nextNextInfo = router.getNextRouteDirectionInfoAfter(nextInfo, new NextDirectionInfo(), true); //I think "true" is correct here, not "!repeat"
|
||||
// Note: getNextRouteDirectionInfoAfter(nextInfo, x, y).distanceTo is distance from nextInfo, not from current position!
|
||||
|
||||
// STATUS_TURN = "Turn (now)"
|
||||
if ((repeat || statusNotPassed(STATUS_TURN)) && isDistanceLess(speed, dist, TURN_NOW_DISTANCE, TURN_NOW_SPEED)) {
|
||||
if (nextNextInfo.distanceTo < TURN_IN_DISTANCE_END && nextNextInfo != null) {
|
||||
if ((repeat || statusNotPassed(STATUS_TURN)) && atd.isTurnStateActive(speed, dist, STATE_TURN_NOW)) {
|
||||
if (nextNextInfo != null && !atd.isTurnStateNotPassed(0, nextNextInfo.distanceTo, STATE_TURN_IN )) {
|
||||
playMakeTurn(currentSegment, next, nextNextInfo);
|
||||
} else {
|
||||
playMakeTurn(currentSegment, next, null);
|
||||
}
|
||||
if (!next.getTurnType().goAhead() && isTargetPoint(nextNextInfo)) { // !goAhead() avoids isolated "and arrive.." prompt, as goAhead() is not pronounced
|
||||
if (nextNextInfo.distanceTo < TURN_IN_DISTANCE_END) {
|
||||
if (!next.getTurnType().goAhead() && isTargetPoint(nextNextInfo) && nextNextInfo != null) {
|
||||
// !goAhead() avoids isolated "and arrive.." prompt, as goAhead() is not pronounced
|
||||
if (!atd.isTurnStateNotPassed(0, nextNextInfo.distanceTo, STATE_TURN_IN )) {
|
||||
// Issue #2865: Ensure a distance associated with the destination arrival is always announced, either here, or in subsequent "Turn in" prompt
|
||||
// Distance fon non-straights already announced in "Turn (now)"'s nextnext code above
|
||||
if ((nextNextInfo != null) && (nextNextInfo.directionInfo != null) && nextNextInfo.directionInfo.getTurnType().goAhead()) {
|
||||
|
@ -555,7 +465,7 @@ public class VoiceRouter {
|
|||
playGoAhead(nextNextInfo.distanceTo, new StreetName());
|
||||
}
|
||||
playAndArriveAtDestination(nextNextInfo);
|
||||
} else if (nextNextInfo.distanceTo < 1.2f * TURN_IN_DISTANCE_END) {
|
||||
} else if (!atd.isTurnStateNotPassed(0, nextNextInfo.distanceTo / 1.2f, STATE_TURN_IN )) {
|
||||
// 1.2 is safety margin should the subsequent "Turn in" prompt not fit in amy more
|
||||
playThen();
|
||||
playGoAhead(nextNextInfo.distanceTo, new StreetName());
|
||||
|
@ -565,33 +475,33 @@ public class VoiceRouter {
|
|||
nextStatusAfter(STATUS_TURN);
|
||||
|
||||
// STATUS_TURN_IN = "Turn in ..."
|
||||
} else if ((repeat || statusNotPassed(STATUS_TURN_IN)) && isDistanceLess(speed, dist, TURN_IN_DISTANCE)) {
|
||||
if (repeat || dist >= TURN_IN_DISTANCE_END) {
|
||||
if ((isDistanceLess(speed, nextNextInfo.distanceTo, TURN_NOW_DISTANCE) || nextNextInfo.distanceTo < TURN_IN_DISTANCE_END) &&
|
||||
nextNextInfo != null) {
|
||||
playMakeTurnIn(currentSegment, next, dist - (int) voicePromptDelayDistance, nextNextInfo.directionInfo);
|
||||
} else if ((repeat || statusNotPassed(STATUS_TURN_IN)) && atd.isTurnStateActive(speed, dist, STATE_TURN_IN)) {
|
||||
if (repeat || atd.isTurnStateNotPassed(0, dist, STATE_TURN_IN)) {
|
||||
if (nextNextInfo != null && (atd.isTurnStateActive(speed, nextNextInfo.distanceTo, STATE_TURN_NOW)
|
||||
|| !atd.isTurnStateNotPassed(speed, nextNextInfo.distanceTo, STATE_TURN_IN))) {
|
||||
playMakeTurnIn(currentSegment, next, atd.calcDistanceWithoutDelay(speed, dist), nextNextInfo.directionInfo);
|
||||
} else {
|
||||
playMakeTurnIn(currentSegment, next, dist - (int) voicePromptDelayDistance, null);
|
||||
playMakeTurnIn(currentSegment, next, atd.calcDistanceWithoutDelay(speed, dist), null);
|
||||
}
|
||||
playGoAndArriveAtDestination(repeat, nextInfo, currentSegment);
|
||||
}
|
||||
nextStatusAfter(STATUS_TURN_IN);
|
||||
|
||||
// STATUS_PREPARE = "Turn after ..."
|
||||
} else if ((repeat || statusNotPassed(STATUS_PREPARE)) && (dist <= PREPARE_DISTANCE)) {
|
||||
if (repeat || dist >= PREPARE_DISTANCE_END) {
|
||||
} else if ((repeat || statusNotPassed(STATUS_PREPARE)) && atd.isTurnStateActive(0, dist, STATE_PREPARE_TURN)) {
|
||||
if (repeat || atd.isTurnStateNotPassed(0, dist, STATE_PREPARE_TURN)) {
|
||||
if (!repeat && (next.getTurnType().keepLeft() || next.getTurnType().keepRight())) {
|
||||
// Do not play prepare for keep left/right
|
||||
} else {
|
||||
playPrepareTurn(currentSegment, next, dist);
|
||||
playPrepareTurn(currentSegment, next, atd.calcDistanceWithoutDelay(speed, dist));
|
||||
playGoAndArriveAtDestination(repeat, nextInfo, currentSegment);
|
||||
}
|
||||
}
|
||||
nextStatusAfter(STATUS_PREPARE);
|
||||
|
||||
// STATUS_LONG_PREPARE = also "Turn after ...", we skip this now, users said this is obsolete
|
||||
} else if ((repeat || statusNotPassed(STATUS_LONG_PREPARE)) && (dist <= PREPARE_LONG_DISTANCE)) {
|
||||
if (repeat || dist >= PREPARE_LONG_DISTANCE_END) {
|
||||
} else if ((repeat || statusNotPassed(STATUS_LONG_PREPARE)) && atd.isTurnStateActive(0, dist, STATE_LONG_PREPARE_TURN)) {
|
||||
if (repeat || atd.isTurnStateNotPassed(0, dist, STATE_LONG_PREPARE_TURN)) {
|
||||
playPrepareTurn(currentSegment, next, dist);
|
||||
playGoAndArriveAtDestination(repeat, nextInfo, currentSegment);
|
||||
}
|
||||
|
@ -835,7 +745,8 @@ public class VoiceRouter {
|
|||
playGoAhead(nextInfo.distanceTo, getSpeakableStreetName(currentSegment, next, false));
|
||||
playAndArriveAtDestination(nextInfo);
|
||||
playedAndArriveAtTarget = true;
|
||||
} else if (nextInfo.distanceTo <= 2 * TURN_IN_DISTANCE) {
|
||||
} else if (nextInfo != null &&
|
||||
atd.isTurnStateActive(0, nextInfo.distanceTo / 2, STATE_TURN_IN)) {
|
||||
playAndArriveAtDestination(nextInfo);
|
||||
playedAndArriveAtTarget = true;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
package net.osmand.plus.routing.data;
|
||||
|
||||
import net.osmand.Location;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.voice.AbstractPrologCommandPlayer;
|
||||
|
||||
public class AnnounceTimeDistances {
|
||||
// Avoids false negatives: Pre-pone close announcements by this distance to allow for the possible over-estimation of the 'true' lead distance due to positioning error.
|
||||
// A smaller value will increase the timing precision, but at the risk of missing prompts which do not meet the precision limit.
|
||||
// We can research if a flexible value like min(12, x * gps-hdop) has advantages over a constant (x could be 2 or so).
|
||||
private static final int POSITIONING_TOLERANCE = 12;
|
||||
|
||||
public final static int STATE_TURN_NOW = 0;
|
||||
public final static int STATE_TURN_IN = 1;
|
||||
public final static int STATE_PREPARE_TURN = 2;
|
||||
public final static int STATE_LONG_PREPARE_TURN = 3;
|
||||
public final static int STATE_SHORT_ALARM_ANNOUNCE = 4;
|
||||
public final static int STATE_LONG_ALARM_ANNOUNCE = 5;
|
||||
public final static int STATE_SHORT_PNT_APPROACH = 6;
|
||||
public final static int STATE_LONG_PNT_APPROACH = 7;
|
||||
|
||||
// Default speed to have comfortable announcements (m/s)
|
||||
// initial value is updated from default speed settings anyway
|
||||
private float DEFAULT_SPEED = 10;
|
||||
private double voicePromptDelayTimeSec = 0;
|
||||
|
||||
private float ARRIVAL_DISTANCE;
|
||||
private float OFF_ROUTE_DISTANCE;
|
||||
|
||||
private float TURN_NOW_SPEED;
|
||||
private int PREPARE_LONG_DISTANCE;
|
||||
private int PREPARE_LONG_DISTANCE_END;
|
||||
private int PREPARE_DISTANCE;
|
||||
private int PREPARE_DISTANCE_END;
|
||||
private int TURN_IN_DISTANCE;
|
||||
private int TURN_IN_DISTANCE_END;
|
||||
private int TURN_NOW_DISTANCE;
|
||||
private int LONG_PNT_ANNOUNCE_RADIUS;
|
||||
private int SHORT_PNT_ANNOUNCE_RADIUS;
|
||||
private int LONG_ALARM_ANNOUNCE_RADIUS;
|
||||
private int SHORT_ALARM_ANNOUNCE_RADIUS;
|
||||
|
||||
public AnnounceTimeDistances(ApplicationMode appMode, OsmandSettings settings) {
|
||||
if (appMode.isDerivedRoutingFrom(ApplicationMode.CAR)) {
|
||||
// keep it as minimum 30 km/h for voice announcement
|
||||
DEFAULT_SPEED = (float) Math.max(8, appMode.getDefaultSpeed());
|
||||
} else {
|
||||
// minimal is 1 meter for turn now
|
||||
DEFAULT_SPEED = (float) Math.max(0.3, appMode.getDefaultSpeed());
|
||||
}
|
||||
|
||||
// 300 s: car 3750 m (113 s @ 120 km/h)
|
||||
PREPARE_LONG_DISTANCE = (int) (DEFAULT_SPEED * 300);
|
||||
// 250 s: car 3125 m (94 s @ 120 km/h)
|
||||
PREPARE_LONG_DISTANCE_END = (int) (DEFAULT_SPEED * 250);
|
||||
if (DEFAULT_SPEED < 30) {
|
||||
// Play only for high speed vehicle with speed > 110 km/h
|
||||
// [issue 1411] - used only for goAhead prompt
|
||||
PREPARE_LONG_DISTANCE_END = PREPARE_LONG_DISTANCE * 2;
|
||||
}
|
||||
|
||||
// 115 s: car 1438 m (45 s @ 120 km/h), bicycle 319 m (46 s @ 25 km/h), pedestrian 128 m
|
||||
PREPARE_DISTANCE = (int) (DEFAULT_SPEED * 115);
|
||||
// 90 s: car 1136 m, bicycle 250 m (36 s @ 25 km/h)
|
||||
PREPARE_DISTANCE_END = (int) (DEFAULT_SPEED * 90);
|
||||
|
||||
// 22 s: car 275 m, bicycle 61 m, pedestrian 24 m
|
||||
TURN_IN_DISTANCE = (int) (DEFAULT_SPEED * 22);
|
||||
// 15 s: car 189 m, bicycle 42 m, pedestrian 17 m
|
||||
TURN_IN_DISTANCE_END = (int) (DEFAULT_SPEED * 15);
|
||||
|
||||
// Do not play prepare: for pedestrian and slow transport
|
||||
// same check as speed < 150/(90-22) m/s = 2.2 m/s = 8 km/h
|
||||
// if (DEFAULT_SPEED < 2.3) {
|
||||
if (PREPARE_DISTANCE_END - TURN_IN_DISTANCE < 150) {
|
||||
PREPARE_DISTANCE_END = PREPARE_DISTANCE * 2;
|
||||
}
|
||||
|
||||
float ARRIVAL_DISTANCE_FACTOR = Math.max(settings.ARRIVAL_DISTANCE_FACTOR.getModeValue(appMode), 0.1f);
|
||||
|
||||
// Turn now: 3.5 s normal speed, 7 s for half speed (default)
|
||||
// float TURN_NOW_TIME = 7;
|
||||
// ** #8749 to keep 1m / 1 sec precision (POSITIONING_TOLERANCE = 12 m)
|
||||
// car 50 km/h - 7 s, bicycle 10 km/h - 3 s, pedestrian 4 km/h - 2 s, 1 km/h - 1 s
|
||||
float TURN_NOW_TIME = (float) Math.min(Math.sqrt(DEFAULT_SPEED * 3.6), 8);
|
||||
|
||||
// 3.6 s: car 45 m, bicycle 10 m -> 12 m, pedestrian 4 m -> 12 m (capped by POSITIONING_TOLERANCE)
|
||||
TURN_NOW_DISTANCE = (int) (Math.max(POSITIONING_TOLERANCE, DEFAULT_SPEED * 3.6) * ARRIVAL_DISTANCE_FACTOR);
|
||||
TURN_NOW_SPEED = TURN_NOW_DISTANCE / TURN_NOW_TIME;
|
||||
|
||||
// 5 s: car 63 m, bicycle 14 m, pedestrian 6 m -> 12 m (capped by POSITIONING_TOLERANCE)
|
||||
ARRIVAL_DISTANCE = (int) (Math.max(POSITIONING_TOLERANCE, DEFAULT_SPEED * 5.) * ARRIVAL_DISTANCE_FACTOR);
|
||||
|
||||
// 20 s: car 250 m, bicycle 56 m, pedestrian 22 m
|
||||
OFF_ROUTE_DISTANCE = DEFAULT_SPEED * 20 * ARRIVAL_DISTANCE_FACTOR; // 20 seconds
|
||||
|
||||
// assume for backward compatibility speed - 10 m/s
|
||||
SHORT_ALARM_ANNOUNCE_RADIUS = (int) (7 * DEFAULT_SPEED * ARRIVAL_DISTANCE_FACTOR); // 70 m
|
||||
LONG_ALARM_ANNOUNCE_RADIUS = (int) (12 * DEFAULT_SPEED * ARRIVAL_DISTANCE_FACTOR); // 120 m
|
||||
SHORT_PNT_ANNOUNCE_RADIUS = (int) (15 * DEFAULT_SPEED * ARRIVAL_DISTANCE_FACTOR); // 150 m
|
||||
LONG_PNT_ANNOUNCE_RADIUS = (int) (60 * DEFAULT_SPEED * ARRIVAL_DISTANCE_FACTOR); // 600 m
|
||||
|
||||
// Trigger close prompts earlier to allow BT SCO link being established, or when VOICE_PROMPT_DELAY is set >0 for the other stream types
|
||||
int ams = settings.AUDIO_MANAGER_STREAM.getModeValue(appMode);
|
||||
if ((ams == 0 && !AbstractPrologCommandPlayer.btScoStatus) || ams > 0) {
|
||||
if (settings.VOICE_PROMPT_DELAY[ams] != null) {
|
||||
voicePromptDelayTimeSec = (double) settings.VOICE_PROMPT_DELAY[ams].get() / 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getImminentTurnStatus(float dist, Location loc) {
|
||||
float speed = getSpeed(loc);
|
||||
if (isTurnStateActive(speed, dist, STATE_TURN_NOW)) {
|
||||
return 0;
|
||||
} else if (isTurnStateActive(speed, dist, STATE_PREPARE_TURN)) {
|
||||
// STATE_TURN_IN included
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTurnStateActive(float currentSpeed, double dist, int turnType) {
|
||||
switch (turnType) {
|
||||
case STATE_TURN_NOW:
|
||||
return isDistanceLess(currentSpeed, dist, TURN_NOW_DISTANCE, TURN_NOW_SPEED);
|
||||
case STATE_TURN_IN:
|
||||
return isDistanceLess(currentSpeed, dist, TURN_IN_DISTANCE);
|
||||
case STATE_PREPARE_TURN:
|
||||
return isDistanceLess(currentSpeed, dist, PREPARE_DISTANCE);
|
||||
case STATE_LONG_PREPARE_TURN:
|
||||
return isDistanceLess(currentSpeed, dist, PREPARE_LONG_DISTANCE);
|
||||
case STATE_SHORT_ALARM_ANNOUNCE:
|
||||
return isDistanceLess(currentSpeed, dist, SHORT_ALARM_ANNOUNCE_RADIUS);
|
||||
case STATE_LONG_ALARM_ANNOUNCE:
|
||||
return isDistanceLess(currentSpeed, dist, LONG_ALARM_ANNOUNCE_RADIUS);
|
||||
case STATE_SHORT_PNT_APPROACH:
|
||||
return isDistanceLess(currentSpeed, dist, SHORT_PNT_ANNOUNCE_RADIUS);
|
||||
case STATE_LONG_PNT_APPROACH:
|
||||
return isDistanceLess(currentSpeed, dist, LONG_PNT_ANNOUNCE_RADIUS);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isTurnStateNotPassed(float currentSpeed, double dist, int turnType) {
|
||||
switch (turnType) {
|
||||
case STATE_TURN_IN:
|
||||
return !isDistanceLess(currentSpeed, dist, TURN_IN_DISTANCE_END);
|
||||
case STATE_PREPARE_TURN:
|
||||
return !isDistanceLess(currentSpeed, dist, PREPARE_DISTANCE_END);
|
||||
case STATE_LONG_PREPARE_TURN:
|
||||
return !isDistanceLess(currentSpeed, dist, PREPARE_LONG_DISTANCE_END);
|
||||
case STATE_LONG_PNT_APPROACH:
|
||||
return !isDistanceLess(currentSpeed, dist, LONG_PNT_ANNOUNCE_RADIUS * 0.5);
|
||||
case STATE_LONG_ALARM_ANNOUNCE:
|
||||
return !isDistanceLess(currentSpeed, dist, LONG_ALARM_ANNOUNCE_RADIUS * 0.5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isDistanceLess(float currentSpeed, double dist, double etalon) {
|
||||
return isDistanceLess(currentSpeed, dist, etalon, DEFAULT_SPEED);
|
||||
}
|
||||
|
||||
private boolean isDistanceLess(float currentSpeed, double dist, double etalon, float defSpeed) {
|
||||
// Check triggers:
|
||||
// (1) distance < etalon?
|
||||
if (dist - voicePromptDelayTimeSec * currentSpeed <= etalon) {
|
||||
return true;
|
||||
}
|
||||
// (2) time_with_current_speed < etalon_time_with_default_speed?
|
||||
// check only if speed > 0
|
||||
if (currentSpeed > 0 && (dist / currentSpeed - voicePromptDelayTimeSec) <= etalon / defSpeed) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public float getSpeed(Location loc) {
|
||||
float speed = DEFAULT_SPEED;
|
||||
if (loc != null && loc.hasSpeed()) {
|
||||
speed = Math.max(loc.getSpeed(), speed);
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
public float getOffRouteDistance() {
|
||||
return OFF_ROUTE_DISTANCE;
|
||||
}
|
||||
|
||||
public float getArrivalDistance() {
|
||||
return ARRIVAL_DISTANCE;
|
||||
}
|
||||
|
||||
public int calcDistanceWithoutDelay(float speed, int dist) {
|
||||
return (int) (dist - voicePromptDelayTimeSec * speed);
|
||||
}
|
||||
|
||||
private void appendTurnDesc(StringBuilder s, String name, int dist) {
|
||||
appendTurnDesc(s, name, dist, DEFAULT_SPEED);
|
||||
}
|
||||
|
||||
private void appendTurnDesc(StringBuilder s, String name, int dist, float speed) {
|
||||
int minDist = (dist / 5) * 5;
|
||||
int time = (int) (dist / speed);
|
||||
if(time > 15) {
|
||||
// round to 5
|
||||
time = (time / 5) * 5;
|
||||
}
|
||||
s.append(String.format("%s: %d - %d m, %d sec\n", name, minDist, minDist + 5, time));
|
||||
}
|
||||
|
||||
public String getTurnsDescription() {
|
||||
StringBuilder turnDescriptions = new StringBuilder();
|
||||
appendTurnDesc(turnDescriptions, "Turn (now)", TURN_NOW_DISTANCE, TURN_NOW_SPEED);
|
||||
appendTurnDesc(turnDescriptions, "Turn (approach)", TURN_IN_DISTANCE);
|
||||
if (PREPARE_DISTANCE_END <= PREPARE_DISTANCE) {
|
||||
appendTurnDesc(turnDescriptions, "Turn (prepare)", PREPARE_DISTANCE);
|
||||
}
|
||||
if (PREPARE_LONG_DISTANCE_END <= PREPARE_LONG_DISTANCE) {
|
||||
appendTurnDesc(turnDescriptions, "Turn (early prepare)", PREPARE_LONG_DISTANCE);
|
||||
}
|
||||
appendTurnDesc(turnDescriptions, "Arrival", (int) getArrivalDistance());
|
||||
if (getOffRouteDistance() > 0) {
|
||||
appendTurnDesc(turnDescriptions, "Off-route", (int) getOffRouteDistance());
|
||||
}
|
||||
appendTurnDesc(turnDescriptions, "Alarm (close)", SHORT_ALARM_ANNOUNCE_RADIUS);
|
||||
appendTurnDesc(turnDescriptions, "Alarm (standard)", LONG_ALARM_ANNOUNCE_RADIUS);
|
||||
appendTurnDesc(turnDescriptions, "Waypoint / fav / POI (passing)", SHORT_PNT_ANNOUNCE_RADIUS);
|
||||
appendTurnDesc(turnDescriptions, "Waypoint / fav / POI (approaching)", LONG_PNT_ANNOUNCE_RADIUS);
|
||||
return turnDescriptions.toString();
|
||||
}
|
||||
}
|
|
@ -374,13 +374,6 @@ public class ApplicationMode {
|
|||
}
|
||||
|
||||
|
||||
public int getOffRouteDistance() {
|
||||
// used to be: 50/14 - 350 m, 10/2.7 - 50 m, 4/1.11 - 20 m
|
||||
float speed = Math.max(getDefaultSpeed(), 0.3f);
|
||||
// become: 50 kmh - 280 m, 10 kmh - 55 m, 4 kmh - 22 m
|
||||
return (int) (speed * 20);
|
||||
}
|
||||
|
||||
public boolean hasFastSpeed() {
|
||||
return getDefaultSpeed() > 10;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue