Merge pull request #2593 from osmandapp/moving_marker

Moving marker
This commit is contained in:
vshcherb 2016-05-25 13:02:22 +02:00
commit afb9f08e4b
28 changed files with 1215 additions and 559 deletions

View file

@ -1,6 +1,5 @@
package net.osmand.util; package net.osmand.util;
import net.osmand.IProgress; import net.osmand.IProgress;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
@ -21,22 +20,23 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
/** /**
* Basic algorithms that are not in jdk * Basic algorithms that are not in jdk
*/ */
public class Algorithms { public class Algorithms {
private static final int BUFFER_SIZE = 1024; private static final int BUFFER_SIZE = 1024;
private static final Log log = PlatformUtil.getLog(Algorithms.class); private static final Log log = PlatformUtil.getLog(Algorithms.class);
public static boolean isEmpty(String s){ public static boolean isEmpty(String s) {
return s == null || s.length() == 0; return s == null || s.length() == 0;
} }
public static boolean isBlank(String s){ public static boolean isBlank(String s) {
return s == null || s.trim().length() == 0; return s == null || s.trim().length() == 0;
} }
@ -47,13 +47,12 @@ public class Algorithms {
return false; return false;
} else if (s2 == null) { } else if (s2 == null) {
return false; return false;
} else {
return s2.equals(s1);
} }
return s2.equals(s1);
} }
public static long parseLongSilently(String input, long def) { public static long parseLongSilently(String input, long def) {
if(input != null && input.length() > 0) { if (input != null && input.length() > 0) {
try { try {
return Long.parseLong(input); return Long.parseLong(input);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
@ -62,20 +61,24 @@ public class Algorithms {
} }
return def; return def;
} }
public static String getFileNameWithoutExtension(File f) { public static String getFileNameWithoutExtension(File f) {
String name = f.getName(); String name = f.getName();
int i = name.indexOf('.'); int i = name.indexOf('.');
if(i >= 0) { if (i >= 0) {
name = name.substring(0, i); name = name.substring(0, i);
} }
return name; return name;
} }
public static String getFileExtension(File f) {
String name = f.getName();
public static File[] getSortedFilesVersions(File dir){ int i = name.lastIndexOf(".");
return name.substring(i + 1);
}
public static File[] getSortedFilesVersions(File dir) {
File[] listFiles = dir.listFiles(); File[] listFiles = dir.listFiles();
if (listFiles != null) { if (listFiles != null) {
Arrays.sort(listFiles, getFileVersionComparator()); Arrays.sort(listFiles, getFileVersionComparator());
@ -89,37 +92,37 @@ public class Algorithms {
public int compare(File o1, File o2) { public int compare(File o1, File o2) {
return -simplifyFileName(o1.getName()).compareTo(simplifyFileName(o2.getName())); return -simplifyFileName(o1.getName()).compareTo(simplifyFileName(o2.getName()));
} }
public String simplifyFileName(String fn) { public String simplifyFileName(String fn) {
String lc = fn.toLowerCase(); String lc = fn.toLowerCase();
if (lc.indexOf(".") != -1) { if (lc.contains(".")) {
lc = lc.substring(0, lc.indexOf(".")); lc = lc.substring(0, lc.indexOf("."));
} }
if (lc.endsWith("_2")) { if (lc.endsWith("_2")) {
lc = lc.substring(0, lc.length() - "_2".length()); lc = lc.substring(0, lc.length() - "_2".length());
} }
boolean hasTimestampEnd = false; boolean hasTimestampEnd = false;
for(int i = 0; i < lc.length(); i++) { for (int i = 0; i < lc.length(); i++) {
if(lc.charAt(i) >= '0' && lc.charAt(i) <= '9') { if (lc.charAt(i) >= '0' && lc.charAt(i) <= '9') {
hasTimestampEnd = true; hasTimestampEnd = true;
break; break;
} }
} }
if(!hasTimestampEnd) { if (!hasTimestampEnd) {
lc += "_00_00_00"; lc += "_00_00_00";
} }
return lc; return lc;
} }
}; };
} }
private static final char CHAR_TOSPLIT = 0x01; private static final char CHAR_TOSPLIT = 0x01;
public static Map<String, String> decodeMap(String s) { public static Map<String, String> decodeMap(String s) {
if (isEmpty(s)) { if (isEmpty(s)) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
Map<String, String> names = new HashMap<String, String>(); Map<String, String> names = new HashMap<>();
String[] split = s.split(CHAR_TOSPLIT + ""); String[] split = s.split(CHAR_TOSPLIT + "");
// last split is an empty string // last split is an empty string
for (int i = 1; i < split.length; i += 2) { for (int i = 1; i < split.length; i += 2) {
@ -127,7 +130,7 @@ public class Algorithms {
} }
return names; return names;
} }
public static String encodeMap(Map<String, String> names) { public static String encodeMap(Map<String, String> names) {
if (names != null) { if (names != null) {
Iterator<Entry<String, String>> it = names.entrySet().iterator(); Iterator<Entry<String, String>> it = names.entrySet().iterator();
@ -135,14 +138,14 @@ public class Algorithms {
while (it.hasNext()) { while (it.hasNext()) {
Entry<String, String> e = it.next(); Entry<String, String> e = it.next();
bld.append(e.getKey()).append(CHAR_TOSPLIT) bld.append(e.getKey()).append(CHAR_TOSPLIT)
.append(e.getValue().replace(CHAR_TOSPLIT, (char)(CHAR_TOSPLIT + 1))); .append(e.getValue().replace(CHAR_TOSPLIT, (char) (CHAR_TOSPLIT + 1)));
bld.append(CHAR_TOSPLIT); bld.append(CHAR_TOSPLIT);
} }
return bld.toString(); return bld.toString();
} }
return ""; return "";
} }
public static int findFirstNumberEndIndex(String value) { public static int findFirstNumberEndIndex(String value) {
int i = 0; int i = 0;
boolean valid = false; boolean valid = false;
@ -159,7 +162,7 @@ public class Algorithms {
return -1; return -1;
} }
} }
public static boolean isDigit(char charAt) { public static boolean isDigit(char charAt) {
return charAt >= '0' && charAt <= '9'; return charAt >= '0' && charAt <= '9';
} }
@ -182,17 +185,17 @@ public class Algorithms {
in.close(); in.close();
return test == 0x504b0304; return test == 0x504b0304;
} }
private static final int readInt(InputStream in) throws IOException { private static int readInt(InputStream in) throws IOException {
int ch1 = in.read(); int ch1 = in.read();
int ch2 = in.read(); int ch2 = in.read();
int ch3 = in.read(); int ch3 = in.read();
int ch4 = in.read(); int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0) if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException(); throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
} }
public static String capitalizeFirstLetterAndLowercase(String s) { public static String capitalizeFirstLetterAndLowercase(String s) {
if (s != null && s.length() > 1) { if (s != null && s.length() > 1) {
// not very efficient algorithm // not very efficient algorithm
@ -201,48 +204,48 @@ public class Algorithms {
return s; return s;
} }
} }
public static boolean objectEquals(Object a, Object b){ public static boolean objectEquals(Object a, Object b) {
if(a == null){ if (a == null) {
return b == null; return b == null;
} else { } else {
return a.equals(b); return a.equals(b);
} }
} }
/** /**
* Parse the color string, and return the corresponding color-int. * Parse the color string, and return the corresponding color-int.
* If the string cannot be parsed, throws an IllegalArgumentException * If the string cannot be parsed, throws an IllegalArgumentException
* exception. Supported formats are: * exception. Supported formats are:
* #RRGGBB * #RRGGBB
* #AARRGGBB * #AARRGGBB
* 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta', * 'red', 'blue', 'green', 'black', 'white', 'gray', 'cyan', 'magenta',
* 'yellow', 'lightgray', 'darkgray' * 'yellow', 'lightgray', 'darkgray'
*/ */
public static int parseColor(String colorString) { public static int parseColor(String colorString) {
if (colorString.charAt(0) == '#') { if (colorString.charAt(0) == '#') {
// Use a long to avoid rollovers on #ffXXXXXX // Use a long to avoid rollovers on #ffXXXXXX
if (colorString.length() == 4) { if (colorString.length() == 4) {
colorString = "#" + colorString = "#" +
colorString.charAt(1) + colorString.charAt(1) + colorString.charAt(1) + colorString.charAt(1) +
colorString.charAt(2) + colorString.charAt(2) + colorString.charAt(2) + colorString.charAt(2) +
colorString.charAt(3) + colorString.charAt(3); colorString.charAt(3) + colorString.charAt(3);
} }
long color = Long.parseLong(colorString.substring(1), 16); long color = Long.parseLong(colorString.substring(1), 16);
if (colorString.length() == 7) { if (colorString.length() == 7) {
// Set the alpha value // Set the alpha value
color |= 0x00000000ff000000; color |= 0x00000000ff000000;
} else if (colorString.length() != 9) { } else if (colorString.length() != 9) {
throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$ throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$
} }
return (int)color; return (int) color;
} }
throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$ throw new IllegalArgumentException("Unknown color " + colorString); //$NON-NLS-1$
} }
public static int extractFirstIntegerNumber(String s) { public static int extractFirstIntegerNumber(String s) {
int i = 0; int i = 0;
for (int k = 0; k < s.length(); k++) { for (int k = 0; k < s.length(); k++) {
@ -254,10 +257,10 @@ public class Algorithms {
} }
return i; return i;
} }
public static int extractIntegerNumber(String s) { public static int extractIntegerNumber(String s) {
int i = 0; int i = 0;
int k = 0; int k;
for (k = 0; k < s.length(); k++) { for (k = 0; k < s.length(); k++) {
if (isDigit(s.charAt(k))) { if (isDigit(s.charAt(k))) {
break; break;
@ -272,7 +275,7 @@ public class Algorithms {
} }
return i; return i;
} }
public static String extractIntegerPrefix(String s) { public static String extractIntegerPrefix(String s) {
int k = 0; int k = 0;
for (; k < s.length(); k++) { for (; k < s.length(); k++) {
@ -282,7 +285,7 @@ public class Algorithms {
} }
return ""; return "";
} }
public static String extractOnlyIntegerSuffix(String s) { public static String extractOnlyIntegerSuffix(String s) {
int k = 0; int k = 0;
for (; k < s.length(); k++) { for (; k < s.length(); k++) {
@ -292,7 +295,7 @@ public class Algorithms {
} }
return ""; return "";
} }
public static String extractIntegerSuffix(String s) { public static String extractIntegerSuffix(String s) {
int k = 0; int k = 0;
for (; k < s.length(); k++) { for (; k < s.length(); k++) {
@ -302,8 +305,9 @@ public class Algorithms {
} }
return ""; return "";
} }
@SuppressWarnings("TryFinallyCanBeTryWithResources")
public static void fileCopy(File src, File dst) throws IOException { public static void fileCopy(File src, File dst) throws IOException {
FileOutputStream fout = new FileOutputStream(dst); FileOutputStream fout = new FileOutputStream(dst);
try { try {
@ -317,59 +321,61 @@ public class Algorithms {
fout.close(); fout.close();
} }
} }
public static void streamCopy(InputStream in, OutputStream out) throws IOException{
public static void streamCopy(InputStream in, OutputStream out) throws IOException {
byte[] b = new byte[BUFFER_SIZE]; byte[] b = new byte[BUFFER_SIZE];
int read; int read;
while ((read = in.read(b)) != -1) { while ((read = in.read(b)) != -1) {
out.write(b, 0, read); out.write(b, 0, read);
} }
} }
public static void streamCopy(InputStream in, OutputStream out, IProgress pg, int bytesDivisor) throws IOException{ public static void streamCopy(InputStream in, OutputStream out, IProgress pg, int bytesDivisor) throws IOException {
byte[] b = new byte[BUFFER_SIZE]; byte[] b = new byte[BUFFER_SIZE];
int read; int read;
int cp = 0; int cp = 0;
while ((read = in.read(b)) != -1) { while ((read = in.read(b)) != -1) {
out.write(b, 0, read); out.write(b, 0, read);
cp += read; cp += read;
if(pg != null && cp > bytesDivisor) { if (pg != null && cp > bytesDivisor) {
pg.progress(cp / bytesDivisor); pg.progress(cp / bytesDivisor);
cp = cp % bytesDivisor; cp = cp % bytesDivisor;
} }
} }
} }
public static void oneByteStreamCopy(InputStream in, OutputStream out) throws IOException{ public static void oneByteStreamCopy(InputStream in, OutputStream out) throws IOException {
int read; int read;
while ((read = in.read()) != -1) { while ((read = in.read()) != -1) {
out.write(read); out.write(read);
} }
} }
public static void closeStream(Closeable stream){ public static void closeStream(Closeable stream) {
try { try {
if(stream != null){ if (stream != null) {
stream.close(); stream.close();
} }
} catch(IOException e){ } catch (IOException e) {
log.warn("Closing stream warn", e); //$NON-NLS-1$ log.warn("Closing stream warn", e); //$NON-NLS-1$
} }
} }
public static void updateAllExistingImgTilesToOsmandFormat(File f){ @SuppressWarnings("ResultOfMethodCallIgnored")
if(f.isDirectory()){ public static void updateAllExistingImgTilesToOsmandFormat(File f) {
for(File c : f.listFiles()){ if (f.isDirectory()) {
for (File c : f.listFiles()) {
updateAllExistingImgTilesToOsmandFormat(c); updateAllExistingImgTilesToOsmandFormat(c);
} }
} else if(f.getName().endsWith(".png") || f.getName().endsWith(".jpg")){ //$NON-NLS-1$ //$NON-NLS-2$ } else if (f.getName().endsWith(".png") || f.getName().endsWith(".jpg")) { //$NON-NLS-1$ //$NON-NLS-2$
f.renameTo(new File(f.getAbsolutePath() + ".tile")); //$NON-NLS-1$ f.renameTo(new File(f.getAbsolutePath() + ".tile")); //$NON-NLS-1$
} else if(f.getName().endsWith(".andnav2")) { //$NON-NLS-1$ } else if (f.getName().endsWith(".andnav2")) { //$NON-NLS-1$
f.renameTo(new File(f.getAbsolutePath().substring(0, f.getAbsolutePath().length() - ".andnav2".length()) + ".tile")); //$NON-NLS-1$ //$NON-NLS-2$ f.renameTo(new File(f.getAbsolutePath().substring(0, f.getAbsolutePath().length() - ".andnav2".length()) + ".tile")); //$NON-NLS-1$ //$NON-NLS-2$
} }
} }
public static StringBuilder readFromInputStream(InputStream i) throws IOException { public static StringBuilder readFromInputStream(InputStream i) throws IOException {
StringBuilder responseBody = new StringBuilder(); StringBuilder responseBody = new StringBuilder();
responseBody.setLength(0); responseBody.setLength(0);
@ -388,27 +394,27 @@ public class Algorithms {
} }
return responseBody; return responseBody;
} }
public static boolean removeAllFiles(File f) { public static boolean removeAllFiles(File f) {
if (f == null) { if (f == null) {
return false; return false;
} }
if (f.isDirectory()) { if (f.isDirectory()) {
File[] fs = f.listFiles(); File[] fs = f.listFiles();
if(fs != null) { if (fs != null) {
for (File c : fs) { for (File c : fs) {
removeAllFiles(c); removeAllFiles(c);
} }
} }
return f.delete(); return f.delete();
} else { } else {
return f.delete(); return f.delete();
} }
} }
public static long parseLongFromBytes(byte[] bytes, int offset) { public static long parseLongFromBytes(byte[] bytes, int offset) {
long o= 0xff & bytes[offset + 7]; long o = 0xff & bytes[offset + 7];
o = o << 8 | (0xff & bytes[offset + 6]); o = o << 8 | (0xff & bytes[offset + 6]);
o = o << 8 | (0xff & bytes[offset + 5]); o = o << 8 | (0xff & bytes[offset + 5]);
o = o << 8 | (0xff & bytes[offset + 4]); o = o << 8 | (0xff & bytes[offset + 4]);
@ -418,10 +424,9 @@ public class Algorithms {
o = o << 8 | (0xff & bytes[offset]); o = o << 8 | (0xff & bytes[offset]);
return o; return o;
} }
public static void putLongToBytes(byte[] bytes, int offset, long l) {
public static void putLongToBytes(byte[] bytes, int offset, long l){
bytes[offset] = (byte) (l & 0xff); bytes[offset] = (byte) (l & 0xff);
l >>= 8; l >>= 8;
bytes[offset + 1] = (byte) (l & 0xff); bytes[offset + 1] = (byte) (l & 0xff);
@ -438,8 +443,8 @@ public class Algorithms {
l >>= 8; l >>= 8;
bytes[offset + 7] = (byte) (l & 0xff); bytes[offset + 7] = (byte) (l & 0xff);
} }
public static int parseIntFromBytes(byte[] bytes, int offset) { public static int parseIntFromBytes(byte[] bytes, int offset) {
int o = (0xff & bytes[offset + 3]) << 24; int o = (0xff & bytes[offset + 3]) << 24;
o |= (0xff & bytes[offset + 2]) << 16; o |= (0xff & bytes[offset + 2]) << 16;
@ -447,8 +452,8 @@ public class Algorithms {
o |= (0xff & bytes[offset]); o |= (0xff & bytes[offset]);
return o; return o;
} }
public static void putIntToBytes(byte[] bytes, int offset, int l){ public static void putIntToBytes(byte[] bytes, int offset, int l) {
bytes[offset] = (byte) (l & 0xff); bytes[offset] = (byte) (l & 0xff);
l >>= 8; l >>= 8;
bytes[offset + 1] = (byte) (l & 0xff); bytes[offset + 1] = (byte) (l & 0xff);
@ -457,8 +462,8 @@ public class Algorithms {
l >>= 8; l >>= 8;
bytes[offset + 3] = (byte) (l & 0xff); bytes[offset + 3] = (byte) (l & 0xff);
} }
public static void writeLongInt(OutputStream stream, long l) throws IOException { public static void writeLongInt(OutputStream stream, long l) throws IOException {
stream.write((int) (l & 0xff)); stream.write((int) (l & 0xff));
l >>= 8; l >>= 8;
@ -476,7 +481,7 @@ public class Algorithms {
l >>= 8; l >>= 8;
stream.write((int) (l & 0xff)); stream.write((int) (l & 0xff));
} }
public static void writeInt(OutputStream stream, int l) throws IOException { public static void writeInt(OutputStream stream, int l) throws IOException {
stream.write(l & 0xff); stream.write(l & 0xff);
l >>= 8; l >>= 8;
@ -486,26 +491,24 @@ public class Algorithms {
l >>= 8; l >>= 8;
stream.write(l & 0xff); stream.write(l & 0xff);
} }
public static void writeSmallInt(OutputStream stream, int l) throws IOException { public static void writeSmallInt(OutputStream stream, int l) throws IOException {
stream.write(l & 0xff); stream.write(l & 0xff);
l >>= 8; l >>= 8;
stream.write(l & 0xff); stream.write(l & 0xff);
l >>= 8;
} }
public static int parseSmallIntFromBytes(byte[] bytes, int offset) { public static int parseSmallIntFromBytes(byte[] bytes, int offset) {
int s = (0xff & bytes[offset + 1]) << 8; int s = (0xff & bytes[offset + 1]) << 8;
s |= (0xff & bytes[offset]); s |= (0xff & bytes[offset]);
return s; return s;
} }
public static void putSmallIntBytes(byte[] bytes, int offset, int s){ public static void putSmallIntBytes(byte[] bytes, int offset, int s) {
bytes[offset] = (byte) (s & 0xff); bytes[offset] = (byte) (s & 0xff);
s >>= 8; s >>= 8;
bytes[offset + 1] = (byte) (s & 0xff); bytes[offset + 1] = (byte) (s & 0xff);
s >>= 8;
} }
public static boolean containsDigit(String name) { public static boolean containsDigit(String name) {
@ -516,7 +519,7 @@ public class Algorithms {
} }
return false; return false;
} }
public static String formatDuration(int seconds, boolean fullForm) { public static String formatDuration(int seconds, boolean fullForm) {
String sec; String sec;
@ -546,14 +549,14 @@ public class Algorithms {
} else { } else {
int min = minutes % 60; int min = minutes % 60;
int hours = minutes / 60; int hours = minutes / 60;
return String.format("%02d:%02d", hours, min); return String.format(Locale.UK, "%02d:%02d", hours, min);
} }
} }
public static <T extends Enum<T> > T parseEnumValue(T[] cl, String val, T defaultValue){ public static <T extends Enum<T>> T parseEnumValue(T[] cl, String val, T defaultValue) {
for(int i = 0; i< cl.length; i++) { for (T aCl : cl) {
if(cl[i].name().equalsIgnoreCase(val)) { if (aCl.name().equalsIgnoreCase(val)) {
return cl[i]; return aCl;
} }
} }
return defaultValue; return defaultValue;
@ -568,7 +571,7 @@ public class Algorithms {
} }
private static String format(int i, String hexString) { private static String format(int i, String hexString) {
while(hexString.length() < i) { while (hexString.length() < i) {
hexString = "0" + hexString; hexString = "0" + hexString;
} }
return hexString; return hexString;
@ -580,16 +583,16 @@ public class Algorithms {
// from purple (low) to red(high). This is useful for producing value-based colourations (e.g., altitude) // from purple (low) to red(high). This is useful for producing value-based colourations (e.g., altitude)
double a = (1. - percent) * 5.; double a = (1. - percent) * 5.;
int X = (int)Math.floor(a); int X = (int) Math.floor(a);
int Y = (int)(Math.floor(255 * (a - X))); int Y = (int) (Math.floor(255 * (a - X)));
switch (X) { switch (X) {
case 0: return 0xFFFF0000 + (Y<<8); case 0: return 0xFFFF0000 + (Y << 8);
case 1: return 0xFF00FF00 + ((255-Y)<<16); case 1: return 0xFF00FF00 + ((255 - Y) << 16);
case 2: return 0xFF00FF00 + Y; case 2: return 0xFF00FF00 + Y;
case 3: return 0xFF0000FF + ((255-Y)<<8); case 3: return 0xFF0000FF + ((255 - Y) << 8);
case 4: return 0xFF0000FF + (Y << 16); case 4: return 0xFF0000FF + (Y << 16);
} }
return 0xFFFF00FF; return 0xFFFF00FF;
} }
} }

View file

@ -2164,4 +2164,4 @@ Für Hilfe mit der OsmAnd-App kontaktieren Sie bitte unser Support-Team unter su
<string name="access_direction_audio_feedback_descr">Zeige Richtung des Zielpunkt durch Ton</string> <string name="access_direction_audio_feedback_descr">Zeige Richtung des Zielpunkt durch Ton</string>
<string name="access_direction_haptic_feedback">Richtung haptisches Feedback</string> <string name="access_direction_haptic_feedback">Richtung haptisches Feedback</string>
<string name="access_direction_haptic_feedback_descr">Zeige Richtung des Zielpunkt durch Vibration</string> <string name="access_direction_haptic_feedback_descr">Zeige Richtung des Zielpunkt durch Vibration</string>
</resources> </resources>

View file

@ -11,6 +11,7 @@
--> -->
<string name="map_widget_battery">Battery level</string> <string name="map_widget_battery">Battery level</string>
<string name="change_markers_position">Change marker\'s position</string>
<string name="move_marker_bottom_sheet_title">Move the map to change marker\'s position</string> <string name="move_marker_bottom_sheet_title">Move the map to change marker\'s position</string>
<string name="lat_lon_pattern">Lat: %1$.6f Lon: %2$.6f</string> <string name="lat_lon_pattern">Lat: %1$.6f Lon: %2$.6f</string>
<string name="follow_us">Follow us</string> <string name="follow_us">Follow us</string>

View file

@ -5,6 +5,7 @@ import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.support.annotation.ColorInt;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
@ -64,8 +65,9 @@ public class GPXUtilities {
} }
return extensions; return extensions;
} }
public int getColor(int defColor) { @ColorInt
public int getColor(@ColorInt int defColor) {
if(extensions != null && extensions.containsKey("color")) { if(extensions != null && extensions.containsKey("color")) {
try { try {
return Color.parseColor(extensions.get("color").toUpperCase()); return Color.parseColor(extensions.get("color").toUpperCase());
@ -665,7 +667,7 @@ public class GPXUtilities {
return points.size() > 0; return points.size() > 0;
} }
public boolean hasTrkpt() { public boolean hasTrkPt() {
for(Track t : tracks) { for(Track t : tracks) {
for (TrkSegment ts : t.segments) { for (TrkSegment ts : t.segments) {
if (ts.points.size() > 0) { if (ts.points.size() > 0) {
@ -1224,7 +1226,5 @@ public class GPXUtilities {
if (from.warning != null) { if (from.warning != null) {
to.warning = from.warning; to.warning = from.warning;
} }
} }
}
}

View file

@ -1,6 +1,7 @@
package net.osmand.plus; package net.osmand.plus;
import android.content.Context; import android.content.Context;
import android.support.annotation.Nullable;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.LocationPoint; import net.osmand.data.LocationPoint;
@ -80,6 +81,37 @@ public class MapMarkersHelper {
return false; return false;
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MapMarker mapMarker = (MapMarker) o;
if (colorIndex != mapMarker.colorIndex) return false;
if (pos != mapMarker.pos) return false;
if (index != mapMarker.index) return false;
if (history != mapMarker.history) return false;
if (selected != mapMarker.selected) return false;
if (dist != mapMarker.dist) return false;
//noinspection SimplifiableIfStatement
if (!point.equals(mapMarker.point)) return false;
return pointDescription != null ? pointDescription.equals(mapMarker.pointDescription) : mapMarker.pointDescription == null;
}
@Override
public int hashCode() {
int result = point.hashCode();
result = 31 * result + (pointDescription != null ? pointDescription.hashCode() : 0);
result = 31 * result + colorIndex;
result = 31 * result + pos;
result = 31 * result + index;
result = 31 * result + (history ? 1 : 0);
result = 31 * result + (selected ? 1 : 0);
result = 31 * result + dist;
return result;
}
} }
public MapMarkersHelper(OsmandApplication ctx) { public MapMarkersHelper(OsmandApplication ctx) {
@ -363,6 +395,15 @@ public class MapMarkersHelper {
} }
} }
public void moveMapMarker(@Nullable MapMarker marker, LatLon latLon) {
if (marker != null) {
settings.moveMapMarker(new LatLon(marker.getLatitude(), marker.getLongitude()), latLon,
marker.pointDescription, marker.colorIndex, marker.pos, marker.selected);
readFromSettings();
refresh();
}
}
public void removeMapMarker(MapMarker marker) { public void removeMapMarker(MapMarker marker) {
if (marker != null) { if (marker != null) {
settings.deleteMapMarker(marker.index); settings.deleteMapMarker(marker.index);

View file

@ -40,7 +40,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
@ -50,7 +49,6 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.TreeSet;
public class OsmandSettings { public class OsmandSettings {
@ -1859,20 +1857,61 @@ public class OsmandSettings {
List<Integer> ns = getPositions(ps.size()); List<Integer> ns = getPositions(ps.size());
List<Boolean> bs = getSelections(ps.size()); List<Boolean> bs = getSelections(ps.size());
int index = ps.indexOf(new LatLon(latitude, longitude)); int index = ps.indexOf(new LatLon(latitude, longitude));
ds.set(index, PointDescription.serializeToString(historyDescription)); if (index != -1) {
if (cs.size() > index) { ds.set(index, PointDescription.serializeToString(historyDescription));
cs.set(index, colorIndex); if (cs.size() > index) {
cs.set(index, colorIndex);
}
if (ns.size() > index) {
ns.set(index, pos);
}
if (bs.size() > index) {
bs.set(index, selected);
}
if (historyDescription != null && !historyDescription.isSearchingAddress(ctx)) {
SearchHistoryHelper.getInstance(ctx).addNewItemToHistory(latitude, longitude, historyDescription);
}
return savePoints(ps, ds, cs, ns, bs);
} else {
return false;
} }
if (ns.size() > index) { }
ns.set(index, pos);
public boolean movePoint(LatLon latLonEx,
LatLon latLonNew,
PointDescription historyDescription,
int colorIndex,
int pos,
boolean selected) {
List<LatLon> ps = getPoints();
List<String> ds = getPointDescriptions(ps.size());
List<Integer> cs = getColors(ps.size());
List<Integer> ns = getPositions(ps.size());
List<Boolean> bs = getSelections(ps.size());
int index = ps.indexOf(latLonEx);
if (index != -1) {
if (ps.size() > index) {
ps.set(index, latLonNew);
}
ds.set(index, PointDescription.serializeToString(historyDescription));
if (cs.size() > index) {
cs.set(index, colorIndex);
}
if (ns.size() > index) {
ns.set(index, pos);
}
if (bs.size() > index) {
bs.set(index, selected);
}
if (historyDescription != null && !historyDescription.isSearchingAddress(ctx)) {
double lat = latLonNew.getLatitude();
double lon = latLonNew.getLongitude();
SearchHistoryHelper.getInstance(ctx).addNewItemToHistory(lat, lon, historyDescription);
}
return savePoints(ps, ds, cs, ns, bs);
} else {
return false;
} }
if (bs.size() > index) {
bs.set(index, selected);
}
if (historyDescription != null && !historyDescription.isSearchingAddress(ctx)) {
SearchHistoryHelper.getInstance(ctx).addNewItemToHistory(latitude, longitude, historyDescription);
}
return savePoints(ps, ds, cs, ns, bs);
} }
@Override @Override
@ -2137,6 +2176,16 @@ public class OsmandSettings {
pos, selected); pos, selected);
} }
public boolean moveMapMarker(LatLon latLonEx,
LatLon latLonNew,
PointDescription historyDescription,
int colorIndex,
int pos,
boolean selected) {
return mapMarkersStorage.movePoint(latLonEx, latLonNew, historyDescription, colorIndex,
pos, selected);
}
public boolean deleteMapMarker(int index) { public boolean deleteMapMarker(int index) {
return mapMarkersStorage.deletePoint(index); return mapMarkersStorage.deletePoint(index);
} }

View file

@ -1,6 +1,7 @@
package net.osmand.plus; package net.osmand.plus;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import net.osmand.Location; import net.osmand.Location;
@ -19,12 +20,12 @@ import java.util.List;
public class TargetPointsHelper { public class TargetPointsHelper {
private List<TargetPoint> intermediatePoints = new ArrayList<TargetPoint>(); private List<TargetPoint> intermediatePoints = new ArrayList<>();
private TargetPoint pointToNavigate = null; private TargetPoint pointToNavigate = null;
private TargetPoint pointToStart = null; private TargetPoint pointToStart = null;
private OsmandSettings settings; private OsmandSettings settings;
private RoutingHelper routingHelper; private RoutingHelper routingHelper;
private List<StateChangedListener<Void>> listeners = new ArrayList<StateChangedListener<Void>>(); private List<StateChangedListener<Void>> listeners = new ArrayList<>();
private OsmandApplication ctx; private OsmandApplication ctx;
private AddressLookupRequest startPointRequest; private AddressLookupRequest startPointRequest;
@ -49,6 +50,7 @@ public class TargetPointsHelper {
this.intermediate = true; this.intermediate = true;
} }
@SuppressLint("StringFormatInvalid")
public PointDescription getPointDescription(Context ctx) { public PointDescription getPointDescription(Context ctx) {
if (!intermediate) { if (!intermediate) {
return new PointDescription(PointDescription.POINT_TYPE_TARGET, ctx.getString(R.string.destination_point, ""), return new PointDescription(PointDescription.POINT_TYPE_TARGET, ctx.getString(R.string.destination_point, ""),
@ -61,7 +63,7 @@ public class TargetPointsHelper {
public PointDescription getOriginalPointDescription() { public PointDescription getOriginalPointDescription() {
return pointDescription; return pointDescription;
}; }
public String getOnlyName() { public String getOnlyName() {
return pointDescription == null ? "" : pointDescription.getName(); return pointDescription == null ? "" : pointDescription.getName();
@ -229,7 +231,7 @@ public class TargetPointsHelper {
} }
public List<LatLon> getIntermediatePointsLatLon() { public List<LatLon> getIntermediatePointsLatLon() {
List<LatLon> intermediatePointsLatLon = new ArrayList<LatLon>(); List<LatLon> intermediatePointsLatLon = new ArrayList<>();
for (TargetPoint t : this.intermediatePoints) { for (TargetPoint t : this.intermediatePoints) {
intermediatePointsLatLon.add(t.point); intermediatePointsLatLon.add(t.point);
} }
@ -237,7 +239,7 @@ public class TargetPointsHelper {
} }
public List<LatLon> getIntermediatePointsLatLonNavigation() { public List<LatLon> getIntermediatePointsLatLonNavigation() {
List<LatLon> intermediatePointsLatLon = new ArrayList<LatLon>(); List<LatLon> intermediatePointsLatLon = new ArrayList<>();
if (settings.USE_INTERMEDIATE_POINTS_NAVIGATION.get()) { if (settings.USE_INTERMEDIATE_POINTS_NAVIGATION.get()) {
for (TargetPoint t : this.intermediatePoints) { for (TargetPoint t : this.intermediatePoints) {
intermediatePointsLatLon.add(t.point); intermediatePointsLatLon.add(t.point);
@ -247,7 +249,7 @@ public class TargetPointsHelper {
} }
public List<TargetPoint> getAllPoints() { public List<TargetPoint> getAllPoints() {
List<TargetPoint> res = new ArrayList<TargetPoint>(); List<TargetPoint> res = new ArrayList<>();
if(pointToStart != null) { if(pointToStart != null) {
res.add(pointToStart); res.add(pointToStart);
} }
@ -259,7 +261,7 @@ public class TargetPointsHelper {
} }
public List<TargetPoint> getIntermediatePointsWithTarget() { public List<TargetPoint> getIntermediatePointsWithTarget() {
List<TargetPoint> res = new ArrayList<TargetPoint>(); List<TargetPoint> res = new ArrayList<>();
res.addAll(this.intermediatePoints); res.addAll(this.intermediatePoints);
if(pointToNavigate != null) { if(pointToNavigate != null) {
res.add(pointToNavigate); res.add(pointToNavigate);
@ -423,8 +425,8 @@ public class TargetPointsHelper {
settings.clearPointToNavigate(); settings.clearPointToNavigate();
if (point.size() > 0) { if (point.size() > 0) {
List<TargetPoint> subList = point.subList(0, point.size() - 1); List<TargetPoint> subList = point.subList(0, point.size() - 1);
ArrayList<String> names = new ArrayList<String>(subList.size()); ArrayList<String> names = new ArrayList<>(subList.size());
ArrayList<LatLon> ls = new ArrayList<LatLon>(subList.size()); ArrayList<LatLon> ls = new ArrayList<>(subList.size());
for(int i = 0; i < subList.size(); i++) { for(int i = 0; i < subList.size(); i++) {
names.add(PointDescription.serializeToString(subList.get(i).pointDescription)); names.add(PointDescription.serializeToString(subList.get(i).pointDescription));
ls.add(subList.get(i).point); ls.add(subList.get(i).point);

View file

@ -320,7 +320,7 @@ public class MapActivityActions implements DialogProvider {
} else { } else {
GPXRouteParamsBuilder params = new GPXRouteParamsBuilder(result, mapActivity.getMyApplication() GPXRouteParamsBuilder params = new GPXRouteParamsBuilder(result, mapActivity.getMyApplication()
.getSettings()); .getSettings());
if (result.hasRtePt() && !result.hasTrkpt()) { if (result.hasRtePt() && !result.hasTrkPt()) {
settings.GPX_CALCULATE_RTEPT.set(true); settings.GPX_CALCULATE_RTEPT.set(true);
} else { } else {
settings.GPX_CALCULATE_RTEPT.set(false); settings.GPX_CALCULATE_RTEPT.set(false);
@ -350,7 +350,7 @@ public class MapActivityActions implements DialogProvider {
final List<GPXFile> gpxFiles = new ArrayList<>(); final List<GPXFile> gpxFiles = new ArrayList<>();
for (SelectedGpxFile gs : selectedGPXFiles) { for (SelectedGpxFile gs : selectedGPXFiles) {
if (!gs.isShowCurrentTrack() && !gs.notShowNavigationDialog) { if (!gs.isShowCurrentTrack() && !gs.notShowNavigationDialog) {
if (gs.getGpxFile().hasRtePt() || gs.getGpxFile().hasTrkpt()) { if (gs.getGpxFile().hasRtePt() || gs.getGpxFile().hasTrkPt()) {
gpxFiles.add(gs.getGpxFile()); gpxFiles.add(gs.getGpxFile());
} }
} }

View file

@ -37,7 +37,7 @@ import net.osmand.plus.render.RenderingIcons;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.ContextMenuLayer; import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.plus.views.DownloadedRegionsLayer; import net.osmand.plus.views.DownloadedRegionsLayer;
import net.osmand.plus.views.FavoritesLayer; import net.osmand.plus.views.FavouritesLayer;
import net.osmand.plus.views.GPXLayer; import net.osmand.plus.views.GPXLayer;
import net.osmand.plus.views.ImpassableRoadsLayer; import net.osmand.plus.views.ImpassableRoadsLayer;
import net.osmand.plus.views.MapControlsLayer; import net.osmand.plus.views.MapControlsLayer;
@ -72,7 +72,7 @@ public class MapActivityLayers {
private GPXLayer gpxLayer; private GPXLayer gpxLayer;
private RouteLayer routeLayer; private RouteLayer routeLayer;
private POIMapLayer poiMapLayer; private POIMapLayer poiMapLayer;
private FavoritesLayer favoritesLayer; private FavouritesLayer mFavouritesLayer;
private TransportStopsLayer transportStopsLayer; private TransportStopsLayer transportStopsLayer;
private TransportInfoLayer transportInfoLayer; private TransportInfoLayer transportInfoLayer;
private PointLocationLayer locationLayer; private PointLocationLayer locationLayer;
@ -138,8 +138,8 @@ public class MapActivityLayers {
poiMapLayer = new POIMapLayer(activity); poiMapLayer = new POIMapLayer(activity);
mapView.addLayer(poiMapLayer, 3); mapView.addLayer(poiMapLayer, 3);
// 4. favorites layer // 4. favorites layer
favoritesLayer = new FavoritesLayer(); mFavouritesLayer = new FavouritesLayer();
mapView.addLayer(favoritesLayer, 4); mapView.addLayer(mFavouritesLayer, 4);
// 5. transport layer // 5. transport layer
transportStopsLayer = new TransportStopsLayer(); transportStopsLayer = new TransportStopsLayer();
// 5.5 transport info layer // 5.5 transport info layer
@ -565,8 +565,8 @@ public class MapActivityLayers {
return contextMenuLayer; return contextMenuLayer;
} }
public FavoritesLayer getFavoritesLayer() { public FavouritesLayer getFavouritesLayer() {
return favoritesLayer; return mFavouritesLayer;
} }
public MapTextLayer getMapTextLayer() { public MapTextLayer getMapTextLayer() {

View file

@ -7,6 +7,9 @@ import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.PointF; import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import net.osmand.data.DataTileManager; import net.osmand.data.DataTileManager;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
@ -16,6 +19,7 @@ import net.osmand.data.RotatedTileBox;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.audionotes.AudioVideoNotesPlugin.Recording; import net.osmand.plus.audionotes.AudioVideoNotesPlugin.Recording;
import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider; import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider;
import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
@ -24,20 +28,22 @@ import net.osmand.util.Algorithms;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvider { public class AudioNotesLayer extends OsmandMapLayer implements
IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider {
private static final int startZoom = 10; private static final int startZoom = 10;
private MapActivity activity; private MapActivity activity;
private AudioVideoNotesPlugin plugin; private AudioVideoNotesPlugin plugin;
private Paint pointAltUI; private Paint pointAltUI;
private Paint paintIcon; private Paint paintIcon;
private Paint point;
private OsmandMapTileView view; private OsmandMapTileView view;
private Bitmap audio; private Bitmap audio;
private Bitmap video; private Bitmap video;
private Bitmap photo; private Bitmap photo;
private Bitmap pointSmall; private Bitmap pointSmall;
private ContextMenuLayer contextMenuLayer;
public AudioNotesLayer(MapActivity activity, AudioVideoNotesPlugin plugin) { public AudioNotesLayer(MapActivity activity, AudioVideoNotesPlugin plugin) {
this.activity = activity; this.activity = activity;
this.plugin = plugin; this.plugin = plugin;
@ -50,7 +56,7 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
pointAltUI = new Paint(); pointAltUI = new Paint();
pointAltUI.setColor(0xa0FF3344); pointAltUI.setColor(0xa0FF3344);
pointAltUI.setStyle(Style.FILL); pointAltUI.setStyle(Style.FILL);
audio = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_audio); audio = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_audio);
video = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_video); video = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_video);
photo = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_photo); photo = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_note_photo);
@ -59,15 +65,17 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
paintIcon = new Paint(); paintIcon = new Paint();
point = new Paint(); Paint point = new Paint();
point.setColor(Color.GRAY); point.setColor(Color.GRAY);
point.setAntiAlias(true); point.setAntiAlias(true);
point.setStyle(Style.STROKE); point.setStyle(Style.STROKE);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
public int getRadiusPoi(RotatedTileBox tb){ public int getRadiusPoi(RotatedTileBox tb) {
int r = 0; int r = 0;
if(tb.getZoom() < startZoom){ if (tb.getZoom() < startZoom) {
r = 0; r = 0;
} else { } else {
r = 15; r = 15;
@ -77,8 +85,13 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (contextMenuLayer.getMoveableObject() instanceof Recording) {
Recording objectInMotion = (Recording) contextMenuLayer.getMoveableObject();
PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
drawRecording(canvas, objectInMotion, pf.x, pf.y);
}
} }
@Override @Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (tileBox.getZoom() >= startZoom) { if (tileBox.getZoom() >= startZoom) {
@ -92,35 +105,41 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
List<LatLon> fullObjectsLatLon = new ArrayList<>(); List<LatLon> fullObjectsLatLon = new ArrayList<>();
List<LatLon> smallObjectsLatLon = new ArrayList<>(); List<LatLon> smallObjectsLatLon = new ArrayList<>();
for (Recording o : objects) { for (Recording o : objects) {
float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude()); if (o != contextMenuLayer.getMoveableObject()) {
float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude()); float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude());
float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude());
if (intersects(boundIntersections, x, y, iconSize, iconSize)) { if (intersects(boundIntersections, x, y, iconSize, iconSize)) {
canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon); canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon);
smallObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude())); smallObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude()));
} else { } else {
fullObjects.add(o); fullObjects.add(o);
fullObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude())); fullObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude()));
}
} }
} }
for (Recording o : fullObjects) { for (Recording o : fullObjects) {
float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude()); float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude());
float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude()); float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude());
Bitmap b; drawRecording(canvas, o, x, y);
if (o.isPhoto()) {
b = photo;
} else if (o.isAudio()) {
b = audio;
} else {
b = video;
}
canvas.drawBitmap(b, x - b.getWidth() / 2, y - b.getHeight() / 2, paintIcon);
} }
this.fullObjectsLatLon = fullObjectsLatLon; this.fullObjectsLatLon = fullObjectsLatLon;
this.smallObjectsLatLon = smallObjectsLatLon; this.smallObjectsLatLon = smallObjectsLatLon;
} }
} }
private void drawRecording(Canvas canvas, Recording o, float x, float y) {
Bitmap b;
if (o.isPhoto()) {
b = photo;
} else if (o.isAudio()) {
b = audio;
} else {
b = video;
}
canvas.drawBitmap(b, x - b.getWidth() / 2, y - b.getHeight() / 2, paintIcon);
}
@Override @Override
public void destroyLayer() { public void destroyLayer() {
} }
@ -130,13 +149,13 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
return true; return true;
} }
@Override @Override
public PointDescription getObjectName(Object o) { public PointDescription getObjectName(Object o) {
if(o instanceof Recording){ if (o instanceof Recording) {
Recording rec = (Recording) o; Recording rec = (Recording) o;
String recName = rec.getName(activity, true); String recName = rec.getName(activity, true);
if(Algorithms.isEmpty(recName)) { if (Algorithms.isEmpty(recName)) {
return new PointDescription(rec.getSearchHistoryType(), view.getResources().getString(R.string.recording_default_name)); return new PointDescription(rec.getSearchHistoryType(), view.getResources().getString(R.string.recording_default_name));
} }
return new PointDescription(rec.getSearchHistoryType(), recName); return new PointDescription(rec.getSearchHistoryType(), recName);
@ -165,7 +184,7 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
getRecordingsFromPoint(point, tileBox, objects); getRecordingsFromPoint(point, tileBox, objects);
} }
} }
public void getRecordingsFromPoint(PointF point, RotatedTileBox tileBox, List<? super Recording> am) { public void getRecordingsFromPoint(PointF point, RotatedTileBox tileBox, List<? super Recording> am) {
int ex = (int) point.x; int ex = (int) point.x;
int ey = (int) point.y; int ey = (int) point.y;
@ -182,17 +201,31 @@ public class AudioNotesLayer extends OsmandMapLayer implements IContextMenuProvi
} }
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) { private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ; return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius;
} }
@Override @Override
public LatLon getObjectLocation(Object o) { public LatLon getObjectLocation(Object o) {
if(o instanceof Recording){ if (o instanceof Recording) {
return new LatLon(((Recording)o).getLatitude(), ((Recording)o).getLongitude()); return new LatLon(((Recording) o).getLatitude(), ((Recording) o).getLongitude());
} }
return null; return null;
} }
@Override
public boolean isObjectMovable(Object o) {
return o instanceof Recording;
}
@Override
public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position, @Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
boolean result = false;
if (o instanceof Recording) {
result = ((Recording) o).setLocation(position);
}
if (callback != null) {
callback.onApplyMovedObject(result, o);
}
}
} }

View file

@ -23,6 +23,7 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.StatFs; import android.os.StatFs;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.Display; import android.view.Display;
@ -254,6 +255,18 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
return false; return false;
} }
public boolean setLocation(LatLon latLon) {
File directory = file.getParentFile();
lat = latLon.getLatitude();
lon = latLon.getLongitude();
File to = getBaseFileName(lat, lon, directory, Algorithms.getFileExtension(file));
if (file.renameTo(to)) {
file = to;
return true;
}
return false;
}
public String getFileName() { public String getFileName() {
return file.getName(); return file.getName();
} }
@ -764,14 +777,18 @@ public class AudioVideoNotesPlugin extends OsmandPlugin {
} }
} }
private File getBaseFileName(double lat, double lon, OsmandApplication app, String ext) { private static File getBaseFileName(double lat, double lon, OsmandApplication app, String ext) {
File baseDir = app.getAppPath(IndexConstants.AV_INDEX_DIR);
return getBaseFileName(lat, lon, baseDir, ext);
}
private static File getBaseFileName(double lat, double lon, @NonNull File baseDir, @NonNull String ext) {
String basename = MapUtils.createShortLinkString(lat, lon, 15); String basename = MapUtils.createShortLinkString(lat, lon, 15);
int k = 1; int k = 1;
File f = app.getAppPath(IndexConstants.AV_INDEX_DIR); baseDir.mkdirs();
f.mkdirs();
File fl; File fl;
do { do {
fl = new File(f, basename + "." + (k++) + "." + ext); fl = new File(baseDir, basename + "." + (k++) + "." + ext);
} while (fl.exists()); } while (fl.exists());
return fl; return fl;
} }

View file

@ -24,6 +24,7 @@ import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import net.osmand.CallbackWithObject; import net.osmand.CallbackWithObject;
import net.osmand.IndexConstants; import net.osmand.IndexConstants;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
@ -55,7 +56,6 @@ import net.osmand.util.MapUtils;
import java.io.File; import java.io.File;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -68,7 +68,7 @@ public class DistanceCalculatorPlugin extends OsmandPlugin {
private DistanceCalculatorLayer distanceCalculatorLayer; private DistanceCalculatorLayer distanceCalculatorLayer;
private TextInfoWidget distanceControl; private TextInfoWidget distanceControl;
private List<LinkedList<WptPt>> measurementPoints = new ArrayList<LinkedList<WptPt>>(); private List<LinkedList<WptPt>> measurementPoints = new ArrayList<>();
private GPXFile originalGPX; private GPXFile originalGPX;
private String distance = null; private String distance = null;
@ -320,7 +320,8 @@ public class DistanceCalculatorPlugin extends OsmandPlugin {
b.show(); b.show();
} }
private void saveGpx(final MapActivity activity, final String fileNameSave) { private void saveGpx(final MapActivity activity,
final String fileNameSave) {
final AsyncTask<Void, Void, String> exportTask = new AsyncTask<Void, Void, String>() { final AsyncTask<Void, Void, String> exportTask = new AsyncTask<Void, Void, String>() {
private ProgressDialog dlg; private ProgressDialog dlg;
private File toSave; private File toSave;
@ -383,9 +384,7 @@ public class DistanceCalculatorPlugin extends OsmandPlugin {
} }
}; };
}; };
exportTask.execute(new Void[0]); exportTask.execute();
} }
private void startEditingHelp(MapActivity ctx) { private void startEditingHelp(MapActivity ctx) {
final CommonPreference<Boolean> pref = app.getSettings().registerBooleanPreference("show_measurement_help_first_time", true); final CommonPreference<Boolean> pref = app.getSettings().registerBooleanPreference("show_measurement_help_first_time", true);
@ -643,9 +642,8 @@ public class DistanceCalculatorPlugin extends OsmandPlugin {
final WptPt p = (WptPt) o; final WptPt p = (WptPt) o;
boolean containsPoint = false; boolean containsPoint = false;
for (int i = 0; i < measurementPoints.size(); i++) { for (int i = 0; i < measurementPoints.size(); i++) {
Iterator<WptPt> it = measurementPoints.get(i).iterator(); for (WptPt wptPt : measurementPoints.get(i)) {
while (it.hasNext()) { if (wptPt == p) {
if (it.next() == p) {
containsPoint = true; containsPoint = true;
break; break;
} }

View file

@ -138,14 +138,15 @@ public class AvoidSpecificRoads {
@Override @Override
public boolean processResult(LatLon result) { public boolean processResult(LatLon result) {
addImpassableRoad(mapActivity, result, true); addImpassableRoad(mapActivity, result, true, null);
return true; return true;
} }
}); });
} }
public void addImpassableRoad(final MapActivity activity, final LatLon loc, final boolean showDialog) { public void addImpassableRoad(final MapActivity activity, final LatLon loc,
final boolean showDialog, final AvoidSpecificRoadsCallback callback) {
final Location ll = new Location(""); final Location ll = new Location("");
ll.setLatitude(loc.getLatitude()); ll.setLatitude(loc.getLatitude());
ll.setLongitude(loc.getLongitude()); ll.setLongitude(loc.getLongitude());
@ -153,34 +154,85 @@ public class AvoidSpecificRoads {
@Override @Override
public boolean publish(RouteDataObject object) { public boolean publish(RouteDataObject object) {
if(object == null) { if (object == null) {
Toast.makeText(activity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show(); Toast.makeText(activity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show();
if (callback != null) {
callback.onAddImpassableRoad(false, null);
}
} else { } else {
getBuilder().addImpassableRoad(object, ll); addImpassableRoadInternal(object, ll, showDialog, activity, loc);
RoutingHelper rh = app.getRoutingHelper();
if(rh.isRouteCalculated() || rh.isRouteBeingCalculated()) { if (callback != null) {
rh.recalculateRouteDueToSettingsChange(); callback.onAddImpassableRoad(true, object);
} }
if (showDialog) {
showDialog(activity);
}
MapContextMenu menu = activity.getContextMenu();
if (menu.isActive() && menu.getLatLon().equals(loc)) {
menu.close();
}
activity.refreshMap();
} }
return true; return true;
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
if (callback != null) {
return callback.isCancelled();
}
return false; return false;
} }
}); });
} }
public void replaceImpassableRoad(final MapActivity activity, final RouteDataObject currentObject,
final LatLon loc, final boolean showDialog,
final AvoidSpecificRoadsCallback callback) {
final Location ll = new Location("");
ll.setLatitude(loc.getLatitude());
ll.setLongitude(loc.getLongitude());
app.getLocationProvider().getRouteSegment(ll, new ResultMatcher<RouteDataObject>() {
@Override
public boolean publish(RouteDataObject object) {
if (object == null) {
Toast.makeText(activity, R.string.error_avoid_specific_road, Toast.LENGTH_LONG).show();
if (callback != null) {
callback.onAddImpassableRoad(false, null);
}
} else {
getBuilder().removeImpassableRoad(currentObject);
addImpassableRoadInternal(object, ll, showDialog, activity, loc);
if (callback != null) {
callback.onAddImpassableRoad(true, object);
}
}
return true;
}
@Override
public boolean isCancelled() {
if (callback != null) {
return callback.isCancelled();
}
return false;
}
});
}
private void addImpassableRoadInternal(RouteDataObject object, Location ll, boolean showDialog, MapActivity activity, LatLon loc) {
getBuilder().addImpassableRoad(object, ll);
RoutingHelper rh = app.getRoutingHelper();
if(rh.isRouteCalculated() || rh.isRouteBeingCalculated()) {
rh.recalculateRouteDueToSettingsChange();
}
if (showDialog) {
showDialog(activity);
}
MapContextMenu menu = activity.getContextMenu();
if (menu.isActive() && menu.getLatLon().equals(loc)) {
menu.close();
}
activity.refreshMap();
}
private void showOnMap(MapActivity ctx, double lat, double lon, String name, private void showOnMap(MapActivity ctx, double lat, double lon, String name,
DialogInterface dialog) { DialogInterface dialog) {
AnimateDraggingMapThread thread = ctx.getMapView().getAnimatedDraggingThread(); AnimateDraggingMapThread thread = ctx.getMapView().getAnimatedDraggingThread();
@ -195,4 +247,10 @@ public class AvoidSpecificRoads {
dialog.dismiss(); dialog.dismiss();
} }
public interface AvoidSpecificRoadsCallback {
void onAddImpassableRoad(boolean success, RouteDataObject newObject);
boolean isCancelled();
}
} }

View file

@ -363,7 +363,7 @@ public class ExternalApiHelper {
FavouritesDbHelper helper = app.getFavorites(); FavouritesDbHelper helper = app.getFavorites();
helper.addFavourite(fav); helper.addFavourite(fav);
showOnMap(lat, lon, fav, mapActivity.getMapLayers().getFavoritesLayer().getObjectName(fav)); showOnMap(lat, lon, fav, mapActivity.getMapLayers().getFavouritesLayer().getObjectName(fav));
resultCode = Activity.RESULT_OK; resultCode = Activity.RESULT_OK;
} else if (API_CMD_ADD_MAP_MARKER.equals(cmd)) { } else if (API_CMD_ADD_MAP_MARKER.equals(cmd)) {

View file

@ -3,6 +3,7 @@ package net.osmand.plus.mapcontextmenu;
import android.app.Dialog; import android.app.Dialog;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.app.AlertDialog.Builder; import android.support.v7.app.AlertDialog.Builder;
@ -214,7 +215,7 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL
public MapContextMenu() { public MapContextMenu() {
} }
public boolean init(LatLon latLon, PointDescription pointDescription, Object object) { public boolean init(LatLon latLon, PointDescription pointDescription, @Nullable Object object) {
return init(latLon, pointDescription, object, false); return init(latLon, pointDescription, object, false);
} }
@ -295,7 +296,7 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL
} }
} }
public void show(LatLon latLon, PointDescription pointDescription, Object object) { public void show(LatLon latLon, PointDescription pointDescription, @Nullable Object object) {
if (init(latLon, pointDescription, object)) { if (init(latLon, pointDescription, object)) {
if (!MapContextMenuFragment.showInstance(this, mapActivity, centerMarker)) { if (!MapContextMenuFragment.showInstance(this, mapActivity, centerMarker)) {
active = false; active = false;
@ -406,7 +407,7 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL
} }
} }
private void setSelectedObject(Object object) { private void setSelectedObject(@Nullable Object object) {
if (object != null) { if (object != null) {
for (OsmandMapLayer l : mapActivity.getMapView().getLayers()) { for (OsmandMapLayer l : mapActivity.getMapView().getLayers()) {
if (l instanceof ContextMenuLayer.IContextMenuProvider) { if (l instanceof ContextMenuLayer.IContextMenuProvider) {

View file

@ -1,6 +1,7 @@
package net.osmand.plus.mapcontextmenu.controllers; package net.osmand.plus.mapcontextmenu.controllers;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import net.osmand.binary.RouteDataObject; import net.osmand.binary.RouteDataObject;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
@ -47,6 +48,6 @@ public class ImpassibleRoadsMenuController extends MenuController {
@Override @Override
public Drawable getLeftIcon() { public Drawable getLeftIcon() {
return getMapActivity().getResources().getDrawable(R.drawable.map_pin_avoid_road); return ContextCompat.getDrawable(getMapActivity(), R.drawable.map_pin_avoid_road);
} }
} }

View file

@ -455,7 +455,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
} }
public static void commitNode(final OsmPoint.Action action, public static void commitNode(final OsmPoint.Action action,
final Node n, final Node node,
final EntityInfo info, final EntityInfo info,
final String comment, final String comment,
final boolean closeChangeSet, final boolean closeChangeSet,
@ -477,7 +477,7 @@ public class EditPoiDialogFragment extends BaseOsmAndDialogFragment {
@Override @Override
protected Node doInBackground(Void... params) { protected Node doInBackground(Void... params) {
return openstreetmapUtil.commitNodeImpl(action, n, info, comment, closeChangeSet); return openstreetmapUtil.commitNodeImpl(action, node, info, comment, closeChangeSet);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package net.osmand.plus.osmedit; package net.osmand.plus.osmedit;
import android.annotation.SuppressLint;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
@ -8,13 +9,13 @@ import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Xml; import android.util.Xml;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.EditText; import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
import net.osmand.AndroidUtils; import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
@ -61,11 +62,6 @@ public class OsmBugsLayer extends OsmandMapLayer implements IContextMenuProvider
private Bitmap resolvedNoteSmall; private Bitmap resolvedNoteSmall;
private final MapActivity activity; private final MapActivity activity;
protected static final String KEY_BUG = "bug";
protected static final String KEY_TEXT = "text";
protected static final String KEY_ACTION = "action";
private static final int DIALOG_BUG = 305;
private static Bundle dialogBundle = new Bundle();
private OsmBugsLocalUtil local; private OsmBugsLocalUtil local;
private MapLayerData<List<OpenStreetNote>> data; private MapLayerData<List<OpenStreetNote>> data;
@ -400,6 +396,7 @@ public class OsmBugsLayer extends OsmandMapLayer implements IContextMenuProvider
OsmBugsUtil util = getOsmbugsUtil(bug); OsmBugsUtil util = getOsmbugsUtil(bug);
final boolean offline = util instanceof OsmBugsLocalUtil; final boolean offline = util instanceof OsmBugsLocalUtil;
@SuppressLint("InflateParams")
final View view = LayoutInflater.from(activity).inflate(R.layout.open_bug, null); final View view = LayoutInflater.from(activity).inflate(R.layout.open_bug, null);
if (offline) { if (offline) {
view.findViewById(R.id.user_name_field).setVisibility(View.GONE); view.findViewById(R.id.user_name_field).setVisibility(View.GONE);

View file

@ -5,9 +5,15 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.Toast;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.osm.edit.Node;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.ContextMenuLayer; import net.osmand.plus.views.ContextMenuLayer;
@ -17,25 +23,25 @@ import net.osmand.plus.views.OsmandMapTileView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider,
* Created by Denis on ContextMenuLayer.IMoveObjectProvider {
* 20.03.2015.
*/
public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider {
private static final int startZoom = 10; private static final int startZoom = 10;
private final OsmEditingPlugin plugin; private final OsmEditingPlugin plugin;
private final MapActivity activity; private final MapActivity activity;
private final OpenstreetmapLocalUtil mOsmChangeUtil;
private final OsmBugsLocalUtil mOsmBugsUtil;
private Bitmap poi; private Bitmap poi;
private Bitmap bug; private Bitmap bug;
private OsmandMapTileView view; private OsmandMapTileView view;
private Paint paintIcon; private Paint paintIcon;
private ContextMenuLayer contextMenuLayer;
public OsmEditsLayer(MapActivity activity, OsmEditingPlugin plugin) { public OsmEditsLayer(MapActivity activity, OsmEditingPlugin plugin) {
this.activity = activity; this.activity = activity;
this.plugin = plugin; this.plugin = plugin;
mOsmChangeUtil = plugin.getPoiModificationLocalUtil();
mOsmBugsUtil = plugin.getOsmNotesLocalUtil();
} }
@Override @Override
@ -43,13 +49,19 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
this.view = view; this.view = view;
poi = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_poi); poi = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_poi);
bug = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_poi); bug = poi;
paintIcon = new Paint(); paintIcon = new Paint();
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (contextMenuLayer.getMoveableObject() instanceof OsmPoint) {
OsmPoint objectInMotion = (OsmPoint) contextMenuLayer.getMoveableObject();
PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
drawPoint(canvas, objectInMotion, pf.x, pf.y);
}
} }
@Override @Override
@ -65,21 +77,27 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
private void drawPoints(Canvas canvas, RotatedTileBox tileBox, List<? extends OsmPoint> objects, private void drawPoints(Canvas canvas, RotatedTileBox tileBox, List<? extends OsmPoint> objects,
List<LatLon> fullObjectsLatLon) { List<LatLon> fullObjectsLatLon) {
for (OsmPoint o : objects) { for (OsmPoint o : objects) {
float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude()); if (contextMenuLayer.getMoveableObject() != o) {
float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude()); float x = tileBox.getPixXFromLatLon(o.getLatitude(), o.getLongitude());
Bitmap b; float y = tileBox.getPixYFromLatLon(o.getLatitude(), o.getLongitude());
if (o.getGroup() == OsmPoint.Group.POI) { drawPoint(canvas, o, x, y);
b = poi; fullObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude()));
} else if (o.getGroup() == OsmPoint.Group.BUG) {
b = bug;
} else {
b = poi;
} }
canvas.drawBitmap(b, x - b.getWidth() / 2, y - b.getHeight() / 2, paintIcon);
fullObjectsLatLon.add(new LatLon(o.getLatitude(), o.getLongitude()));
} }
} }
private void drawPoint(Canvas canvas, OsmPoint o, float x, float y) {
Bitmap b;
if (o.getGroup() == OsmPoint.Group.POI) {
b = poi;
} else if (o.getGroup() == OsmPoint.Group.BUG) {
b = bug;
} else {
b = poi;
}
canvas.drawBitmap(b, x - b.getWidth() / 2, y - b.getHeight() / 2, paintIcon);
}
@Override @Override
public void destroyLayer() { public void destroyLayer() {
@ -97,11 +115,11 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
int compare = getRadiusPoi(tileBox); int compare = getRadiusPoi(tileBox);
int radius = compare * 3 / 2; int radius = compare * 3 / 2;
compare = getFromPoint(tileBox, am, ex, ey, compare, radius, plugin.getDBBug().getOsmbugsPoints()); compare = getFromPoint(tileBox, am, ex, ey, compare, radius, plugin.getDBBug().getOsmbugsPoints());
compare = getFromPoint(tileBox, am, ex, ey, compare, radius, plugin.getDBPOI().getOpenstreetmapPoints()); getFromPoint(tileBox, am, ex, ey, compare, radius, plugin.getDBPOI().getOpenstreetmapPoints());
} }
private int getFromPoint(RotatedTileBox tileBox, List<? super OsmPoint> am, int ex, int ey, int compare, private int getFromPoint(RotatedTileBox tileBox, List<? super OsmPoint> am, int ex, int ey, int compare,
int radius, List<? extends OsmPoint> pnts) { int radius, List<? extends OsmPoint> pnts) {
for (OsmPoint n : pnts) { for (OsmPoint n : pnts) {
int x = (int) tileBox.getPixXFromLatLon(n.getLatitude(), n.getLongitude()); int x = (int) tileBox.getPixXFromLatLon(n.getLatitude(), n.getLongitude());
int y = (int) tileBox.getPixYFromLatLon(n.getLatitude(), n.getLongitude()); int y = (int) tileBox.getPixYFromLatLon(n.getLatitude(), n.getLongitude());
@ -114,12 +132,12 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
} }
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) { private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ; return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius;
} }
public int getRadiusPoi(RotatedTileBox tb){ public int getRadiusPoi(RotatedTileBox tb) {
int r = 0; int r;
if(tb.getZoom() < startZoom){ if (tb.getZoom() < startZoom) {
r = 0; r = 0;
} else { } else {
r = 15; r = 15;
@ -152,7 +170,7 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
@Override @Override
public LatLon getObjectLocation(Object o) { public LatLon getObjectLocation(Object o) {
if (o instanceof OsmPoint) { if (o instanceof OsmPoint) {
return new LatLon(((OsmPoint)o).getLatitude(),((OsmPoint)o).getLongitude()); return new LatLon(((OsmPoint) o).getLatitude(), ((OsmPoint) o).getLongitude());
} }
return null; return null;
} }
@ -160,11 +178,11 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
@Override @Override
public PointDescription getObjectName(Object o) { public PointDescription getObjectName(Object o) {
if(o instanceof OsmPoint) { if (o instanceof OsmPoint) {
OsmPoint point = (OsmPoint) o; OsmPoint point = (OsmPoint) o;
String name = ""; String name = "";
String type = ""; String type = "";
if (point.getGroup() == OsmPoint.Group.POI){ if (point.getGroup() == OsmPoint.Group.POI) {
name = ((OpenstreetmapPoint) point).getName(); name = ((OpenstreetmapPoint) point).getName();
type = PointDescription.POINT_TYPE_OSM_NOTE; type = PointDescription.POINT_TYPE_OSM_NOTE;
} else if (point.getGroup() == OsmPoint.Group.BUG) { } else if (point.getGroup() == OsmPoint.Group.BUG) {
@ -176,4 +194,100 @@ public class OsmEditsLayer extends OsmandMapLayer implements ContextMenuLayer.IC
return null; return null;
} }
@Override
public boolean isObjectMovable(Object o) {
return o instanceof OsmPoint;
}
@Override
public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position, @Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
if (o instanceof OsmPoint) {
if (o instanceof OpenstreetmapPoint) {
OpenstreetmapPoint objectInMotion = (OpenstreetmapPoint) o;
Node node = objectInMotion.getEntity();
node.setLatitude(position.getLatitude());
node.setLongitude(position.getLongitude());
new SaveOsmChangeAsyncTask(mOsmChangeUtil, callback).execute(node);
} else if (o instanceof OsmNotesPoint) {
OsmNotesPoint objectInMotion = (OsmNotesPoint) o;
objectInMotion.setLatitude(position.getLatitude());
objectInMotion.setLongitude(position.getLongitude());
new SaveOsmNoteAsyncTask(objectInMotion.getText(), activity, callback, plugin, mOsmBugsUtil)
.execute(objectInMotion);
}
} else if (callback != null) {
callback.onApplyMovedObject(false, o);
}
}
static class SaveOsmChangeAsyncTask extends AsyncTask<Node, Void, Node> {
private final OpenstreetmapLocalUtil mOpenstreetmapUtil;
@Nullable
private final ContextMenuLayer.ApplyMovedObjectCallback mCallback;
SaveOsmChangeAsyncTask(OpenstreetmapLocalUtil openstreetmapUtil,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
this.mOpenstreetmapUtil = openstreetmapUtil;
this.mCallback = callback;
}
@Override
protected Node doInBackground(Node... params) {
Node node = params[0];
return mOpenstreetmapUtil.commitNodeImpl(OsmPoint.Action.MODIFY, node,
mOpenstreetmapUtil.getEntityInfo(node.getId()), "", false);
}
@Override
protected void onPostExecute(Node newNode) {
if (mCallback != null) {
mCallback.onApplyMovedObject(true, newNode);
}
}
}
private static class SaveOsmNoteAsyncTask extends AsyncTask<OsmNotesPoint, Void, Boolean> {
private final String mText;
private final MapActivity mActivity;
@Nullable
private final ContextMenuLayer.ApplyMovedObjectCallback mCallback;
private final OsmEditingPlugin plugin;
private OsmBugsUtil mOsmbugsUtil;
private OsmNotesPoint mOsmNotesPoint;
public SaveOsmNoteAsyncTask(String text,
MapActivity activity,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback,
OsmEditingPlugin plugin, OsmBugsUtil osmbugsUtil) {
mText = text;
mActivity = activity;
mCallback = callback;
this.plugin = plugin;
mOsmbugsUtil = osmbugsUtil;
}
@Override
protected Boolean doInBackground(OsmNotesPoint... params) {
mOsmNotesPoint = params[0];
OsmPoint.Action action = mOsmNotesPoint.getAction();
boolean isSuccess = plugin.getDBBug().deleteAllBugModifications(mOsmNotesPoint);
OsmBugsUtil.OsmBugResult result = mOsmbugsUtil.commit(mOsmNotesPoint, mText, action);
isSuccess &= isOperationSuccessfull(result);
return isSuccess;
}
private boolean isOperationSuccessfull(OsmBugsUtil.OsmBugResult result) {
return result != null && result.warning == null;
}
@Override
protected void onPostExecute(Boolean isSuccess) {
if (isSuccess) {
Toast.makeText(mActivity, R.string.osm_changes_added_to_local_edits, Toast.LENGTH_LONG).show();
}
if (mCallback != null) {
mCallback.onApplyMovedObject(isSuccess, mOsmNotesPoint);
}
}
}
} }

View file

@ -1,6 +1,15 @@
package net.osmand.plus.parkingpoint; package net.osmand.plus.parkingpoint;
import java.util.List; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
@ -10,14 +19,8 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.ContextMenuLayer; import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.plus.views.OsmandMapLayer; import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import android.content.Context;
import android.graphics.Bitmap; import java.util.List;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.DisplayMetrics;
import android.view.WindowManager;
/** /**
* Class represents a layer which depicts the position of the parked car * Class represents a layer which depicts the position of the parked car
@ -25,7 +28,8 @@ import android.view.WindowManager;
* @see ParkingPositionPlugin * @see ParkingPositionPlugin
* *
*/ */
public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider { public class ParkingPositionLayer extends OsmandMapLayer implements
ContextMenuLayer.IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider {
/** /**
* magic number so far * magic number so far
*/ */
@ -45,6 +49,8 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
private ParkingPositionPlugin plugin; private ParkingPositionPlugin plugin;
private ContextMenuLayer contextMenuLayer;
public ParkingPositionLayer(MapActivity map, ParkingPositionPlugin plugin) { public ParkingPositionLayer(MapActivity map, ParkingPositionPlugin plugin) {
this.map = map; this.map = map;
this.plugin = plugin; this.plugin = plugin;
@ -68,11 +74,14 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
parkingNoLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_poi_parking_pos_no_limit); parkingNoLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_poi_parking_pos_no_limit);
parkingLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_poi_parking_pos_limit); parkingLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_poi_parking_pos_limit);
timeLimit = plugin.getParkingType(); timeLimit = plugin.getParkingType();
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings nightMode) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
LatLon parkingPoint = getParkingPoint(); LatLon parkingPoint = getParkingPoint();
boolean inMotion = parkingPoint == contextMenuLayer.getMoveableObject();
if (parkingPoint == null) if (parkingPoint == null)
return; return;
@ -84,11 +93,19 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
} }
double latitude = parkingPoint.getLatitude(); double latitude = parkingPoint.getLatitude();
double longitude = parkingPoint.getLongitude(); double longitude = parkingPoint.getLongitude();
if (isLocationVisible(tb, latitude, longitude)) { if (isLocationVisible(tileBox, latitude, longitude) || inMotion) {
int marginX = parkingNoLimitIcon.getWidth() / 2; int marginX = parkingNoLimitIcon.getWidth() / 2;
int marginY = parkingNoLimitIcon.getHeight() / 2; int marginY = parkingNoLimitIcon.getHeight() / 2;
int locationX = tb.getPixXFromLonNoRot(longitude); float locationX;
int locationY = tb.getPixYFromLatNoRot(latitude); float locationY;
if (inMotion) {
PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
locationX = pf.x;
locationY = pf.y;
} else {
locationX = tileBox.getPixXFromLonNoRot(longitude);
locationY = tileBox.getPixYFromLatNoRot(latitude);
}
canvas.rotate(-view.getRotate(), locationX, locationY); canvas.rotate(-view.getRotate(), locationX, locationY);
canvas.drawBitmap(parkingIcon, locationX - marginX, locationY - marginY, bitmapPaint); canvas.drawBitmap(parkingIcon, locationX - marginX, locationY - marginY, bitmapPaint);
} }
@ -183,5 +200,22 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
} }
} }
@Override
public boolean isObjectMovable(Object o) {
return o == getParkingPoint();
}
@Override
public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
boolean result = false;
if (o == getParkingPoint()) {
plugin.setParkingPosition(position.getLatitude(), position.getLongitude());
result = true;
}
if (callback != null) {
callback.onApplyMovedObject(result, getParkingPoint());
}
}
} }

View file

@ -10,6 +10,7 @@ import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Vibrator; import android.os.Vibrator;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission; import android.support.annotation.RequiresPermission;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.view.GestureDetector; import android.view.GestureDetector;
@ -58,6 +59,8 @@ public class ContextMenuLayer extends OsmandMapLayer {
private final MoveMarkerBottomSheetHelper mMoveMarkerBottomSheetHelper; private final MoveMarkerBottomSheetHelper mMoveMarkerBottomSheetHelper;
private boolean mInChangeMarkerPositionMode; private boolean mInChangeMarkerPositionMode;
private IContextMenuProvider selectedObjectContextMenuProvider; private IContextMenuProvider selectedObjectContextMenuProvider;
private boolean cancelApplyingNewMarkerPosition;
private LatLon applyingMarkerLatLon;
public ContextMenuLayer(MapActivity activity) { public ContextMenuLayer(MapActivity activity) {
this.activity = activity; this.activity = activity;
@ -133,14 +136,25 @@ public class ContextMenuLayer extends OsmandMapLayer {
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) { public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) {
if (itemId == R.string.shared_string_show_description) { if (itemId == R.string.shared_string_show_description) {
menu.openMenuFullScreen(); menu.openMenuFullScreen();
} else if (itemId == R.string.change_markers_position) {
RotatedTileBox tileBox = activity.getMapView().getCurrentRotatedTileBox();
enterMovingMode(tileBox);
} }
return true; return true;
} }
}; };
adapter.addItem(new ContextMenuItem.ItemBuilder() adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.shared_string_show_description, activity) .setTitleId(R.string.shared_string_show_description, activity)
.setIcon(R.drawable.ic_action_note_dark).setListener(listener) .setIcon(R.drawable.ic_action_note_dark)
.setListener(listener)
.createItem()); .createItem());
if (isObjectMoveable(o)) {
adapter.addItem(new ContextMenuItem.ItemBuilder()
.setTitleId(R.string.change_markers_position, activity)
.setIcon(R.drawable.ic_show_on_map)
.setListener(listener)
.createItem());
}
} }
} }
@ -153,22 +167,7 @@ public class ContextMenuLayer extends OsmandMapLayer {
if (pressedContextMarker(tileBox, point.x, point.y)) { if (pressedContextMarker(tileBox, point.x, point.y)) {
Object obj = menu.getObject(); Object obj = menu.getObject();
if (isObjectMoveable(obj)) { if (isObjectMoveable(obj)) {
Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); enterMovingMode(tileBox);
vibrator.vibrate(VIBRATE_SHORT);
menu.updateMapCenter(null);
menu.hide();
LatLon ll = menu.getLatLon();
RotatedTileBox rb = new RotatedTileBox(tileBox);
rb.setCenterLocation(0.5f, 0.5f);
rb.setLatLonCenter(ll.getLatitude(), ll.getLongitude());
double lat = rb.getLatFromPixel(tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
double lon = rb.getLonFromPixel(tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
view.setLatLon(lat, lon);
enterMovingMode();
view.refreshMap();
return true; return true;
} }
return false; return false;
@ -181,7 +180,13 @@ public class ContextMenuLayer extends OsmandMapLayer {
public PointF getMoveableCenterPoint(RotatedTileBox tb) { public PointF getMoveableCenterPoint(RotatedTileBox tb) {
return new PointF(tb.getPixWidth() / 2, tb.getPixHeight() / 2); if (applyingMarkerLatLon != null) {
float x = tb.getPixXFromLatLon(applyingMarkerLatLon.getLatitude(), applyingMarkerLatLon.getLongitude());
float y = tb.getPixYFromLatLon(applyingMarkerLatLon.getLatitude(), applyingMarkerLatLon.getLongitude());
return new PointF(x, y);
} else {
return new PointF(tb.getPixWidth() / 2, tb.getPixHeight() / 2);
}
} }
public Object getMoveableObject() { public Object getMoveableObject() {
@ -198,20 +203,23 @@ public class ContextMenuLayer extends OsmandMapLayer {
} else if (selectedObjectContextMenuProvider != null } else if (selectedObjectContextMenuProvider != null
&& selectedObjectContextMenuProvider instanceof ContextMenuLayer.IMoveObjectProvider) { && selectedObjectContextMenuProvider instanceof ContextMenuLayer.IMoveObjectProvider) {
final IMoveObjectProvider l = (ContextMenuLayer.IMoveObjectProvider) selectedObjectContextMenuProvider; final IMoveObjectProvider l = (ContextMenuLayer.IMoveObjectProvider) selectedObjectContextMenuProvider;
if (l.isObjectMoveable(o)) { if (l.isObjectMovable(o)) {
return true; return true;
} }
} }
return false; return false;
} }
public void applyMovedObject(Object o, LatLon position) { public void applyMovedObject(Object o, LatLon position, ApplyMovedObjectCallback callback) {
if (selectedObjectContextMenuProvider != null if (selectedObjectContextMenuProvider != null) {
&& selectedObjectContextMenuProvider instanceof ContextMenuLayer.IMoveObjectProvider) { if (selectedObjectContextMenuProvider instanceof IMoveObjectProvider) {
final IMoveObjectProvider l = (ContextMenuLayer.IMoveObjectProvider) selectedObjectContextMenuProvider; final IMoveObjectProvider l = (IMoveObjectProvider) selectedObjectContextMenuProvider;
if (l.isObjectMoveable(o)) { if (l.isObjectMovable(o)) {
l.applyNewObjectPosition(o, position); l.applyNewObjectPosition(o, position, callback);
}
} }
} else if (mInChangeMarkerPositionMode) {
callback.onApplyMovedObject(true, null);
} }
} }
@ -222,18 +230,35 @@ public class ContextMenuLayer extends OsmandMapLayer {
RotatedTileBox tileBox = activity.getMapView().getCurrentRotatedTileBox(); RotatedTileBox tileBox = activity.getMapView().getCurrentRotatedTileBox();
PointF newMarkerPosition = getMoveableCenterPoint(tileBox); PointF newMarkerPosition = getMoveableCenterPoint(tileBox);
LatLon ll = tileBox.getLatLonFromPixel(newMarkerPosition.x, newMarkerPosition.y); final LatLon ll = tileBox.getLatLonFromPixel(newMarkerPosition.x, newMarkerPosition.y);
applyingMarkerLatLon = ll;
Object obj = getMoveableObject(); Object obj = getMoveableObject();
applyMovedObject(obj, ll); cancelApplyingNewMarkerPosition = false;
quitMovingMarker(); mMoveMarkerBottomSheetHelper.enterApplyPositionMode();
applyMovedObject(obj, ll, new ApplyMovedObjectCallback() {
@Override
public void onApplyMovedObject(boolean success, @Nullable Object newObject) {
mMoveMarkerBottomSheetHelper.exitApplyPositionMode();
if (success && !cancelApplyingNewMarkerPosition) {
mMoveMarkerBottomSheetHelper.hide();
quitMovingMarker();
PointDescription pointDescription = null; PointDescription pointDescription = null;
if (selectedObjectContextMenuProvider != null) { if (selectedObjectContextMenuProvider != null) {
pointDescription = selectedObjectContextMenuProvider.getObjectName(obj); pointDescription = selectedObjectContextMenuProvider.getObjectName(newObject);
} }
menu.show(ll, pointDescription, obj); menu.show(ll, pointDescription, newObject);
view.refreshMap(); view.refreshMap();
}
applyingMarkerLatLon = null;
}
@Override
public boolean isCancelled() {
return cancelApplyingNewMarkerPosition;
}
});
} }
private void quitMovingMarker() { private void quitMovingMarker() {
@ -242,11 +267,27 @@ public class ContextMenuLayer extends OsmandMapLayer {
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info); R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
} }
private void enterMovingMode() { private void enterMovingMode(RotatedTileBox tileBox) {
Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_SHORT);
menu.updateMapCenter(null);
menu.hide();
LatLon ll = menu.getLatLon();
RotatedTileBox rb = new RotatedTileBox(tileBox);
rb.setCenterLocation(0.5f, 0.5f);
rb.setLatLonCenter(ll.getLatitude(), ll.getLongitude());
double lat = rb.getLatFromPixel(tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
double lon = rb.getLonFromPixel(tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
view.setLatLon(lat, lon);
mInChangeMarkerPositionMode = true; mInChangeMarkerPositionMode = true;
mMoveMarkerBottomSheetHelper.show(menu.getLeftIcon()); mMoveMarkerBottomSheetHelper.show(menu.getLeftIcon());
mark(View.INVISIBLE, R.id.map_ruler_layout, mark(View.INVISIBLE, R.id.map_ruler_layout,
R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info); R.id.map_left_widgets_panel, R.id.map_right_widgets_panel, R.id.map_center_info);
view.refreshMap();
} }
private void mark(int status, int... widgets) { private void mark(int status, int... widgets) {
@ -259,8 +300,10 @@ public class ContextMenuLayer extends OsmandMapLayer {
} }
public void cancelMovingMarker() { public void cancelMovingMarker() {
cancelApplyingNewMarkerPosition = true;
quitMovingMarker(); quitMovingMarker();
activity.getContextMenu().show(); activity.getContextMenu().show();
applyingMarkerLatLon = null;
} }
public boolean showContextMenu(double latitude, double longitude, boolean showUnknownLocation) { public boolean showContextMenu(double latitude, double longitude, boolean showUnknownLocation) {
@ -492,12 +535,19 @@ public class ContextMenuLayer extends OsmandMapLayer {
public interface IMoveObjectProvider { public interface IMoveObjectProvider {
boolean isObjectMoveable(Object o); boolean isObjectMovable(Object o);
boolean applyNewObjectPosition(Object o, LatLon position);
void applyNewObjectPosition(@NonNull Object o,
@NonNull LatLon position,
@Nullable ApplyMovedObjectCallback callback);
} }
public interface ApplyMovedObjectCallback {
void onApplyMovedObject(boolean success, @Nullable Object newObject);
boolean isCancelled();
}
public interface IContextMenuProviderSelection { public interface IContextMenuProviderSelection {

View file

@ -9,6 +9,8 @@ import android.graphics.PointF;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.support.annotation.ColorInt; import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import net.osmand.data.FavouritePoint; import net.osmand.data.FavouritePoint;
@ -21,12 +23,13 @@ import net.osmand.plus.FavouritesDbHelper;
import net.osmand.plus.OsmandSettings; import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.base.FavoriteImageDrawable; import net.osmand.plus.base.FavoriteImageDrawable;
import net.osmand.plus.views.ContextMenuLayer.ApplyMovedObjectCallback;
import net.osmand.plus.views.MapTextLayer.MapTextProvider; import net.osmand.plus.views.MapTextLayer.MapTextProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class FavoritesLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider, public class FavouritesLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider,
ContextMenuLayer.IMoveObjectProvider, MapTextProvider<FavouritePoint> { ContextMenuLayer.IMoveObjectProvider, MapTextProvider<FavouritePoint> {
protected int startZoom = 6; protected int startZoom = 6;
@ -36,14 +39,13 @@ public class FavoritesLayer extends OsmandMapLayer implements ContextMenuLayer.
private FavouritesDbHelper favorites; private FavouritesDbHelper favorites;
protected List<FavouritePoint> cache = new ArrayList<>(); protected List<FavouritePoint> cache = new ArrayList<>();
private MapTextLayer textLayer; private MapTextLayer textLayer;
private ContextMenuLayer contextMenuLayer;
private Paint paintIcon; private Paint paintIcon;
private Bitmap pointSmall; private Bitmap pointSmall;
private int defaultColor; private int defaultColor;
private OsmandSettings settings; private OsmandSettings settings;
private ContextMenuLayer contextMenuLayer;
protected String getObjName() { protected String getObjName() {
return view.getContext().getString(R.string.favorite); return view.getContext().getString(R.string.favorite);
@ -63,10 +65,10 @@ public class FavoritesLayer extends OsmandMapLayer implements ContextMenuLayer.
settings = view.getApplication().getSettings(); settings = view.getApplication().getSettings();
favorites = view.getApplication().getFavorites(); favorites = view.getApplication().getFavorites();
textLayer = view.getLayerByClass(MapTextLayer.class); textLayer = view.getLayerByClass(MapTextLayer.class);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
paintIcon = new Paint(); paintIcon = new Paint();
pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small); pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small);
defaultColor = ContextCompat.getColor(view.getContext(), R.color.color_favorite); defaultColor = ContextCompat.getColor(view.getContext(), R.color.color_favorite);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) { private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
@ -90,8 +92,9 @@ public class FavoritesLayer extends OsmandMapLayer implements ContextMenuLayer.
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (contextMenuLayer.getMoveableObject() instanceof FavouritePoint) { if (contextMenuLayer.getMoveableObject() instanceof FavouritePoint) {
FavouritePoint fp = (FavouritePoint) contextMenuLayer.getMoveableObject(); FavouritePoint objectInMotion = (FavouritePoint) contextMenuLayer.getMoveableObject();
FavoriteImageDrawable fid = FavoriteImageDrawable.getOrCreate(view.getContext(), fp.getColor(), true); FavoriteImageDrawable fid = FavoriteImageDrawable.getOrCreate(view.getContext(),
objectInMotion.getColor(), true);
PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox); PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
fid.drawBitmapInCenter(canvas, pf.x, pf.y); fid.drawBitmapInCenter(canvas, pf.x, pf.y);
} }
@ -238,17 +241,22 @@ public class FavoritesLayer extends OsmandMapLayer implements ContextMenuLayer.
@Override @Override
public boolean isObjectMoveable(Object o) { public boolean isObjectMovable(Object o) {
return o instanceof FavouritePoint; return o instanceof FavouritePoint;
} }
@Override @Override
public boolean applyNewObjectPosition(Object o, LatLon position) { public void applyNewObjectPosition(@NonNull Object o,
if(o instanceof FavouritePoint) { @NonNull LatLon position,
favorites.editFavourite((FavouritePoint) o, position.getLatitude(), position.getLongitude()); @Nullable ApplyMovedObjectCallback callback) {
return true; boolean result = false;
if (o instanceof FavouritePoint) {
favorites.editFavourite((FavouritePoint) o, position.getLatitude(), position.getLongitude());
result = true;
}
if (callback != null) {
callback.onApplyMovedObject(result, o);
} }
return false;
} }
} }

View file

@ -12,11 +12,18 @@ import android.graphics.PointF;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.os.AsyncTask;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect; import net.osmand.data.QuadRect;
import net.osmand.data.QuadTree; import net.osmand.data.QuadTree;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile; import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.TrkSegment; import net.osmand.plus.GPXUtilities.TrkSegment;
import net.osmand.plus.GPXUtilities.WptPt; import net.osmand.plus.GPXUtilities.WptPt;
@ -24,6 +31,7 @@ import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings.CommonPreference; import net.osmand.plus.OsmandSettings.CommonPreference;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.base.FavoriteImageDrawable; import net.osmand.plus.base.FavoriteImageDrawable;
@ -34,15 +42,18 @@ import net.osmand.render.RenderingRuleProperty;
import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRuleSearchRequest;
import net.osmand.render.RenderingRulesStorage; import net.osmand.render.RenderingRulesStorage;
import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider,
ContextMenuLayer.IMoveObjectProvider, MapTextProvider<WptPt> {
public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider,
MapTextProvider<WptPt> {
private OsmandMapTileView view; private OsmandMapTileView view;
private Paint paint; private Paint paint;
private Paint paint2; private Paint paint2;
private boolean isPaint2; private boolean isPaint2;
@ -57,10 +68,11 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
private static final int startZoom = 7; private static final int startZoom = 7;
private GpxSelectionHelper selectedGpxHelper; private GpxSelectionHelper selectedGpxHelper;
private Paint paintBmp; private Paint paintBmp;
private List<WptPt> cache = new ArrayList<WptPt>(); private List<WptPt> cache = new ArrayList<>();
private Map<WptPt, SelectedGpxFile> pointFileMap = new HashMap<>();
private MapTextLayer textLayer; private MapTextLayer textLayer;
@ -75,7 +87,20 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
private List<TrkSegment> points; private List<TrkSegment> points;
private GPXFile gpx; private GPXFile gpx;
private ContextMenuLayer contextMenuLayer;
@ColorInt
private int visitedColor;
@ColorInt
private int defPointColor;
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
selectedGpxHelper = view.getApplication().getSelectedGpxHelper();
osmandRenderer = view.getApplication().getResourceManager().getRenderer().getRenderer();
initUI();
}
private void initUI() { private void initUI() {
paint = new Paint(); paint = new Paint();
paint.setStyle(Style.STROKE); paint.setStyle(Style.STROKE);
@ -89,21 +114,19 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
paint_1 = new Paint(); paint_1 = new Paint();
paint_1.setStyle(Style.STROKE); paint_1.setStyle(Style.STROKE);
paint_1.setAntiAlias(true); paint_1.setAntiAlias(true);
paintBmp = new Paint(); paintBmp = new Paint();
paintBmp.setAntiAlias(true); paintBmp.setAntiAlias(true);
paintBmp.setFilterBitmap(true); paintBmp.setFilterBitmap(true);
paintBmp.setDither(true); paintBmp.setDither(true);
paintTextIcon = new Paint(); paintTextIcon = new Paint();
paintTextIcon.setTextSize(10 * view.getDensity()); paintTextIcon.setTextSize(10 * view.getDensity());
paintTextIcon.setTextAlign(Align.CENTER); paintTextIcon.setTextAlign(Align.CENTER);
paintTextIcon.setFakeBoldText(true); paintTextIcon.setFakeBoldText(true);
paintTextIcon.setColor(Color.BLACK); paintTextIcon.setColor(Color.BLACK);
paintTextIcon.setAntiAlias(true); paintTextIcon.setAntiAlias(true);
textLayer = view.getLayerByClass(MapTextLayer.class); textLayer = view.getLayerByClass(MapTextLayer.class);
paintOuter = new Paint(); paintOuter = new Paint();
@ -117,43 +140,71 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
paintIcon = new Paint(); paintIcon = new Paint();
pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small); pointSmall = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_white_shield_small);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
visitedColor = ContextCompat.getColor(view.getApplication(), R.color.color_ok);
defPointColor = ContextCompat.getColor(view.getApplication(), R.color.gpx_color_point);
} }
@Override @Override
public void initLayer(OsmandMapTileView view) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
this.view = view; if (contextMenuLayer.getMoveableObject() instanceof WptPt) {
selectedGpxHelper = view.getApplication().getSelectedGpxHelper(); WptPt objectInMotion = (WptPt) contextMenuLayer.getMoveableObject();
osmandRenderer = view.getApplication().getResourceManager().getRenderer().getRenderer(); PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
initUI(); SelectedGpxFile gpxFile = pointFileMap.get(objectInMotion);
if (gpxFile != null) {
drawBigPoint(canvas, objectInMotion, getFileColor(gpxFile), pf.x, pf.y);
}
}
}
@Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (points != null) {
updatePaints(0, false, false, settings, tileBox);
for (TrkSegment ts : points)
ts.drawRenderers(view.getZoom(), paint, canvas, tileBox);
} else {
List<SelectedGpxFile> selectedGPXFiles = selectedGpxHelper.getSelectedGPXFiles();
cache.clear();
if (!selectedGPXFiles.isEmpty()) {
drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings);
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
drawSelectedFilesSplits(canvas, tileBox, selectedGPXFiles, settings);
drawSelectedFilesPoints(canvas, tileBox, selectedGPXFiles);
}
if (textLayer != null && textLayer.isVisible()) {
textLayer.putData(this, cache);
}
}
} }
public void updateLayerStyle() { public void updateLayerStyle() {
cachedHash = -1; cachedHash = -1;
} }
private int updatePaints(int color, boolean routePoints, boolean currentTrack, DrawSettings nightMode, RotatedTileBox tileBox){ private int updatePaints(int color, boolean routePoints, boolean currentTrack, DrawSettings nightMode, RotatedTileBox tileBox) {
RenderingRulesStorage rrs = view.getApplication().getRendererRegistry().getCurrentSelectedRenderer(); RenderingRulesStorage rrs = view.getApplication().getRendererRegistry().getCurrentSelectedRenderer();
final boolean isNight = nightMode != null && nightMode.isNightMode(); final boolean isNight = nightMode != null && nightMode.isNightMode();
int hsh = calculateHash(rrs, routePoints, isNight, tileBox.getMapDensity(), tileBox.getZoom()); int hsh = calculateHash(rrs, routePoints, isNight, tileBox.getMapDensity(), tileBox.getZoom());
if (hsh != cachedHash) { if (hsh != cachedHash) {
cachedHash = hsh; cachedHash = hsh;
cachedColor = view.getResources().getColor(R.color.gpx_track); cachedColor = ContextCompat.getColor(view.getApplication(), R.color.gpx_track);
if (rrs != null) { if (rrs != null) {
RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs); RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs);
req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, isNight); req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, isNight);
CommonPreference<String> p = view.getSettings().getCustomRenderProperty("currentTrackColor"); CommonPreference<String> p = view.getSettings().getCustomRenderProperty("currentTrackColor");
if(p != null && p.isSet()) { if (p != null && p.isSet()) {
RenderingRuleProperty ctColor = rrs.PROPS.get("currentTrackColor"); RenderingRuleProperty ctColor = rrs.PROPS.get("currentTrackColor");
if(ctColor != null) { if (ctColor != null) {
req.setStringFilter(ctColor, p.get()); req.setStringFilter(ctColor, p.get());
} }
} }
CommonPreference<String> p2 = view.getSettings().getCustomRenderProperty("currentTrackWidth"); CommonPreference<String> p2 = view.getSettings().getCustomRenderProperty("currentTrackWidth");
if(p2 != null && p2.isSet()) { if (p2 != null && p2.isSet()) {
RenderingRuleProperty ctWidth = rrs.PROPS.get("currentTrackWidth"); RenderingRuleProperty ctWidth = rrs.PROPS.get("currentTrackWidth");
if(ctWidth != null) { if (ctWidth != null) {
req.setStringFilter(ctWidth, p2.get()); req.setStringFilter(ctWidth, p2.get());
} }
} }
@ -193,35 +244,13 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
paint.setColor(color == 0 ? cachedColor : color); paint.setColor(color == 0 ? cachedColor : color);
return cachedColor; return cachedColor;
} }
private int calculateHash(Object... o) { private int calculateHash(Object... o) {
return Arrays.hashCode(o); return Arrays.hashCode(o);
} }
private void drawSelectedFilesSplits(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles,
@Override DrawSettings settings) {
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if(points != null) {
updatePaints(0, false, false, settings, tileBox);
for (TrkSegment ts : points)
ts.drawRenderers(view.getZoom(), paint, canvas, tileBox);
} else {
List<SelectedGpxFile> selectedGPXFiles = selectedGpxHelper.getSelectedGPXFiles();
cache.clear();
if (!selectedGPXFiles.isEmpty()) {
drawSelectedFilesSegments(canvas, tileBox, selectedGPXFiles, settings);
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
drawSelectedFilesSplits(canvas, tileBox, selectedGPXFiles, settings);
drawSelectedFilesPoints(canvas, tileBox, selectedGPXFiles);
}
if (textLayer != null && textLayer.isVisible()) {
textLayer.putData(this, cache);
}
}
}
private void drawSelectedFilesSplits(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles,
DrawSettings settings) {
if (tileBox.getZoom() >= startZoom) { if (tileBox.getZoom() >= startZoom) {
// request to load // request to load
for (SelectedGpxFile g : selectedGPXFiles) { for (SelectedGpxFile g : selectedGPXFiles) {
@ -239,10 +268,10 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
private void drawSplitItems(Canvas canvas, RotatedTileBox tileBox, List<GpxDisplayItem> items, DrawSettings settings) { private void drawSplitItems(Canvas canvas, RotatedTileBox tileBox, List<GpxDisplayItem> items, DrawSettings settings) {
final QuadRect latLonBounds = tileBox.getLatLonBounds(); final QuadRect latLonBounds = tileBox.getLatLonBounds();
int r = (int) (12 * tileBox.getDensity()); int r = (int) (12 * tileBox.getDensity());
int dr = r * 3 / 2; int dr = r * 3 / 2;
int px = -1; int px = -1;
int py = -1; int py = -1;
for(int k = 0; k < items.size(); k++) { for (int k = 0; k < items.size(); k++) {
GpxDisplayItem i = items.get(k); GpxDisplayItem i = items.get(k);
WptPt o = i.locationEnd; WptPt o = i.locationEnd;
if (o != null && o.lat >= latLonBounds.bottom && o.lat <= latLonBounds.top && o.lon >= latLonBounds.left if (o != null && o.lat >= latLonBounds.bottom && o.lat <= latLonBounds.top && o.lon >= latLonBounds.left
@ -272,8 +301,6 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
} }
private void drawSelectedFilesPoints(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) { private void drawSelectedFilesPoints(Canvas canvas, RotatedTileBox tileBox, List<SelectedGpxFile> selectedGPXFiles) {
int defPointColor = view.getResources().getColor(R.color.gpx_color_point);
int visitedColor = view.getContext().getResources().getColor(R.color.color_ok);
if (tileBox.getZoom() >= startZoom) { if (tileBox.getZoom() >= startZoom) {
float iconSize = FavoriteImageDrawable.getOrCreate(view.getContext(), 0, float iconSize = FavoriteImageDrawable.getOrCreate(view.getContext(), 0,
true).getIntrinsicWidth() * 3 / 2.5f; true).getIntrinsicWidth() * 3 / 2.5f;
@ -286,18 +313,20 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
for (SelectedGpxFile g : selectedGPXFiles) { for (SelectedGpxFile g : selectedGPXFiles) {
List<WptPt> pts = getListStarPoints(g); List<WptPt> pts = getListStarPoints(g);
List<WptPt> fullObjects = new ArrayList<>(); List<WptPt> fullObjects = new ArrayList<>();
int fcolor = g.getColor() == 0 ? defPointColor : g.getColor(); @ColorInt
int fileColor = getFileColor(g);
for (WptPt o : pts) { for (WptPt o : pts) {
if (o.lat >= latLonBounds.bottom && o.lat <= latLonBounds.top if (o.lat >= latLonBounds.bottom && o.lat <= latLonBounds.top
&& o.lon >= latLonBounds.left && o.lon <= latLonBounds.right) { && o.lon >= latLonBounds.left && o.lon <= latLonBounds.right
&& o != contextMenuLayer.getMoveableObject()) {
cache.add(o); cache.add(o);
float x = tileBox.getPixXFromLatLon(o.lat, o.lon); float x = tileBox.getPixXFromLatLon(o.lat, o.lon);
float y = tileBox.getPixYFromLatLon(o.lat, o.lon); float y = tileBox.getPixYFromLatLon(o.lat, o.lon);
if (intersects(boundIntersections, x, y, iconSize, iconSize)) { if (intersects(boundIntersections, x, y, iconSize, iconSize)) {
boolean visit = isPointVisited(o); @ColorInt
int col = visit ? visitedColor : o.getColor(fcolor); int pointColor = getPointColor(o, fileColor);
paintIcon.setColorFilter(new PorterDuffColorFilter(col, PorterDuff.Mode.MULTIPLY)); paintIcon.setColorFilter(new PorterDuffColorFilter(pointColor, PorterDuff.Mode.MULTIPLY));
canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon); canvas.drawBitmap(pointSmall, x - pointSmall.getWidth() / 2, y - pointSmall.getHeight() / 2, paintIcon);
smallObjectsLatLon.add(new LatLon(o.lat, o.lon)); smallObjectsLatLon.add(new LatLon(o.lat, o.lon));
} else { } else {
@ -305,14 +334,12 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
fullObjectsLatLon.add(new LatLon(o.lat, o.lon)); fullObjectsLatLon.add(new LatLon(o.lat, o.lon));
} }
} }
pointFileMap.put(o, g);
} }
for (WptPt o : fullObjects) { for (WptPt o : fullObjects) {
float x = tileBox.getPixXFromLatLon(o.lat, o.lon); float x = tileBox.getPixXFromLatLon(o.lat, o.lon);
float y = tileBox.getPixYFromLatLon(o.lat, o.lon); float y = tileBox.getPixYFromLatLon(o.lat, o.lon);
boolean visit = isPointVisited(o); drawBigPoint(canvas, o, fileColor, x, y);
int pointColor = visit ? visitedColor : o.getColor(fcolor);
FavoriteImageDrawable fid = FavoriteImageDrawable.getOrCreate(view.getContext(), pointColor, true);
fid.drawBitmapInCenter(canvas, x, y);
} }
} }
this.fullObjectsLatLon = fullObjectsLatLon; this.fullObjectsLatLon = fullObjectsLatLon;
@ -320,15 +347,31 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
} }
} }
private int getFileColor(@NonNull SelectedGpxFile g) {
return g.getColor() == 0 ? defPointColor : g.getColor();
}
private void drawBigPoint(Canvas canvas, WptPt o, int fileColor, float x, float y) {
int pointColor = getPointColor(o, fileColor);
FavoriteImageDrawable fid = FavoriteImageDrawable.getOrCreate(view.getContext(), pointColor, true);
fid.drawBitmapInCenter(canvas, x, y);
}
@ColorInt
private int getPointColor(WptPt o, @ColorInt int fileColor) {
boolean visit = isPointVisited(o);
return visit ? visitedColor : o.getColor(fileColor);
}
private void drawSelectedFilesSegments(Canvas canvas, RotatedTileBox tileBox, private void drawSelectedFilesSegments(Canvas canvas, RotatedTileBox tileBox,
List<SelectedGpxFile> selectedGPXFiles, DrawSettings settings) { List<SelectedGpxFile> selectedGPXFiles, DrawSettings settings) {
for (SelectedGpxFile g : selectedGPXFiles) { for (SelectedGpxFile g : selectedGPXFiles) {
List<TrkSegment> segments = g.getPointsToDisplay(); List<TrkSegment> segments = g.getPointsToDisplay();
for (TrkSegment ts : segments) { for (TrkSegment ts : segments) {
if (ts.renders.isEmpty() // only do once (CODE HERE NEEDS TO BE UI INSTEAD) if (ts.renders.isEmpty() // only do once (CODE HERE NEEDS TO BE UI INSTEAD)
&& !ts.points.isEmpty()) { // hmmm. 0-point tracks happen, but.... how? && !ts.points.isEmpty()) { // hmmm. 0-point tracks happen, but.... how?
if (g.isShowCurrentTrack()) { if (g.isShowCurrentTrack()) {
ts.renders.add(new Renderable.CurrentTrack(ts.points)); ts.renders.add(new Renderable.CurrentTrack(ts.points));
@ -343,32 +386,22 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
} }
} }
private boolean isPointVisited(WptPt o) { private boolean isPointVisited(WptPt o) {
boolean visit = false; boolean visit = false;
String visited = o.getExtensionsToRead().get("VISITED_KEY"); String visited = o.getExtensionsToRead().get("VISITED_KEY");
if(visited != null && !visited.equals("0")) { if (visited != null && !visited.equals("0")) {
visit = true; visit = true;
} }
return visit; return visit;
} }
private List<WptPt> getListStarPoints(SelectedGpxFile g) { private List<WptPt> getListStarPoints(SelectedGpxFile g) {
List<WptPt> pts = g.getGpxFile().points;
// don't display points here return g.getGpxFile().points;
// if(pts.isEmpty() & !g.getGpxFile().routes.isEmpty()) {
// pts = g.getGpxFile().routes.get(0).points;
// }
return pts;
} }
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
}
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) { private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
return (Math.abs(objx - ex) <= radius * 2 && Math.abs(objy - ey) <= radius * 2) ; return (Math.abs(objx - ex) <= radius * 2 && Math.abs(objy - ey) <= radius * 2);
// return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ; // return Math.abs(objx - ex) <= radius && (ey - objy) <= radius / 2 && (objy - ey) <= 3 * radius ;
} }
@ -391,8 +424,8 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
@Override @Override
public PointDescription getObjectName(Object o) { public PointDescription getObjectName(Object o) {
if(o instanceof WptPt){ if (o instanceof WptPt) {
return new PointDescription(PointDescription.POINT_TYPE_WPT, ((WptPt)o).name); //$NON-NLS-1$ return new PointDescription(PointDescription.POINT_TYPE_WPT, ((WptPt) o).name); //$NON-NLS-1$
} }
return null; return null;
} }
@ -421,17 +454,18 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
@Override @Override
public LatLon getObjectLocation(Object o) { public LatLon getObjectLocation(Object o) {
if(o instanceof WptPt){ if (o instanceof WptPt) {
return new LatLon(((WptPt)o).lat, ((WptPt)o).lon); return new LatLon(((WptPt) o).lat, ((WptPt) o).lon);
} }
return null; return null;
} }
@Override @Override
public void destroyLayer() { public void destroyLayer() {
} }
@Override @Override
public boolean drawInScreenPixels() { public boolean drawInScreenPixels() {
return false; return false;
@ -444,7 +478,7 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
@Override @Override
public LatLon getTextLocation(WptPt o) { public LatLon getTextLocation(WptPt o) {
return new LatLon(((WptPt)o).lat, ((WptPt)o).lon); return new LatLon(o.lat, o.lon);
} }
@Override @Override
@ -460,8 +494,58 @@ public class GPXLayer extends OsmandMapLayer implements ContextMenuLayer.IContex
public void setGivenGpx(GPXFile gpx) { public void setGivenGpx(GPXFile gpx) {
this.gpx = gpx; this.gpx = gpx;
this.points = (gpx == null ? null : gpx.proccessPoints()); this.points = (gpx == null ? null : gpx.proccessPoints());
} }
@Override
public boolean isObjectMovable(Object o) {
return o instanceof WptPt;
}
@Override
public void applyNewObjectPosition(@NonNull Object o,
@NonNull LatLon position,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
if (o instanceof WptPt) {
WptPt objectInMotion = (WptPt) o;
GPXFile gpxFile = pointFileMap.get(objectInMotion).getGpxFile();
gpxFile.updateWptPt(objectInMotion, position.getLatitude(),
position.getLongitude(), System.currentTimeMillis(), objectInMotion.desc,
objectInMotion.name, objectInMotion.category, objectInMotion.getColor());
new SaveGpxFileAsyncTask(view.getApplication(), callback, objectInMotion).execute(gpxFile);
} else if (callback != null) {
callback.onApplyMovedObject(false, o);
}
}
static class SaveGpxFileAsyncTask extends AsyncTask<GPXFile, Void, String> {
private final OsmandApplication app;
@Nullable
private final ContextMenuLayer.ApplyMovedObjectCallback callback;
@Nullable
private final WptPt point;
SaveGpxFileAsyncTask(OsmandApplication app,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback,
@Nullable WptPt point) {
this.app = app;
this.callback = callback;
this.point = point;
}
@Override
protected String doInBackground(GPXFile... params) {
GPXFile gpxFile = params[0];
return GPXUtilities.writeGpxFile(new File(gpxFile.path), gpxFile, app);
}
@Override
protected void onPostExecute(String errorMessage) {
if (callback != null) {
callback.onApplyMovedObject(errorMessage == null, point);
}
}
}
} }

View file

@ -5,7 +5,10 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PointF; import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.binary.RouteDataObject; import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
@ -13,14 +16,18 @@ import net.osmand.data.PointDescription;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem; import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidSpecificRoadsCallback;
import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.ContextMenuLayer.ApplyMovedObjectCallback;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class ImpassableRoadsLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider { public class ImpassableRoadsLayer extends OsmandMapLayer implements
ContextMenuLayer.IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider {
private static final int startZoom = 10; private static final int startZoom = 10;
private final MapActivity activity; private final MapActivity activity;
@ -31,6 +38,8 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements ContextMenuL
private List<RouteDataObject> missingRoads; private List<RouteDataObject> missingRoads;
private RoutingHelper routingHelper; private RoutingHelper routingHelper;
private ContextMenuLayer contextMenuLayer;
public ImpassableRoadsLayer(MapActivity activity) { public ImpassableRoadsLayer(MapActivity activity) {
this.activity = activity; this.activity = activity;
} }
@ -41,17 +50,30 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements ContextMenuL
roadWorkIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_avoid_road); roadWorkIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_pin_avoid_road);
paint = new Paint(); paint = new Paint();
routingHelper = activity.getRoutingHelper(); routingHelper = activity.getRoutingHelper();
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (contextMenuLayer.getMoveableObject() instanceof RouteDataObject) {
PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
float left = pf.x - roadWorkIcon.getWidth() / 2;
float top = pf.y - roadWorkIcon.getHeight();
canvas.drawBitmap(roadWorkIcon, left, top, paint);
}
} }
@Override @Override
public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) { public void onPrepareBufferImage(Canvas canvas, RotatedTileBox tileBox, DrawSettings settings) {
if (tileBox.getZoom() >= startZoom) { if (tileBox.getZoom() >= startZoom) {
for (long id : getMissingRoadLocations().keySet()) { for (long id : getMissingRoadLocations().keySet()) {
if(contextMenuLayer.getMoveableObject() instanceof RouteDataObject) {
RouteDataObject object = (RouteDataObject) contextMenuLayer.getMoveableObject();
if (object.id == id) {
continue;
}
}
Location location = getMissingRoadLocations().get(id); Location location = getMissingRoadLocations().get(id);
float x = tileBox.getPixXFromLatLon(location.getLatitude(), location.getLongitude()); float x = tileBox.getPixXFromLatLon(location.getLatitude(), location.getLongitude());
float y = tileBox.getPixYFromLatLon(location.getLatitude(), location.getLongitude()); float y = tileBox.getPixYFromLatLon(location.getLatitude(), location.getLongitude());
@ -87,7 +109,7 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements ContextMenuL
} }
public int getRadiusPoi(RotatedTileBox tb) { public int getRadiusPoi(RotatedTileBox tb) {
int r = 0; int r;
if (tb.getZoom() < startZoom) { if (tb.getZoom() < startZoom) {
r = 0; r = 0;
} else { } else {
@ -164,7 +186,7 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements ContextMenuL
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) { public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked) {
if (itemId == R.string.avoid_road) { if (itemId == R.string.avoid_road) {
activity.getMyApplication().getAvoidSpecificRoads().addImpassableRoad( activity.getMyApplication().getAvoidSpecificRoads().addImpassableRoad(
activity, latLon, false); activity, latLon, false, null);
} }
return true; return true;
} }
@ -176,4 +198,32 @@ public class ImpassableRoadsLayer extends OsmandMapLayer implements ContextMenuL
.createItem()); .createItem());
} }
} }
@Override
public boolean isObjectMovable(Object o) {
return o instanceof RouteDataObject;
}
@Override
public void applyNewObjectPosition(@NonNull Object o,
@NonNull LatLon position,
@Nullable final ApplyMovedObjectCallback callback) {
if (o instanceof RouteDataObject) {
final RouteDataObject object = (RouteDataObject) o;
final OsmandApplication application = activity.getMyApplication();
application.getAvoidSpecificRoads().replaceImpassableRoad(activity, object, position, false, new AvoidSpecificRoadsCallback() {
@Override
public void onAddImpassableRoad(boolean success, RouteDataObject newObject) {
if (callback != null) {
callback.onApplyMovedObject(success, newObject);
}
}
@Override
public boolean isCancelled() {
return callback != null && callback.isCancelled();
}
});
}
}
} }

View file

@ -10,8 +10,12 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.MotionEvent; import android.view.MotionEvent;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
@ -24,6 +28,7 @@ import net.osmand.plus.OsmandSettings;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.views.ContextMenuLayer.ApplyMovedObjectCallback;
import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider; import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider;
import net.osmand.plus.views.ContextMenuLayer.IContextMenuProviderSelection; import net.osmand.plus.views.ContextMenuLayer.IContextMenuProviderSelection;
import net.osmand.plus.views.mapwidgets.MapMarkersWidgetsFactory; import net.osmand.plus.views.mapwidgets.MapMarkersWidgetsFactory;
@ -31,7 +36,8 @@ import net.osmand.plus.views.mapwidgets.MapMarkersWidgetsFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvider, IContextMenuProviderSelection { public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvider,
IContextMenuProviderSelection, ContextMenuLayer.IMoveObjectProvider {
protected static final int DIST_TO_SHOW = 80; protected static final int DIST_TO_SHOW = 80;
protected static final long USE_FINGER_LOCATION_DELAY = 1000; protected static final long USE_FINGER_LOCATION_DELAY = 1000;
private static final int MAP_REFRESH_MESSAGE = OsmAndConstants.UI_HANDLER_MAP_VIEW + 6; private static final int MAP_REFRESH_MESSAGE = OsmAndConstants.UI_HANDLER_MAP_VIEW + 6;
@ -71,6 +77,8 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
private GestureDetector longTapDetector; private GestureDetector longTapDetector;
private Handler handler; private Handler handler;
private ContextMenuLayer contextMenuLayer;
public MapMarkersLayer(MapActivity map) { public MapMarkersLayer(MapActivity map) {
this.map = map; this.map = map;
} }
@ -108,10 +116,12 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeJoin(Paint.Join.ROUND);
paint.setColor(map.getResources().getColor(R.color.marker_red)); paint.setColor(ContextCompat.getColor(map, R.color.marker_red));
paint.setAlpha(200); paint.setAlpha(200);
widgetsFactory = new MapMarkersWidgetsFactory(map); widgetsFactory = new MapMarkersWidgetsFactory(map);
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
private Paint createPaintDest(int colorId) { private Paint createPaintDest(int colorId) {
@ -119,7 +129,7 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
paint.setDither(true); paint.setDither(true);
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setFilterBitmap(true); paint.setFilterBitmap(true);
int color = map.getResources().getColor(colorId); int color = ContextCompat.getColor(map, colorId);
paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
return paint; return paint;
} }
@ -216,11 +226,11 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings nightMode) { public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
widgetsFactory.updateInfo(useFingerLocation ? fingerLocation : null, tb.getZoom()); widgetsFactory.updateInfo(useFingerLocation ? fingerLocation : null, tileBox.getZoom());
if (tb.getZoom() < 3 || !map.getMyApplication().getSettings().USE_MAP_MARKERS.get()) { if (tileBox.getZoom() < 3 || !map.getMyApplication().getSettings().USE_MAP_MARKERS.get()) {
return; return;
} }
@ -230,14 +240,14 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
boolean first = true; boolean first = true;
Location myLocation = map.getMapViewTrackingUtilities().getMyLocation(); Location myLocation = map.getMapViewTrackingUtilities().getMyLocation();
if (markersHelper.isStartFromMyLocation() && myLocation != null) { if (markersHelper.isStartFromMyLocation() && myLocation != null) {
int locationX = tb.getPixXFromLonNoRot(myLocation.getLongitude()); int locationX = tileBox.getPixXFromLonNoRot(myLocation.getLongitude());
int locationY = tb.getPixYFromLatNoRot(myLocation.getLatitude()); int locationY = tileBox.getPixYFromLatNoRot(myLocation.getLatitude());
path.moveTo(locationX, locationY); path.moveTo(locationX, locationY);
first = false; first = false;
} }
for (LatLon point : route) { for (LatLon point : route) {
int locationX = tb.getPixXFromLonNoRot(point.getLongitude()); int locationX = tileBox.getPixXFromLonNoRot(point.getLongitude());
int locationY = tb.getPixYFromLatNoRot(point.getLatitude()); int locationY = tileBox.getPixYFromLatNoRot(point.getLatitude());
if (first) { if (first) {
path.moveTo(locationX, locationY); path.moveTo(locationX, locationY);
first = false; first = false;
@ -249,17 +259,17 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
} }
List<MapMarker> activeMapMarkers = markersHelper.getActiveMapMarkers(); List<MapMarker> activeMapMarkers = markersHelper.getActiveMapMarkers();
for (int i = 0; i < activeMapMarkers.size(); i++) { for (MapMarker marker : activeMapMarkers) {
MapMarker marker = activeMapMarkers.get(i); if (isLocationVisible(tileBox, marker) && !overlappedByWaypoint(marker)
if (isLocationVisible(tb, marker) && !overlappedByWaypoint(marker)) { && !isInMotion(marker)) {
Bitmap bmp = getMapMarkerBitmap(marker.colorIndex); Bitmap bmp = getMapMarkerBitmap(marker.colorIndex);
int marginX = bmp.getWidth() / 6; int marginX = bmp.getWidth() / 6;
int marginY = bmp.getHeight(); int marginY = bmp.getHeight();
int locationX = tb.getPixXFromLonNoRot(marker.getLongitude()); int locationX = tileBox.getPixXFromLonNoRot(marker.getLongitude());
int locationY = tb.getPixYFromLatNoRot(marker.getLatitude()); int locationY = tileBox.getPixYFromLatNoRot(marker.getLatitude());
canvas.rotate(-tb.getRotate(), locationX, locationY); canvas.rotate(-tileBox.getRotate(), locationX, locationY);
canvas.drawBitmap(bmp, locationX - marginX, locationY - marginY, bitmapPaint); canvas.drawBitmap(bmp, locationX - marginX, locationY - marginY, bitmapPaint);
canvas.rotate(tb.getRotate(), locationX, locationY); canvas.rotate(tileBox.getRotate(), locationX, locationY);
} }
} }
@ -269,21 +279,21 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
if (show) { if (show) {
LatLon loc = fingerLocation; LatLon loc = fingerLocation;
if (!useFingerLocation) { if (!useFingerLocation) {
loc = tb.getCenterLatLon(); loc = tileBox.getCenterLatLon();
} }
if (loc != null) { if (loc != null) {
List<MapMarker> sortedMapMarkers = markersHelper.getSortedMapMarkers(); List<MapMarker> sortedMapMarkers = markersHelper.getSortedMapMarkers();
int i = 0; int i = 0;
for (MapMarker marker : sortedMapMarkers) { for (MapMarker marker : sortedMapMarkers) {
if (!isLocationVisible(tb, marker)) { if (!isLocationVisible(tileBox, marker) && !isInMotion(marker)) {
canvas.save(); canvas.save();
net.osmand.Location.distanceBetween(loc.getLatitude(), loc.getLongitude(), net.osmand.Location.distanceBetween(loc.getLatitude(), loc.getLongitude(),
marker.getLatitude(), marker.getLongitude(), calculations); marker.getLatitude(), marker.getLongitude(), calculations);
float bearing = calculations[1] - 90; float bearing = calculations[1] - 90;
float radiusBearing = DIST_TO_SHOW * tb.getDensity(); float radiusBearing = DIST_TO_SHOW * tileBox.getDensity();
final QuadPoint cp = tb.getCenterPixelPoint(); final QuadPoint cp = tileBox.getCenterPixelPoint();
canvas.rotate(bearing, cp.x, cp.y); canvas.rotate(bearing, cp.x, cp.y);
canvas.translate(-24 * tb.getDensity() + radiusBearing, -22 * tb.getDensity()); canvas.translate(-24 * tileBox.getDensity() + radiusBearing, -22 * tileBox.getDensity());
canvas.drawBitmap(arrowToDestination, cp.x, cp.y, getMarkerDestPaint(marker.colorIndex)); canvas.drawBitmap(arrowToDestination, cp.x, cp.y, getMarkerDestPaint(marker.colorIndex));
canvas.restore(); canvas.restore();
} }
@ -294,9 +304,26 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
} }
} }
} }
if (contextMenuLayer.getMoveableObject() instanceof MapMarker) {
MapMarker objectInMotion = (MapMarker) contextMenuLayer.getMoveableObject();
Bitmap bitmap = getMapMarkerBitmap(objectInMotion.colorIndex);
PointF pf = contextMenuLayer.getMoveableCenterPoint(tileBox);
int marginX = bitmap.getWidth() / 6;
int marginY = bitmap.getHeight();
float locationX = pf.x;
float locationY = pf.y;
canvas.rotate(-tileBox.getRotate(), locationX, locationY);
canvas.drawBitmap(bitmap, locationX - marginX, locationY - marginY, bitmapPaint);
}
}
private boolean isInMotion(@NonNull MapMarker marker) {
return marker.equals(contextMenuLayer.getMoveableObject());
} }
public boolean isLocationVisible(RotatedTileBox tb, MapMarker marker) { public boolean isLocationVisible(RotatedTileBox tb, MapMarker marker) {
//noinspection SimplifiableIfStatement
if (marker == null || tb == null) { if (marker == null || tb == null) {
return false; return false;
} }
@ -482,4 +509,30 @@ public class MapMarkersLayer extends OsmandMapLayer implements IContextMenuProvi
public void clearSelectedObject() { public void clearSelectedObject() {
} }
@Override
public boolean isObjectMovable(Object o) {
return o instanceof MapMarker;
}
@Override
public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position,
@Nullable ApplyMovedObjectCallback callback) {
boolean result = false;
MapMarker newObject = null;
if (o instanceof MapMarker) {
MapMarkersHelper markersHelper = map.getMyApplication().getMapMarkersHelper();
MapMarker marker = (MapMarker) o;
marker.getOriginalPointDescription().setName(PointDescription.getSearchAddressStr(map));
markersHelper.moveMapMarker(marker, position);
int index = markersHelper.getActiveMapMarkers().indexOf(marker);
if (index != -1) {
newObject = markersHelper.getActiveMapMarkers().get(index);
}
result = true;
}
if (callback != null) {
callback.onApplyMovedObject(result, newObject == null ? o : newObject);
}
}
} }

View file

@ -1,25 +1,26 @@
package net.osmand.plus.views; package net.osmand.plus.views;
import gnu.trove.set.hash.TIntHashSet;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import net.osmand.data.LatLon;
import net.osmand.data.RotatedTileBox;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Align; import android.graphics.Paint.Align;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import net.osmand.data.LatLon;
import net.osmand.data.RotatedTileBox;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import gnu.trove.set.hash.TIntHashSet;
public class MapTextLayer extends OsmandMapLayer { public class MapTextLayer extends OsmandMapLayer {
private Map<OsmandMapLayer, private Map<OsmandMapLayer,
List<?>> textObjects = new LinkedHashMap<OsmandMapLayer, List<?>>(); Collection<?>> textObjects = new LinkedHashMap<>();
public static final int TEXT_WRAP = 15; public static final int TEXT_WRAP = 15;
public static final int TEXT_LINES = 3; public static final int TEXT_LINES = 3;
private Paint paintTextIcon; private Paint paintTextIcon;
@ -37,7 +38,7 @@ public class MapTextLayer extends OsmandMapLayer {
String getText(T o); String getText(T o);
} }
public void putData(OsmandMapLayer ml, List<?> objects) { public void putData(OsmandMapLayer ml, Collection<?> objects) {
if(objects == null || objects.isEmpty()) { if(objects == null || objects.isEmpty()) {
textObjects.remove(ml); textObjects.remove(ml);
} else { } else {
@ -173,7 +174,7 @@ public class MapTextLayer extends OsmandMapLayer {
paintTextIcon.setTextSize(13 * v.getDensity()); paintTextIcon.setTextSize(13 * v.getDensity());
paintTextIcon.setTextAlign(Align.CENTER); paintTextIcon.setTextAlign(Align.CENTER);
paintTextIcon.setAntiAlias(true); paintTextIcon.setAntiAlias(true);
Map<OsmandMapLayer, List<?>> textObjectsLoc = new TreeMap<OsmandMapLayer, List<?>>(new Comparator<OsmandMapLayer>() { Map<OsmandMapLayer, Collection<?>> textObjectsLoc = new TreeMap<OsmandMapLayer, Collection<?>>(new Comparator<OsmandMapLayer>() {
@Override @Override
public int compare(OsmandMapLayer lhs, OsmandMapLayer rhs) { public int compare(OsmandMapLayer lhs, OsmandMapLayer rhs) {

View file

@ -1,10 +1,12 @@
package net.osmand.plus.views; package net.osmand.plus.views;
import android.content.Context; import android.content.Context;
import android.graphics.PointF;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import net.osmand.data.RotatedTileBox; import net.osmand.data.RotatedTileBox;
import net.osmand.plus.IconsCache; import net.osmand.plus.IconsCache;
import net.osmand.plus.R; import net.osmand.plus.R;
@ -15,6 +17,7 @@ public class MoveMarkerBottomSheetHelper {
private final TextView mDescription; private final TextView mDescription;
private final Context mContext; private final Context mContext;
private final ContextMenuLayer mContextMenuLayer; private final ContextMenuLayer mContextMenuLayer;
private boolean applyingPositionMode;
public MoveMarkerBottomSheetHelper(MapActivity activity, ContextMenuLayer contextMenuLayer) { public MoveMarkerBottomSheetHelper(MapActivity activity, ContextMenuLayer contextMenuLayer) {
mContextMenuLayer = contextMenuLayer; mContextMenuLayer = contextMenuLayer;
@ -28,7 +31,6 @@ public class MoveMarkerBottomSheetHelper {
mView.findViewById(R.id.apply_button).setOnClickListener(new View.OnClickListener() { mView.findViewById(R.id.apply_button).setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
hide();
mContextMenuLayer.applyNewMarkerPosition(); mContextMenuLayer.applyNewMarkerPosition();
} }
}); });
@ -42,8 +44,9 @@ public class MoveMarkerBottomSheetHelper {
} }
public void onDraw(RotatedTileBox rt) { public void onDraw(RotatedTileBox rt) {
double lat = rt.getLatFromPixel(rt.getPixWidth() / 2, rt.getPixHeight() / 2); PointF point = mContextMenuLayer.getMoveableCenterPoint(rt);
double lon = rt.getLonFromPixel(rt.getPixWidth() / 2, rt.getPixHeight() / 2); double lat = rt.getLatFromPixel(point.x, point.y);
double lon = rt.getLonFromPixel(point.x, point.y);
mDescription.setText(mContext.getString(R.string.lat_lon_pattern, lat, lon)); mDescription.setText(mContext.getString(R.string.lat_lon_pattern, lat, lon));
} }
@ -52,11 +55,27 @@ public class MoveMarkerBottomSheetHelper {
} }
public void show(Drawable drawable) { public void show(Drawable drawable) {
exitApplyPositionMode();
mView.setVisibility(View.VISIBLE); mView.setVisibility(View.VISIBLE);
((ImageView) mView.findViewById(R.id.icon)).setImageDrawable(drawable); ((ImageView) mView.findViewById(R.id.icon)).setImageDrawable(drawable);
} }
public void hide() { public void hide() {
exitApplyPositionMode();
mView.setVisibility(View.GONE); mView.setVisibility(View.GONE);
} }
public void enterApplyPositionMode() {
if (!applyingPositionMode) {
applyingPositionMode = true;
mView.findViewById(R.id.apply_button).setEnabled(false);
}
}
public void exitApplyPositionMode() {
if (applyingPositionMode) {
applyingPositionMode = false;
mView.findViewById(R.id.apply_button).setEnabled(true);
}
}
} }

View file

@ -8,6 +8,10 @@ import android.graphics.Paint;
import android.graphics.Paint.Align; import android.graphics.Paint.Align;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.PointF; import android.graphics.PointF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import net.osmand.data.LatLon; import net.osmand.data.LatLon;
import net.osmand.data.PointDescription; import net.osmand.data.PointDescription;
import net.osmand.data.QuadPoint; import net.osmand.data.QuadPoint;
@ -21,61 +25,60 @@ import net.osmand.plus.views.ContextMenuLayer.IContextMenuProvider;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class PointNavigationLayer extends OsmandMapLayer implements IContextMenuProvider { public class PointNavigationLayer extends OsmandMapLayer implements
IContextMenuProvider, ContextMenuLayer.IMoveObjectProvider {
protected final static int DIST_TO_SHOW = 80; protected final static int DIST_TO_SHOW = 80;
private Paint point; private Paint mPoint;
private Paint bitmapPaint; private Paint mBitmapPaint;
private OsmandMapTileView view;
private float[] calculations = new float[2];
private Bitmap startPoint; private OsmandMapTileView mView;
private Bitmap targetPoint; private float[] mCalculations = new float[2];
private Bitmap intermediatePoint;
private Bitmap arrowToDestination;
private Paint textPaint; private Bitmap mStartPoint;
private Bitmap mTargetPoint;
private Bitmap mIntermediatePoint;
private Bitmap mArrowToDestination;
private Paint mTextPaint;
private final MapActivity map; private final MapActivity map;
private ContextMenuLayer contextMenuLayer;
public PointNavigationLayer(MapActivity map) { public PointNavigationLayer(MapActivity map) {
this.map = map; this.map = map;
} }
private void initUI() { private void initUI() {
mPoint = new Paint();
point = new Paint(); mPoint.setColor(ContextCompat.getColor(map, R.color.nav_point));
point.setColor(view.getResources().getColor(R.color.nav_point)); mPoint.setAntiAlias(true);
point.setAntiAlias(true); mPoint.setStyle(Style.FILL);
point.setStyle(Style.FILL);
bitmapPaint = new Paint(); mBitmapPaint = new Paint();
bitmapPaint.setDither(true); mBitmapPaint.setDither(true);
bitmapPaint.setAntiAlias(true); mBitmapPaint.setAntiAlias(true);
bitmapPaint.setFilterBitmap(true); mBitmapPaint.setFilterBitmap(true);
textPaint = new Paint(); mTextPaint = new Paint();
float sp = Resources.getSystem().getDisplayMetrics().scaledDensity; float sp = Resources.getSystem().getDisplayMetrics().scaledDensity;
textPaint.setTextSize(sp * 18); mTextPaint.setTextSize(sp * 18);
textPaint.setTextAlign(Align.CENTER); mTextPaint.setTextAlign(Align.CENTER);
textPaint.setAntiAlias(true); mTextPaint.setAntiAlias(true);
startPoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_start_point); mStartPoint = BitmapFactory.decodeResource(mView.getResources(), R.drawable.map_start_point);
targetPoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_target_point); mTargetPoint = BitmapFactory.decodeResource(mView.getResources(), R.drawable.map_target_point);
intermediatePoint = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_intermediate_point); mIntermediatePoint = BitmapFactory.decodeResource(mView.getResources(), R.drawable.map_intermediate_point);
arrowToDestination = BitmapFactory.decodeResource(view.getResources(), R.drawable.map_arrow_to_destination); mArrowToDestination = BitmapFactory.decodeResource(mView.getResources(), R.drawable.map_arrow_to_destination);
} }
@Override @Override
public void initLayer(OsmandMapTileView view) { public void initLayer(OsmandMapTileView view) {
this.view = view; this.mView = view;
initUI(); initUI();
contextMenuLayer = view.getLayerByClass(ContextMenuLayer.class);
} }
@Override @Override
public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings nightMode) { public void onDraw(Canvas canvas, RotatedTileBox tb, DrawSettings nightMode) {
if (tb.getZoom() < 3) { if (tb.getZoom() < 3) {
@ -86,75 +89,96 @@ public class PointNavigationLayer extends OsmandMapLayer implements IContextMenu
TargetPoint pointToStart = targetPoints.getPointToStart(); TargetPoint pointToStart = targetPoints.getPointToStart();
if (pointToStart != null) { if (pointToStart != null) {
if (isLocationVisible(tb, pointToStart)) { if (isLocationVisible(tb, pointToStart)) {
int marginX = startPoint.getWidth() / 6; int marginX = mStartPoint.getWidth() / 6;
int marginY = startPoint.getHeight(); int marginY = mStartPoint.getHeight();
int locationX = tb.getPixXFromLonNoRot(pointToStart.getLongitude()); float locationX = getPointX(tb, pointToStart);
int locationY = tb.getPixYFromLatNoRot(pointToStart.getLatitude()); float locationY = getPointY(tb, pointToStart);
canvas.rotate(-tb.getRotate(), locationX, locationY); canvas.rotate(-tb.getRotate(), locationX, locationY);
canvas.drawBitmap(startPoint, locationX - marginX, locationY - marginY, bitmapPaint); canvas.drawBitmap(mStartPoint, locationX - marginX, locationY - marginY, mBitmapPaint);
} }
} }
int index = 0; int index = 0;
for (TargetPoint ip : targetPoints.getIntermediatePoints()) { for (TargetPoint ip : targetPoints.getIntermediatePoints()) {
index ++; index++;
if (isLocationVisible(tb, ip)) { if (isLocationVisible(tb, ip)) {
int marginX = intermediatePoint.getWidth() / 6; int marginX = mIntermediatePoint.getWidth() / 6;
int marginY = intermediatePoint.getHeight(); int marginY = mIntermediatePoint.getHeight();
int locationX = tb.getPixXFromLonNoRot(ip.getLongitude()); float locationX = getPointX(tb, ip);
int locationY = tb.getPixYFromLatNoRot(ip.getLatitude()); float locationY = getPointY(tb, ip);
canvas.rotate(-tb.getRotate(), locationX, locationY); canvas.rotate(-tb.getRotate(), locationX, locationY);
canvas.drawBitmap(intermediatePoint, locationX - marginX, locationY - marginY, bitmapPaint); canvas.drawBitmap(mIntermediatePoint, locationX - marginX, locationY - marginY, mBitmapPaint);
marginX = intermediatePoint.getWidth() / 3; marginX = mIntermediatePoint.getWidth() / 3;
canvas.drawText(index + "", locationX + marginX, locationY - 3 * marginY / 5, textPaint); canvas.drawText(index + "", locationX + marginX, locationY - 3 * marginY / 5, mTextPaint);
canvas.rotate(tb.getRotate(), locationX, locationY); canvas.rotate(tb.getRotate(), locationX, locationY);
} }
} }
TargetPoint pointToNavigate = targetPoints.getPointToNavigate(); TargetPoint pointToNavigate = targetPoints.getPointToNavigate();
if (isLocationVisible(tb, pointToNavigate)) { if (isLocationVisible(tb, pointToNavigate)) {
int marginX = targetPoint.getWidth() / 6; int marginX = mTargetPoint.getWidth() / 6;
int marginY = targetPoint.getHeight(); int marginY = mTargetPoint.getHeight();
int locationX = tb.getPixXFromLonNoRot(pointToNavigate.getLongitude()); float locationX = getPointX(tb, pointToNavigate);
int locationY = tb.getPixYFromLatNoRot(pointToNavigate.getLatitude()); float locationY = getPointY(tb, pointToNavigate);
canvas.rotate(-tb.getRotate(), locationX, locationY); canvas.rotate(-tb.getRotate(), locationX, locationY);
canvas.drawBitmap(targetPoint, locationX - marginX, locationY - marginY, bitmapPaint); canvas.drawBitmap(mTargetPoint, locationX - marginX, locationY - marginY, mBitmapPaint);
} }
Iterator<TargetPoint> it = targetPoints.getIntermediatePoints().iterator(); Iterator<TargetPoint> it = targetPoints.getIntermediatePoints().iterator();
if(it.hasNext()) { if (it.hasNext()) {
pointToNavigate = it.next(); pointToNavigate = it.next();
} }
if (pointToNavigate != null && !isLocationVisible(tb, pointToNavigate)) { if (pointToNavigate != null && !isLocationVisible(tb, pointToNavigate)) {
boolean show = !view.getApplication().getRoutingHelper().isRouteCalculated(); boolean show = !mView.getApplication().getRoutingHelper().isRouteCalculated();
if(view.getSettings().SHOW_DESTINATION_ARROW.isSet()) { if (mView.getSettings().SHOW_DESTINATION_ARROW.isSet()) {
show = view.getSettings().SHOW_DESTINATION_ARROW.get(); show = mView.getSettings().SHOW_DESTINATION_ARROW.get();
} }
if (show) { if (show) {
net.osmand.Location.distanceBetween(view.getLatitude(), view.getLongitude(), net.osmand.Location.distanceBetween(mView.getLatitude(), mView.getLongitude(),
pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), calculations); pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), mCalculations);
float bearing = calculations[1] - 90; float bearing = mCalculations[1] - 90;
float radiusBearing = DIST_TO_SHOW * tb.getDensity(); float radiusBearing = DIST_TO_SHOW * tb.getDensity();
final QuadPoint cp = tb.getCenterPixelPoint(); final QuadPoint cp = tb.getCenterPixelPoint();
canvas.rotate(bearing, cp.x, cp.y); canvas.rotate(bearing, cp.x, cp.y);
canvas.translate(-24 * tb.getDensity() + radiusBearing, -22 * tb.getDensity()); canvas.translate(-24 * tb.getDensity() + radiusBearing, -22 * tb.getDensity());
canvas.drawBitmap(arrowToDestination, cp.x, cp.y, bitmapPaint); canvas.drawBitmap(mArrowToDestination, cp.x, cp.y, mBitmapPaint);
} }
} }
} }
public boolean isLocationVisible(RotatedTileBox tb, TargetPoint p){ private float getPointX(RotatedTileBox tileBox, TargetPoint point) {
if(p == null || tb == null){ if (contextMenuLayer.getMoveableObject() != null
&& point == contextMenuLayer.getMoveableObject()) {
return contextMenuLayer.getMoveableCenterPoint(tileBox).x;
} else {
return tileBox.getPixXFromLonNoRot(point.getLongitude());
}
}
private float getPointY(RotatedTileBox tileBox, TargetPoint point) {
if (contextMenuLayer.getMoveableObject() != null
&& point == contextMenuLayer.getMoveableObject()) {
return contextMenuLayer.getMoveableCenterPoint(tileBox).y;
} else {
return tileBox.getPixYFromLatNoRot(point.getLatitude());
}
}
public boolean isLocationVisible(RotatedTileBox tb, TargetPoint p) {
if (contextMenuLayer.getMoveableObject() != null
&& p == contextMenuLayer.getMoveableObject()) {
return true;
} else if (p == null || tb == null) {
return false; return false;
} }
return tb.containsLatLon(p.getLatitude(), p.getLongitude()); return tb.containsLatLon(p.getLatitude(), p.getLongitude());
} }
@Override @Override
public void destroyLayer() { public void destroyLayer() {
} }
@Override @Override
@ -198,19 +222,19 @@ public class PointNavigationLayer extends OsmandMapLayer implements IContextMenu
} }
} }
} }
private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) { private boolean calculateBelongs(int ex, int ey, int objx, int objy, int radius) {
return Math.abs(objx - ex) <= radius && (ey - objy) <= radius && (objy - ey) <= 2.5 * radius ; return Math.abs(objx - ex) <= radius && (ey - objy) <= radius && (objy - ey) <= 2.5 * radius;
} }
public int getRadiusPoi(RotatedTileBox tb){ public int getRadiusPoi(RotatedTileBox tb) {
int r = 0; int r;
final double zoom = tb.getZoom(); final double zoom = tb.getZoom();
if(zoom <= 15){ if (zoom <= 15) {
r = 10; r = 10;
} else if(zoom <= 16){ } else if (zoom <= 16) {
r = 14; r = 14;
} else if(zoom <= 17){ } else if (zoom <= 17) {
r = 16; r = 16;
} else { } else {
r = 18; r = 18;
@ -226,14 +250,32 @@ public class PointNavigationLayer extends OsmandMapLayer implements IContextMenu
return null; return null;
} }
@Override @Override
public PointDescription getObjectName(Object o) { public PointDescription getObjectName(Object o) {
if (o instanceof TargetPoint) { if (o instanceof TargetPoint) {
return ((TargetPoint) o).getPointDescription(view.getContext()); return ((TargetPoint) o).getPointDescription(mView.getContext());
} }
return null; return null;
} }
@Override
public boolean isObjectMovable(Object o) {
TargetPointsHelper targetPoints = map.getMyApplication().getTargetPointsHelper();
return o == targetPoints.getPointToNavigate();
}
@Override
public void applyNewObjectPosition(@NonNull Object o, @NonNull LatLon position,
@Nullable ContextMenuLayer.ApplyMovedObjectCallback callback) {
boolean result = false;
if (o instanceof TargetPoint) {
TargetPoint point = (TargetPoint) o;
TargetPointsHelper tph = map.getMyApplication().getTargetPointsHelper();
tph.navigateToPoint(position, true, -1, point.getPointDescription(map));
result = true;
}
if (callback != null) {
callback.onApplyMovedObject(result, o);
}
}
} }