Merge pull request #11105 from osmandapp/track_dependent_coloring
Track coloring based on speed / altitude / slope
This commit is contained in:
commit
5f9047cc6d
23 changed files with 687 additions and 199 deletions
|
@ -6,6 +6,7 @@ import net.osmand.binary.StringBundle;
|
|||
import net.osmand.binary.StringBundleWriter;
|
||||
import net.osmand.binary.StringBundleXmlWriter;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.router.RouteColorize.ColorizationType;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -227,6 +228,9 @@ public class GPXUtilities {
|
|||
public double hdop = Double.NaN;
|
||||
public float heading = Float.NaN;
|
||||
public boolean deleted = false;
|
||||
public int speedColor = 0;
|
||||
public int altitudeColor = 0;
|
||||
public int slopeColor = 0;
|
||||
public int colourARGB = 0; // point colour (used for altitude/speed colouring)
|
||||
public double distance = 0.0; // cumulative distance, if in a track
|
||||
|
||||
|
@ -249,6 +253,9 @@ public class GPXUtilities {
|
|||
this.hdop = wptPt.hdop;
|
||||
this.heading = wptPt.heading;
|
||||
this.deleted = wptPt.deleted;
|
||||
this.speedColor = wptPt.speedColor;
|
||||
this.altitudeColor = wptPt.altitudeColor;
|
||||
this.slopeColor = wptPt.slopeColor;
|
||||
this.colourARGB = wptPt.colourARGB;
|
||||
this.distance = wptPt.distance;
|
||||
}
|
||||
|
@ -311,6 +318,16 @@ public class GPXUtilities {
|
|||
getExtensionsToWrite().put(ICON_NAME_EXTENSION, iconName);
|
||||
}
|
||||
|
||||
public int getColor(ColorizationType type) {
|
||||
if (type == ColorizationType.SPEED) {
|
||||
return speedColor;
|
||||
} else if (type == ColorizationType.ELEVATION) {
|
||||
return altitudeColor;
|
||||
} else {
|
||||
return slopeColor;
|
||||
}
|
||||
}
|
||||
|
||||
public String getBackgroundType() {
|
||||
return getExtensionsToRead().get(BACKGROUND_TYPE_EXTENSION);
|
||||
}
|
||||
|
@ -1662,16 +1679,16 @@ public class GPXUtilities {
|
|||
return new QuadRect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public int getGradientScaleColor(String gradientScaleType, int defColor) {
|
||||
public int[] getGradientScaleColor(String gradientScaleType) {
|
||||
String clrValue = null;
|
||||
if (extensions != null) {
|
||||
clrValue = extensions.get(gradientScaleType);
|
||||
}
|
||||
return parseColor(clrValue, defColor);
|
||||
return Algorithms.stringToGradientPalette(clrValue);
|
||||
}
|
||||
|
||||
public void setGradientScaleColor(String gradientScaleType, int gradientScaleColor) {
|
||||
getExtensionsToWrite().put(gradientScaleType, Algorithms.colorToString(gradientScaleColor));
|
||||
public void setGradientScaleColor(String gradientScaleType, int[] gradientScalePalette) {
|
||||
getExtensionsToWrite().put(gradientScaleType, Algorithms.gradientPaletteToString(gradientScalePalette));
|
||||
}
|
||||
|
||||
public String getGradientScaleType() {
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.osmand.PlatformUtil;
|
|||
import net.osmand.osm.edit.Node;
|
||||
import net.osmand.osm.edit.OsmMapUtils;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -24,11 +25,12 @@ public class RouteColorize {
|
|||
|
||||
public static final int DARK_GREY = rgbaToDecimal(92, 92, 92, 255);
|
||||
public static final int LIGHT_GREY = rgbaToDecimal(200, 200, 200, 255);
|
||||
public static final int RED = rgbaToDecimal(255,1,1,255);
|
||||
public static final int GREEN = rgbaToDecimal(46,185,0,191);
|
||||
public static final int YELLOW = rgbaToDecimal(255,222,2,227);
|
||||
public static final int GREEN = rgbaToDecimal(90, 220, 95, 255);
|
||||
public static final int YELLOW = rgbaToDecimal(212, 239, 50, 255);
|
||||
public static final int RED = rgbaToDecimal(243, 55, 77, 255);
|
||||
public static final int[] colors = new int[] {GREEN, YELLOW, RED};
|
||||
|
||||
public enum ValueType {
|
||||
public enum ColorizationType {
|
||||
ELEVATION,
|
||||
SPEED,
|
||||
SLOPE,
|
||||
|
@ -42,7 +44,7 @@ public class RouteColorize {
|
|||
private final int BLUE_COLOR_INDEX = 3;//RGB
|
||||
private final int ALPHA_COLOR_INDEX = 4;//RGBA
|
||||
|
||||
private ValueType valueType;
|
||||
private ColorizationType colorizationType;
|
||||
|
||||
public static int SLOPE_RANGE = 150;//150 meters
|
||||
private static final double MIN_DIFFERENCE_SLOPE = 0.05d;//5%
|
||||
|
@ -73,7 +75,7 @@ public class RouteColorize {
|
|||
/**
|
||||
* @param type ELEVATION, SPEED, SLOPE
|
||||
*/
|
||||
public RouteColorize(int zoom, GPXUtilities.GPXFile gpxFile, ValueType type) {
|
||||
public RouteColorize(int zoom, GPXUtilities.GPXFile gpxFile, ColorizationType type) {
|
||||
|
||||
if (!gpxFile.hasTrkPt()) {
|
||||
LOG.warn("GPX file is not consist of track points");
|
||||
|
@ -88,7 +90,7 @@ public class RouteColorize {
|
|||
for (GPXUtilities.WptPt p : ts.points) {
|
||||
latList.add(p.lat);
|
||||
lonList.add(p.lon);
|
||||
if (type == ValueType.SPEED) {
|
||||
if (type == ColorizationType.SPEED) {
|
||||
valList.add(p.speed);
|
||||
} else {
|
||||
valList.add(p.ele);
|
||||
|
@ -101,14 +103,14 @@ public class RouteColorize {
|
|||
latitudes = listToArray(latList);
|
||||
longitudes = listToArray(lonList);
|
||||
|
||||
if (type == ValueType.SLOPE) {
|
||||
if (type == ColorizationType.SLOPE) {
|
||||
values = calculateSlopesByElevations(latitudes, longitudes, listToArray(valList), SLOPE_RANGE);
|
||||
} else {
|
||||
values = listToArray(valList);
|
||||
}
|
||||
|
||||
calculateMinMaxValue();
|
||||
valueType = type;
|
||||
colorizationType = type;
|
||||
checkPalette();
|
||||
sortPalette();
|
||||
}
|
||||
|
@ -201,6 +203,17 @@ public class RouteColorize {
|
|||
sortPalette();
|
||||
}
|
||||
|
||||
public void setPalette(int[] gradientPalette) {
|
||||
if (gradientPalette == null || gradientPalette.length != 3) {
|
||||
return;
|
||||
}
|
||||
setPalette(new double[][] {
|
||||
{minValue, gradientPalette[0]},
|
||||
{colorizationType == ColorizationType.SLOPE ? 0 : (minValue + maxValue) / 2, gradientPalette[1]},
|
||||
{maxValue, gradientPalette[2]}
|
||||
});
|
||||
}
|
||||
|
||||
private int getDefaultColor() {
|
||||
return rgbaToDecimal(0, 0, 0, 0);
|
||||
}
|
||||
|
@ -282,7 +295,7 @@ public class RouteColorize {
|
|||
|
||||
double[][] defaultPalette = {
|
||||
{minValue, GREEN},
|
||||
{valueType == ValueType.SLOPE ? 0 : (minValue + maxValue) / 2, YELLOW},
|
||||
{colorizationType == ColorizationType.SLOPE ? 0 : (minValue + maxValue) / 2, YELLOW},
|
||||
{maxValue, RED}
|
||||
};
|
||||
palette = defaultPalette;
|
||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.util;
|
|||
|
||||
import net.osmand.IProgress;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.router.RouteColorize;
|
||||
import net.osmand.data.LatLon;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -1061,4 +1062,30 @@ public class Algorithms {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int[] stringToGradientPalette(String str) {
|
||||
if (Algorithms.isBlank(str)) {
|
||||
return RouteColorize.colors;
|
||||
}
|
||||
String[] arr = str.split(" ");
|
||||
if (arr.length != 3) {
|
||||
return RouteColorize.colors;
|
||||
}
|
||||
int[] colors = new int[3];
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
colors[i] = Algorithms.parseColor(arr[i]);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
return RouteColorize.colors;
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
public static String gradientPaletteToString(int[] colors) {
|
||||
int[] src = (colors != null && colors.length == 3) ? colors : RouteColorize.colors;
|
||||
return Algorithms.colorToString(src[0]) + " " +
|
||||
Algorithms.colorToString(src[1]) + " " +
|
||||
Algorithms.colorToString(src[2]);
|
||||
}
|
||||
}
|
13
OsmAnd/res/drawable/bg_track_gradient.xml
Normal file
13
OsmAnd/res/drawable/bg_track_gradient.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape>
|
||||
<gradient
|
||||
android:angle="0"
|
||||
android:startColor="@color/track_gradient_start"
|
||||
android:centerColor="@color/track_gradient_center"
|
||||
android:endColor="@color/track_gradient_end"
|
||||
android:type="linear" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
46
OsmAnd/res/layout/gradient_card.xml
Normal file
46
OsmAnd/res/layout/gradient_card.xml
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingEnd="@dimen/content_padding">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/pages_item_size"
|
||||
android:layout_marginBottom="@dimen/content_padding_half"
|
||||
android:background="@drawable/bg_track_gradient" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/min_value"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="100 m"/>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/max_value"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="end"
|
||||
android:textColor="?attr/main_font_color_basic"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="100 m"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -20,9 +20,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="@dimen/context_menu_padding_margin_tiny"
|
||||
android:paddingBottom="@dimen/content_padding"
|
||||
android:visibility="gone">
|
||||
android:paddingTop="@dimen/context_menu_buttons_padding_bottom">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
|
@ -41,15 +39,4 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.FlowLayout
|
||||
android:id="@+id/select_color"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/context_menu_padding_margin_tiny"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding_half" />
|
||||
|
||||
</LinearLayout>
|
|
@ -45,7 +45,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/content_padding">
|
||||
android:paddingBottom="@dimen/favorites_select_group_button_height">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -482,4 +482,8 @@
|
|||
<color name="text_input_background_dark">#1AFFFFFF</color>
|
||||
<color name="mtrl_textinput_default_box_stroke_color">#67727272</color>
|
||||
|
||||
<color name="track_gradient_start">#5ADC5F</color>
|
||||
<color name="track_gradient_center">#D4EF32</color>
|
||||
<color name="track_gradient_end">#F3374D</color>
|
||||
|
||||
</resources>
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
-->
|
||||
|
||||
<string name="select_another_colorization">Please select another type of colorization.</string>
|
||||
<string name="track_has_no_speed">The track does not contain speed data.</string>
|
||||
<string name="track_has_no_altitude">The track does not contain altitude data.</string>
|
||||
<string name="shared_string_interval">Interval</string>
|
||||
<string name="quick_action_show_hide_title">Show/hide</string>
|
||||
<string name="copy_poi_name">Copy POI name</string>
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package net.osmand.plus;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.IndexConstants;
|
||||
|
@ -16,6 +13,9 @@ import java.io.File;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class GPXDatabase {
|
||||
|
||||
private static final int DB_VERSION = 11;
|
||||
|
@ -176,11 +176,11 @@ public class GPXDatabase {
|
|||
private File file;
|
||||
private GPXTrackAnalysis analysis;
|
||||
private String width;
|
||||
private GradientScaleType gradientScaleType;
|
||||
private int color;
|
||||
private int gradientSpeedColor;
|
||||
private int gradientAltitudeColor;
|
||||
private int gradientSlopeColor;
|
||||
private GradientScaleType gradientScaleType;
|
||||
private int[] gradientSpeedPalette;
|
||||
private int[] gradientAltitudePalette;
|
||||
private int[] gradientSlopePalette;
|
||||
private int splitType;
|
||||
private double splitInterval;
|
||||
private long fileLastModifiedTime;
|
||||
|
@ -210,9 +210,9 @@ public class GPXDatabase {
|
|||
width = gpxFile.getWidth(null);
|
||||
showArrows = gpxFile.isShowArrows();
|
||||
showStartFinish = gpxFile.isShowStartFinish();
|
||||
gradientSpeedColor = gpxFile.getGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), 0);
|
||||
gradientSlopeColor = gpxFile.getGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), 0);
|
||||
gradientAltitudeColor = gpxFile.getGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), 0);
|
||||
gradientSpeedPalette = gpxFile.getGradientScaleColor(GradientScaleType.SPEED.getColorTypeName());
|
||||
gradientSlopePalette = gpxFile.getGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName());
|
||||
gradientAltitudePalette = gpxFile.getGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName());
|
||||
|
||||
if (!Algorithms.isEmpty(gpxFile.getSplitType()) && gpxFile.getSplitInterval() > 0) {
|
||||
GpxSplitType gpxSplitType = GpxSplitType.getSplitTypeByName(gpxFile.getSplitType());
|
||||
|
@ -243,23 +243,22 @@ public class GPXDatabase {
|
|||
return gradientScaleType;
|
||||
}
|
||||
|
||||
public int getGradientSpeedColor() {
|
||||
return gradientSpeedColor;
|
||||
public int[] getGradientSpeedPalette() {
|
||||
return gradientSpeedPalette;
|
||||
}
|
||||
|
||||
public int getGradientAltitudeColor() {
|
||||
return gradientAltitudeColor;
|
||||
public int[] getGradientAltitudePalette() {
|
||||
return gradientAltitudePalette;
|
||||
}
|
||||
|
||||
public int getGradientSlopeColor() {
|
||||
return gradientSlopeColor;
|
||||
public int[] getGradientSlopePalette() {
|
||||
return gradientSlopePalette;
|
||||
}
|
||||
|
||||
public String getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
public long getFileLastModifiedTime() {
|
||||
return fileLastModifiedTime;
|
||||
}
|
||||
|
@ -507,7 +506,7 @@ public class GPXDatabase {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean updateGradientScaleColor(@NonNull GpxDataItem item, @NonNull GradientScaleType gradientScaleType, int gradientScaleColor) {
|
||||
public boolean updateGradientScaleColor(@NonNull GpxDataItem item, @NonNull GradientScaleType gradientScaleType, int[] gradientScalePalette) {
|
||||
SQLiteConnection db = openConnection(false);
|
||||
if (db != null) {
|
||||
try {
|
||||
|
@ -516,17 +515,17 @@ public class GPXDatabase {
|
|||
String columnName = null;
|
||||
if (GradientScaleType.SPEED == gradientScaleType) {
|
||||
columnName = GPX_COL_GRADIENT_SPEED_COLOR;
|
||||
item.gradientSpeedColor = gradientScaleColor;
|
||||
item.gradientSpeedPalette = gradientScalePalette;
|
||||
} else if (GradientScaleType.ALTITUDE == gradientScaleType) {
|
||||
columnName = GPX_COL_GRADIENT_ALTITUDE_COLOR;
|
||||
item.gradientAltitudeColor = gradientScaleColor;
|
||||
item.gradientAltitudePalette = gradientScalePalette;
|
||||
} else if (GradientScaleType.SLOPE == gradientScaleType) {
|
||||
columnName = GPX_COL_GRADIENT_SLOPE_COLOR;
|
||||
item.gradientSlopeColor = gradientScaleColor;
|
||||
item.gradientSlopePalette = gradientScalePalette;
|
||||
}
|
||||
db.execSQL("UPDATE " + GPX_TABLE_NAME + " SET " + columnName + " = ? " +
|
||||
" WHERE " + GPX_COL_NAME + " = ? AND " + GPX_COL_DIR + " = ?",
|
||||
new Object[] {(gradientScaleColor == 0 ? "" : Algorithms.colorToString(gradientScaleColor)), fileName, fileDir});
|
||||
new Object[] {Algorithms.gradientPaletteToString(gradientScalePalette), fileName, fileDir});
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
|
@ -729,7 +728,7 @@ public class GPXDatabase {
|
|||
color, item.file.lastModified(), item.splitType, item.splitInterval, item.apiImported ? 1 : 0,
|
||||
Algorithms.encodeStringSet(item.analysis.wptCategoryNames), item.showAsMarkers ? 1 : 0,
|
||||
item.joinSegments ? 1 : 0, item.showArrows ? 1 : 0, item.showStartFinish ? 1 : 0, item.width,
|
||||
item.gradientSpeedColor, item.gradientAltitudeColor, item.gradientSlopeColor, gradientScaleType});
|
||||
item.gradientSpeedPalette, item.gradientAltitudePalette, item.gradientSlopePalette, gradientScaleType});
|
||||
} else {
|
||||
db.execSQL("INSERT INTO " + GPX_TABLE_NAME + "(" +
|
||||
GPX_COL_NAME + ", " +
|
||||
|
@ -752,7 +751,9 @@ public class GPXDatabase {
|
|||
new Object[] {fileName, fileDir, color, 0, item.splitType, item.splitInterval,
|
||||
item.apiImported ? 1 : 0, item.showAsMarkers ? 1 : 0, item.joinSegments ? 1 : 0,
|
||||
item.showArrows ? 1 : 0, item.showStartFinish ? 1 : 0, item.width,
|
||||
item.gradientSpeedColor, item.gradientAltitudeColor, item.gradientSlopeColor, gradientScaleType});
|
||||
Algorithms.gradientPaletteToString(item.gradientSpeedPalette),
|
||||
Algorithms.gradientPaletteToString(item.gradientAltitudePalette),
|
||||
Algorithms.gradientPaletteToString(item.gradientSlopePalette), gradientScaleType});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,9 +837,9 @@ public class GPXDatabase {
|
|||
boolean showArrows = query.getInt(26) == 1;
|
||||
boolean showStartFinish = query.getInt(27) == 1;
|
||||
String width = query.getString(28);
|
||||
String gradientSpeedColor = query.getString(29);
|
||||
String gradientAltitudeColor = query.getString(30);
|
||||
String gradientSlopeColor = query.getString(31);
|
||||
String gradientSpeedPalette = query.getString(29);
|
||||
String gradientAltitudePalette = query.getString(30);
|
||||
String gradientSlopePalette = query.getString(31);
|
||||
String gradientScaleType = query.getString(32);
|
||||
|
||||
GPXTrackAnalysis a = new GPXTrackAnalysis();
|
||||
|
@ -880,12 +881,12 @@ public class GPXDatabase {
|
|||
item.showArrows = showArrows;
|
||||
item.showStartFinish = showStartFinish;
|
||||
item.width = width;
|
||||
item.gradientSpeedColor = parseColor(gradientSpeedColor);
|
||||
item.gradientAltitudeColor = parseColor(gradientAltitudeColor);
|
||||
item.gradientSlopeColor = parseColor(gradientSlopeColor);
|
||||
item.gradientSpeedPalette = Algorithms.stringToGradientPalette(gradientSpeedPalette);
|
||||
item.gradientAltitudePalette = Algorithms.stringToGradientPalette(gradientAltitudePalette);
|
||||
item.gradientSlopePalette = Algorithms.stringToGradientPalette(gradientSlopePalette);
|
||||
|
||||
try {
|
||||
item.gradientScaleType = Algorithms.isEmpty(gradientScaleType) ? null : GradientScaleType.valueOf(gradientScaleType);
|
||||
item.gradientScaleType = GradientScaleType.getGradientTypeByName(gradientScaleType);
|
||||
} catch (IllegalArgumentException e) {
|
||||
item.gradientScaleType = null;
|
||||
}
|
||||
|
|
|
@ -78,8 +78,8 @@ public class GpxDbHelper {
|
|||
return res;
|
||||
}
|
||||
|
||||
public boolean updateGradientScaleColor(@NonNull GpxDataItem item, @NonNull GradientScaleType gradientScaleType, int color) {
|
||||
boolean res = db.updateGradientScaleColor(item, gradientScaleType, color);
|
||||
public boolean updateGradientScalePalette(@NonNull GpxDataItem item, @NonNull GradientScaleType gradientScaleType, int[] palette) {
|
||||
boolean res = db.updateGradientScaleColor(item, gradientScaleType, palette);
|
||||
putToCache(item);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -2310,15 +2310,9 @@ public class GpxUiHelper {
|
|||
if (dataItem.getWidth() != null) {
|
||||
gpxFile.setWidth(dataItem.getWidth());
|
||||
}
|
||||
if (dataItem.getGradientSpeedColor() != 0) {
|
||||
gpxFile.setGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), dataItem.getGradientSpeedColor());
|
||||
}
|
||||
if (dataItem.getGradientSlopeColor() != 0) {
|
||||
gpxFile.setGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), dataItem.getGradientSlopeColor());
|
||||
}
|
||||
if (dataItem.getGradientAltitudeColor() != 0) {
|
||||
gpxFile.setGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), dataItem.getGradientAltitudeColor());
|
||||
}
|
||||
gpxFile.setGradientScaleColor(GradientScaleType.SPEED.getColorTypeName(), dataItem.getGradientSpeedPalette());
|
||||
gpxFile.setGradientScaleColor(GradientScaleType.SLOPE.getColorTypeName(), dataItem.getGradientSlopePalette());
|
||||
gpxFile.setGradientScaleColor(GradientScaleType.ALTITUDE.getColorTypeName(), dataItem.getGradientAltitudePalette());
|
||||
if (dataItem.getGradientScaleType() != null) {
|
||||
gpxFile.setGradientScaleType(dataItem.getGradientScaleType().name());
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ public class EnumStringPreference<E extends Enum<E>> extends CommonPreference<E>
|
|||
@Override
|
||||
protected E getValue(Object prefs, E defaultValue) {
|
||||
try {
|
||||
String name = getSettingsAPI().getString(prefs, getId(), defaultValue.name());
|
||||
String defaultValueName = defaultValue == null ? null : defaultValue.name();
|
||||
String name = getSettingsAPI().getString(prefs, getId(), defaultValueName);
|
||||
E value = parseString(name);
|
||||
return value != null ? value : defaultValue;
|
||||
} catch (ClassCastException ex) {
|
||||
|
@ -23,7 +24,8 @@ public class EnumStringPreference<E extends Enum<E>> extends CommonPreference<E>
|
|||
|
||||
@Override
|
||||
public boolean setValue(Object prefs, E val) {
|
||||
return getSettingsAPI().edit(prefs).putString(getId(), val.name()).commit();
|
||||
String name = val == null ? null : val.name();
|
||||
return getSettingsAPI().edit(prefs).putString(getId(), name).commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -50,6 +50,7 @@ import net.osmand.plus.rastermaps.LayerTransparencySeekbarMode;
|
|||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.routing.RouteService;
|
||||
import net.osmand.plus.srtmplugin.TerrainMode;
|
||||
import net.osmand.plus.track.GradientScaleType;
|
||||
import net.osmand.plus.views.layers.RadiusRulerControlLayer.RadiusRulerMode;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.wikipedia.WikiArticleShowImages;
|
||||
|
@ -1408,6 +1409,10 @@ public class OsmandSettings {
|
|||
public final OsmandPreference<Long> LAST_UPDATES_CARD_REFRESH = new LongPreference(this, "last_updates_card_refresh", 0).makeGlobal();
|
||||
|
||||
public final CommonPreference<Integer> CURRENT_TRACK_COLOR = new IntPreference(this, "current_track_color", 0).makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<GradientScaleType> CURRENT_TRACK_COLORIZATION = new EnumStringPreference<>(this, "current_track_colorization", null, GradientScaleType.values()).makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<String> CURRENT_TRACK_SPEED_GRADIENT_PALETTE = new StringPreference(this, "current_track_speed_gradient_palette", null).makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<String> CURRENT_TRACK_ALTITUDE_GRADIENT_PALETTE = new StringPreference(this, "current_track_altitude_gradient_palette", null).makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<String> CURRENT_TRACK_SLOPE_GRADIENT_PALETTE = new StringPreference(this, "current_track_slope_gradient_palette", null).makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<String> CURRENT_TRACK_WIDTH = new StringPreference(this, "current_track_width", "").makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<Boolean> CURRENT_TRACK_SHOW_ARROWS = new BooleanPreference(this, "current_track_show_arrows", false).makeGlobal().makeShared().cache();
|
||||
public final CommonPreference<Boolean> CURRENT_TRACK_SHOW_START_FINISH = new BooleanPreference(this, "current_track_show_start_finish", true).makeGlobal().makeShared().cache();
|
||||
|
|
|
@ -17,9 +17,9 @@ public class GpxAppearanceInfo {
|
|||
public String width;
|
||||
public GradientScaleType scaleType;
|
||||
public int color;
|
||||
public int gradientSpeedColor;
|
||||
public int gradientAltitudeColor;
|
||||
public int gradientSlopeColor;
|
||||
public int[] gradientSpeedPalette;
|
||||
public int[] gradientAltitudePalette;
|
||||
public int[] gradientSlopePalette;
|
||||
public int splitType;
|
||||
public double splitInterval;
|
||||
public boolean showArrows;
|
||||
|
@ -41,9 +41,9 @@ public class GpxAppearanceInfo {
|
|||
splitType = dataItem.getSplitType();
|
||||
splitInterval = dataItem.getSplitInterval();
|
||||
scaleType = dataItem.getGradientScaleType();
|
||||
gradientSpeedColor = dataItem.getGradientSpeedColor();
|
||||
gradientSlopeColor = dataItem.getGradientSlopeColor();
|
||||
gradientAltitudeColor = dataItem.getGradientAltitudeColor();
|
||||
gradientSpeedPalette = dataItem.getGradientSpeedPalette();
|
||||
gradientSlopePalette = dataItem.getGradientSlopePalette();
|
||||
gradientAltitudePalette = dataItem.getGradientAltitudePalette();
|
||||
|
||||
GPXTrackAnalysis analysis = dataItem.getAnalysis();
|
||||
if (analysis != null) {
|
||||
|
@ -61,9 +61,9 @@ public class GpxAppearanceInfo {
|
|||
writeParam(json, "split_type", GpxSplitType.getSplitTypeByTypeId(splitType).getTypeName());
|
||||
writeParam(json, "split_interval", splitInterval);
|
||||
writeParam(json, "gradient_scale_type", scaleType);
|
||||
writeParam(json, GradientScaleType.SPEED.getColorTypeName(), gradientSpeedColor);
|
||||
writeParam(json, GradientScaleType.SLOPE.getColorTypeName(), gradientSlopeColor);
|
||||
writeParam(json, GradientScaleType.ALTITUDE.getColorTypeName(), gradientAltitudeColor);
|
||||
writeParam(json, GradientScaleType.SPEED.getColorTypeName(), Algorithms.gradientPaletteToString(gradientSpeedPalette));
|
||||
writeParam(json, GradientScaleType.ALTITUDE.getColorTypeName(), Algorithms.gradientPaletteToString(gradientAltitudePalette));
|
||||
writeParam(json, GradientScaleType.SLOPE.getColorTypeName(), Algorithms.gradientPaletteToString(gradientSlopePalette));
|
||||
|
||||
writeParam(json, "time_span", timeSpan);
|
||||
writeParam(json, "wpt_points", wptPoints);
|
||||
|
@ -79,9 +79,9 @@ public class GpxAppearanceInfo {
|
|||
gpxAppearanceInfo.splitType = GpxSplitType.getSplitTypeByName(json.optString("split_type")).getType();
|
||||
gpxAppearanceInfo.splitInterval = json.optDouble("split_interval");
|
||||
gpxAppearanceInfo.scaleType = getScaleType(json.optString("gradient_scale_type"));
|
||||
gpxAppearanceInfo.gradientSpeedColor = json.optInt(GradientScaleType.SPEED.getColorTypeName());
|
||||
gpxAppearanceInfo.gradientSlopeColor = json.optInt(GradientScaleType.SLOPE.getColorTypeName());
|
||||
gpxAppearanceInfo.gradientAltitudeColor = json.optInt(GradientScaleType.ALTITUDE.getColorTypeName());
|
||||
gpxAppearanceInfo.gradientSpeedPalette = getGradientPalette(json, GradientScaleType.SPEED);
|
||||
gpxAppearanceInfo.gradientAltitudePalette = getGradientPalette(json, GradientScaleType.ALTITUDE);
|
||||
gpxAppearanceInfo.gradientSlopePalette = getGradientPalette(json, GradientScaleType.SLOPE);
|
||||
|
||||
gpxAppearanceInfo.timeSpan = json.optLong("time_span");
|
||||
gpxAppearanceInfo.wptPoints = json.optInt("wpt_points");
|
||||
|
@ -101,6 +101,10 @@ public class GpxAppearanceInfo {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static int[] getGradientPalette(JSONObject json, GradientScaleType scaleType) {
|
||||
return Algorithms.stringToGradientPalette(json.optString(scaleType.getColorTypeName()));
|
||||
}
|
||||
|
||||
private static void writeParam(@NonNull JSONObject json, @NonNull String name, @Nullable Object value) throws JSONException {
|
||||
if (value instanceof Integer) {
|
||||
if ((Integer) value != 0) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import net.osmand.plus.GpxDbHelper;
|
|||
import net.osmand.plus.GpxDbHelper.GpxDataItemCallback;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.track.GpxSplitType;
|
||||
import net.osmand.plus.track.GradientScaleType;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -83,6 +84,9 @@ public class GpxSettingsItem extends FileSettingsItem {
|
|||
gpxDbHelper.updateShowStartFinish(dataItem, appearanceInfo.showStartFinish);
|
||||
gpxDbHelper.updateSplit(dataItem, splitType, appearanceInfo.splitInterval);
|
||||
gpxDbHelper.updateGradientScaleType(dataItem, appearanceInfo.scaleType);
|
||||
gpxDbHelper.updateGradientScalePalette(dataItem, GradientScaleType.SPEED, appearanceInfo.gradientSpeedPalette);
|
||||
gpxDbHelper.updateGradientScalePalette(dataItem, GradientScaleType.ALTITUDE, appearanceInfo.gradientAltitudePalette);
|
||||
gpxDbHelper.updateGradientScalePalette(dataItem, GradientScaleType.SLOPE, appearanceInfo.gradientSlopePalette);
|
||||
}
|
||||
|
||||
private void createGpxAppearanceInfo() {
|
||||
|
|
84
OsmAnd/src/net/osmand/plus/track/GradientCard.java
Normal file
84
OsmAnd/src/net/osmand/plus/track/GradientCard.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.widget.TextView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class GradientCard extends BaseCard {
|
||||
|
||||
private GPXTrackAnalysis gpxTrackAnalysis;
|
||||
private GradientScaleType selectedScaleType;
|
||||
|
||||
public GradientCard(@NonNull MapActivity mapActivity, @NonNull GPXTrackAnalysis gpxTrackAnalysis, @Nullable GradientScaleType selectedScaleType) {
|
||||
super(mapActivity);
|
||||
this.gpxTrackAnalysis = gpxTrackAnalysis;
|
||||
this.selectedScaleType = selectedScaleType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardLayoutId() {
|
||||
return R.layout.gradient_card;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateContent() {
|
||||
if (selectedScaleType == null) {
|
||||
AndroidUiHelper.updateVisibility(view, false);
|
||||
return;
|
||||
}
|
||||
|
||||
AndroidUiHelper.updateVisibility(view, true);
|
||||
TextView minValue = view.findViewById(R.id.min_value);
|
||||
TextView maxValue = view.findViewById(R.id.max_value);
|
||||
float min = getMinValue();
|
||||
float max = getMaxValue(min);
|
||||
minValue.setText(formatValue(min));
|
||||
maxValue.setText(formatValue(max));
|
||||
}
|
||||
|
||||
public void setSelectedScaleType(GradientScaleType type) {
|
||||
this.selectedScaleType = type;
|
||||
updateContent();
|
||||
}
|
||||
|
||||
private float getMinValue() {
|
||||
return (float) (selectedScaleType == GradientScaleType.ALTITUDE ? gpxTrackAnalysis.minElevation : 0.0);
|
||||
}
|
||||
|
||||
private float getMaxValue(float minValue) {
|
||||
if (selectedScaleType == GradientScaleType.SPEED) {
|
||||
return (Math.max(gpxTrackAnalysis.maxSpeed, app.getSettings().getApplicationMode().getMaxSpeed()));
|
||||
} else if (selectedScaleType == GradientScaleType.ALTITUDE) {
|
||||
return (float) Math.max(gpxTrackAnalysis.maxElevation, minValue + 50);
|
||||
} else {
|
||||
return 25;
|
||||
}
|
||||
}
|
||||
|
||||
private CharSequence formatValue(float value) {
|
||||
if (selectedScaleType == GradientScaleType.ALTITUDE) {
|
||||
return OsmAndFormatter.getFormattedAlt(value, app);
|
||||
} else if (selectedScaleType == GradientScaleType.SLOPE) {
|
||||
return (int) value + " %";
|
||||
}
|
||||
String speed = OsmAndFormatter.getFormattedSpeed(value, app);
|
||||
String speedUnit = app.getSettings().SPEED_SYSTEM.get().toShortString(app);
|
||||
Spannable formattedSpeed = new SpannableString(speed);
|
||||
formattedSpeed.setSpan(
|
||||
new ForegroundColorSpan(AndroidUtils.getColorFromAttr(app, android.R.attr.textColorSecondary)),
|
||||
speed.indexOf(speedUnit), speed.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return formattedSpeed;
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.StringRes;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.router.RouteColorize.ColorizationType;
|
||||
|
||||
public enum GradientScaleType {
|
||||
|
||||
|
@ -44,6 +45,18 @@ public enum GradientScaleType {
|
|||
return ctx.getString(resId);
|
||||
}
|
||||
|
||||
public ColorizationType toColorizationType() {
|
||||
if (this == SPEED) {
|
||||
return ColorizationType.SPEED;
|
||||
} else if (this == ALTITUDE) {
|
||||
return ColorizationType.ELEVATION;
|
||||
} else if (this == SLOPE) {
|
||||
return ColorizationType.SLOPE;
|
||||
} else {
|
||||
return ColorizationType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public static GradientScaleType getGradientTypeByName(@NonNull String name) {
|
||||
for (GradientScaleType scaleType : GradientScaleType.values()) {
|
||||
if (scaleType.name().equalsIgnoreCase(name)) {
|
||||
|
|
|
@ -15,14 +15,6 @@ import android.widget.ImageView;
|
|||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.PlatformUtil;
|
||||
|
@ -60,6 +52,14 @@ import java.io.File;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import static net.osmand.plus.dialogs.ConfigureMapMenu.CURRENT_TRACK_COLOR_ATTR;
|
||||
import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_BOLD;
|
||||
import static net.osmand.plus.dialogs.GpxAppearanceAdapter.TRACK_WIDTH_MEDIUM;
|
||||
|
@ -89,6 +89,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
private SplitIntervalCard splitIntervalCard;
|
||||
private TrackColoringCard trackColoringCard;
|
||||
private ColorsCard colorsCard;
|
||||
private GradientCard gradientCard;
|
||||
private boolean showStartFinishIconsInitialValue;
|
||||
|
||||
private ImageView trackIcon;
|
||||
|
@ -158,6 +159,10 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
if (selectedGpxFile.isShowCurrentTrack()) {
|
||||
trackDrawInfo = new TrackDrawInfo(true);
|
||||
trackDrawInfo.setColor(app.getSettings().CURRENT_TRACK_COLOR.get());
|
||||
trackDrawInfo.setGradientScaleType(app.getSettings().CURRENT_TRACK_COLORIZATION.get());
|
||||
trackDrawInfo.setSpeedGradientPalette(Algorithms.stringToArray(app.getSettings().CURRENT_TRACK_SPEED_GRADIENT_PALETTE.get()));
|
||||
trackDrawInfo.setAltitudeGradientPalette(Algorithms.stringToArray(app.getSettings().CURRENT_TRACK_ALTITUDE_GRADIENT_PALETTE.get()));
|
||||
trackDrawInfo.setSlopeGradientPalette(Algorithms.stringToArray(app.getSettings().CURRENT_TRACK_SLOPE_GRADIENT_PALETTE.get()));
|
||||
trackDrawInfo.setWidth(app.getSettings().CURRENT_TRACK_WIDTH.get());
|
||||
trackDrawInfo.setShowArrows(app.getSettings().CURRENT_TRACK_SHOW_ARROWS.get());
|
||||
trackDrawInfo.setShowStartFinish(app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.get());
|
||||
|
@ -340,6 +345,16 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
if (mapActivity != null) {
|
||||
if (card instanceof SplitIntervalCard) {
|
||||
SplitIntervalBottomSheet.showInstance(mapActivity.getSupportFragmentManager(), trackDrawInfo, this);
|
||||
} else if (card instanceof TrackColoringCard) {
|
||||
GradientScaleType currentScaleType = ((TrackColoringCard) card).getSelectedScaleType();
|
||||
trackDrawInfo.setGradientScaleType(currentScaleType);
|
||||
mapActivity.refreshMap();
|
||||
if (gradientCard != null) {
|
||||
gradientCard.setSelectedScaleType(currentScaleType);
|
||||
}
|
||||
if (colorsCard != null) {
|
||||
AndroidUiHelper.updateVisibility(colorsCard.getView(), currentScaleType == null);
|
||||
}
|
||||
} else if (card instanceof ColorsCard) {
|
||||
int color = ((ColorsCard) card).getSelectedColor();
|
||||
trackDrawInfo.setColor(color);
|
||||
|
@ -555,6 +570,9 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
if (trackWidthCard != null) {
|
||||
trackWidthCard.updateItems();
|
||||
}
|
||||
if (trackColoringCard != null) {
|
||||
trackColoringCard.updateColor();
|
||||
}
|
||||
MapActivity mapActivity = getMapActivity();
|
||||
if (mapActivity != null) {
|
||||
mapActivity.refreshMap();
|
||||
|
@ -565,12 +583,19 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
GPXFile gpxFile = selectedGpxFile.getGpxFile();
|
||||
if (gpxFile.showCurrentTrack) {
|
||||
app.getSettings().CURRENT_TRACK_COLOR.set(trackDrawInfo.getColor());
|
||||
app.getSettings().CURRENT_TRACK_COLORIZATION.set(trackDrawInfo.getGradientScaleType());
|
||||
app.getSettings().CURRENT_TRACK_SPEED_GRADIENT_PALETTE.set(Algorithms.arrayToString(trackDrawInfo.getSpeedGradientPalette()));
|
||||
app.getSettings().CURRENT_TRACK_ALTITUDE_GRADIENT_PALETTE.set(Algorithms.arrayToString(trackDrawInfo.getAltitudeGradientPalette()));
|
||||
app.getSettings().CURRENT_TRACK_SLOPE_GRADIENT_PALETTE.set(Algorithms.arrayToString(trackDrawInfo.getSlopeGradientPalette()));
|
||||
app.getSettings().CURRENT_TRACK_WIDTH.set(trackDrawInfo.getWidth());
|
||||
app.getSettings().CURRENT_TRACK_SHOW_ARROWS.set(trackDrawInfo.isShowArrows());
|
||||
app.getSettings().CURRENT_TRACK_SHOW_START_FINISH.set(trackDrawInfo.isShowStartFinish());
|
||||
} else if (gpxDataItem != null) {
|
||||
GpxSplitType splitType = GpxSplitType.getSplitTypeByTypeId(trackDrawInfo.getSplitType());
|
||||
gpxDbHelper.updateColor(gpxDataItem, trackDrawInfo.getColor());
|
||||
gpxDbHelper.updateGradientScalePalette(gpxDataItem, GradientScaleType.SPEED, trackDrawInfo.getSpeedGradientPalette());
|
||||
gpxDbHelper.updateGradientScalePalette(gpxDataItem, GradientScaleType.ALTITUDE, trackDrawInfo.getAltitudeGradientPalette());
|
||||
gpxDbHelper.updateGradientScalePalette(gpxDataItem, GradientScaleType.SLOPE, trackDrawInfo.getSlopeGradientPalette());
|
||||
gpxDbHelper.updateWidth(gpxDataItem, trackDrawInfo.getWidth());
|
||||
gpxDbHelper.updateShowArrows(gpxDataItem, trackDrawInfo.isShowArrows());
|
||||
// gpxDbHelper.updateShowStartFinish(gpxDataItem, trackDrawInfo.isShowStartFinish());
|
||||
|
@ -642,12 +667,15 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
showStartFinishCard.setListener(this);
|
||||
cardsContainer.addView(showStartFinishCard.build(mapActivity));
|
||||
|
||||
trackColoringCard = new TrackColoringCard(mapActivity, trackDrawInfo, this);
|
||||
trackColoringCard = new TrackColoringCard(mapActivity, selectedGpxFile.getTrackAnalysis(app), trackDrawInfo);
|
||||
trackColoringCard.setListener(this);
|
||||
cardsContainer.addView(trackColoringCard.build(mapActivity));
|
||||
|
||||
setupColorsCard(cardsContainer);
|
||||
|
||||
gradientCard = new GradientCard(mapActivity, selectedGpxFile.getTrackAnalysis(app), trackDrawInfo.getGradientScaleType());
|
||||
cardsContainer.addView(gradientCard.build(mapActivity));
|
||||
|
||||
trackWidthCard = new TrackWidthCard(mapActivity, trackDrawInfo, new OnNeedScrollListener() {
|
||||
|
||||
@Override
|
||||
|
@ -674,7 +702,8 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
|
|||
List<Integer> colors = getTrackColors();
|
||||
colorsCard = new ColorsCard(mapActivity, trackDrawInfo.getColor(), this, colors, app.getSettings().CUSTOM_TRACK_COLORS, null);
|
||||
colorsCard.setListener(this);
|
||||
cardsContainer.addView(colorsCard.build(mapActivity));
|
||||
AndroidUiHelper.updateVisibility(colorsCard.build(mapActivity), trackDrawInfo.getGradientScaleType() == null);
|
||||
cardsContainer.addView(colorsCard.getView());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Build;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -7,14 +8,10 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
|
@ -27,26 +24,29 @@ import org.apache.commons.logging.Log;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TrackColoringCard extends BaseCard {
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
private static final int MINIMUM_CONTRAST_RATIO = 3;
|
||||
public class TrackColoringCard extends BaseCard {
|
||||
|
||||
private final static String SOLID_COLOR = "solid_color";
|
||||
private static final Log log = PlatformUtil.getLog(TrackColoringCard.class);
|
||||
|
||||
private GPXTrackAnalysis gpxTrackAnalysis;
|
||||
private TrackDrawInfo trackDrawInfo;
|
||||
|
||||
private TrackColoringAdapter coloringAdapter;
|
||||
private TrackAppearanceItem selectedAppearanceItem;
|
||||
private List<TrackAppearanceItem> appearanceItems;
|
||||
|
||||
private Fragment target;
|
||||
|
||||
public TrackColoringCard(MapActivity mapActivity, TrackDrawInfo trackDrawInfo, Fragment target) {
|
||||
public TrackColoringCard(MapActivity mapActivity, GPXTrackAnalysis gpxTrackAnalysis, TrackDrawInfo trackDrawInfo) {
|
||||
super(mapActivity);
|
||||
this.target = target;
|
||||
this.trackDrawInfo = trackDrawInfo;
|
||||
appearanceItems = getGradientAppearanceItems();
|
||||
this.gpxTrackAnalysis = gpxTrackAnalysis;
|
||||
appearanceItems = getTrackAppearanceItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,25 +58,44 @@ public class TrackColoringCard extends BaseCard {
|
|||
protected void updateContent() {
|
||||
updateHeader();
|
||||
|
||||
// coloringAdapter = new TrackColoringAdapter(appearanceItems);
|
||||
// RecyclerView groupRecyclerView = view.findViewById(R.id.recycler_view);
|
||||
// groupRecyclerView.setAdapter(coloringAdapter);
|
||||
// groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
|
||||
coloringAdapter = new TrackColoringAdapter(appearanceItems);
|
||||
RecyclerView groupRecyclerView = view.findViewById(R.id.recycler_view);
|
||||
groupRecyclerView.setLayoutManager(new LinearLayoutManager(app, RecyclerView.HORIZONTAL, false));
|
||||
groupRecyclerView.setAdapter(coloringAdapter);
|
||||
|
||||
AndroidUiHelper.updateVisibility(view.findViewById(R.id.top_divider), isShowDivider());
|
||||
}
|
||||
|
||||
private List<TrackAppearanceItem> getGradientAppearanceItems() {
|
||||
public void updateColor() {
|
||||
if (coloringAdapter != null) {
|
||||
// Provide empty object to update item without animation
|
||||
coloringAdapter.notifyItemChanged(0, new Object());
|
||||
}
|
||||
}
|
||||
|
||||
public GradientScaleType getSelectedScaleType() {
|
||||
String attrName = selectedAppearanceItem.getAttrName();
|
||||
return attrName.equals(SOLID_COLOR) ? null : GradientScaleType.valueOf(attrName.toUpperCase());
|
||||
}
|
||||
|
||||
private List<TrackAppearanceItem> getTrackAppearanceItems() {
|
||||
List<TrackAppearanceItem> items = new ArrayList<>();
|
||||
items.add(new TrackAppearanceItem(SOLID_COLOR, app.getString(R.string.track_coloring_solid), R.drawable.ic_action_circle));
|
||||
|
||||
// for (GradientScaleType scaleType : GradientScaleType.values()) {
|
||||
// items.add(new TrackAppearanceItem(scaleType.getTypeName(), scaleType.getHumanString(app), scaleType.getIconId()));
|
||||
// }
|
||||
|
||||
items.add(new TrackAppearanceItem(SOLID_COLOR, app.getString(R.string.track_coloring_solid), R.drawable.ic_action_circle, true));
|
||||
for (GradientScaleType scaleType : GradientScaleType.values()) {
|
||||
items.add(new TrackAppearanceItem(scaleType.getTypeName(),
|
||||
scaleType.getHumanString(app), scaleType.getIconId(), isScaleTypeActive(scaleType)));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private boolean isScaleTypeActive(GradientScaleType scaleType) {
|
||||
if (scaleType == GradientScaleType.SPEED) {
|
||||
return gpxTrackAnalysis.isSpeedSpecified();
|
||||
} else {
|
||||
return gpxTrackAnalysis.isElevationSpecified();
|
||||
}
|
||||
}
|
||||
|
||||
private TrackAppearanceItem getSelectedAppearanceItem() {
|
||||
if (selectedAppearanceItem == null) {
|
||||
GradientScaleType scaleType = trackDrawInfo.getGradientScaleType();
|
||||
|
@ -98,27 +117,22 @@ public class TrackColoringCard extends BaseCard {
|
|||
headerView.setBackgroundDrawable(null);
|
||||
|
||||
TextView titleView = view.findViewById(R.id.title);
|
||||
titleView.setText(R.string.select_color);
|
||||
titleView.setText(R.string.shared_string_color);
|
||||
|
||||
TextView descriptionView = view.findViewById(R.id.description);
|
||||
descriptionView.setText(getSelectedAppearanceItem().getLocalizedValue());
|
||||
}
|
||||
|
||||
private void updateColorSelector() {
|
||||
boolean visible = getSelectedAppearanceItem().getAttrName().equals(SOLID_COLOR);
|
||||
AndroidUiHelper.updateVisibility(view.findViewById(R.id.select_color), visible);
|
||||
}
|
||||
|
||||
public void setGradientScaleType(TrackAppearanceItem item) {
|
||||
selectedAppearanceItem = item;
|
||||
if (item.getAttrName().equals(SOLID_COLOR)) {
|
||||
trackDrawInfo.setGradientScaleType(null);
|
||||
} else {
|
||||
trackDrawInfo.setGradientScaleType(GradientScaleType.valueOf(item.getAttrName()));
|
||||
trackDrawInfo.setGradientScaleType(GradientScaleType.valueOf(item.getAttrName().toUpperCase()));
|
||||
}
|
||||
mapActivity.refreshMap();
|
||||
|
||||
updateHeader();
|
||||
updateColorSelector();
|
||||
}
|
||||
|
||||
private class TrackColoringAdapter extends RecyclerView.Adapter<TrackAppearanceViewHolder> {
|
||||
|
@ -136,42 +150,38 @@ public class TrackColoringCard extends BaseCard {
|
|||
View view = themedInflater.inflate(R.layout.point_editor_group_select_item, parent, false);
|
||||
view.getLayoutParams().width = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_width);
|
||||
view.getLayoutParams().height = app.getResources().getDimensionPixelSize(R.dimen.gpx_group_button_height);
|
||||
|
||||
TrackAppearanceViewHolder holder = new TrackAppearanceViewHolder(view);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
|
||||
R.drawable.ripple_solid_dark_6dp);
|
||||
}
|
||||
return holder;
|
||||
return new TrackAppearanceViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull final TrackAppearanceViewHolder holder, int position) {
|
||||
TrackAppearanceItem item = items.get(position);
|
||||
holder.title.setText(item.getLocalizedValue());
|
||||
final TrackAppearanceItem item = items.get(position);
|
||||
|
||||
updateButtonBg(holder, item);
|
||||
|
||||
int colorId;
|
||||
if (item.getAttrName().equals(SOLID_COLOR)) {
|
||||
colorId = trackDrawInfo.getColor();
|
||||
} else if (item.getAttrName().equals(getSelectedAppearanceItem().getAttrName())) {
|
||||
colorId = ContextCompat.getColor(app, nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light);
|
||||
} else {
|
||||
colorId = AndroidUtils.getColorFromAttr(holder.itemView.getContext(), R.attr.default_icon_color);
|
||||
if (item.isActive() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AndroidUtils.setBackground(app, holder.button, nightMode, R.drawable.ripple_solid_light_6dp,
|
||||
R.drawable.ripple_solid_dark_6dp);
|
||||
}
|
||||
|
||||
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.getIconId(), colorId));
|
||||
updateButtonBg(holder, item);
|
||||
updateTextAndIconColor(holder, item);
|
||||
|
||||
holder.title.setText(item.getLocalizedValue());
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (!item.isActive()) {
|
||||
showSnackbar(view, item.getAttrName());
|
||||
return;
|
||||
}
|
||||
|
||||
int prevSelectedPosition = getItemPosition(getSelectedAppearanceItem());
|
||||
selectedAppearanceItem = items.get(holder.getAdapterPosition());
|
||||
notifyItemChanged(holder.getAdapterPosition());
|
||||
notifyItemChanged(prevSelectedPosition);
|
||||
|
||||
setGradientScaleType(selectedAppearanceItem);
|
||||
if (getListener() != null) {
|
||||
getListener().onCardPressed(TrackColoringCard.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -179,18 +189,72 @@ public class TrackColoringCard extends BaseCard {
|
|||
private void updateButtonBg(TrackAppearanceViewHolder holder, TrackAppearanceItem item) {
|
||||
GradientDrawable rectContourDrawable = (GradientDrawable) AppCompatResources.getDrawable(app, R.drawable.bg_select_group_button_outline);
|
||||
if (rectContourDrawable != null) {
|
||||
if (getSelectedAppearanceItem() != null && getSelectedAppearanceItem().equals(item)) {
|
||||
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light);
|
||||
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 2), strokeColor);
|
||||
Context ctx = holder.itemView.getContext();
|
||||
boolean itemSelected = getSelectedAppearanceItem() != null && getSelectedAppearanceItem().equals(item);
|
||||
|
||||
int strokeColor;
|
||||
int backgroundColor;
|
||||
int strokeWidth;
|
||||
|
||||
if (itemSelected) {
|
||||
strokeColor = AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary);
|
||||
backgroundColor = 0;
|
||||
strokeWidth = 2;
|
||||
} else if (!item.isActive()) {
|
||||
strokeColor = AndroidUtils.getColorFromAttr(ctx, R.attr.stroked_buttons_and_links_outline);
|
||||
backgroundColor = AndroidUtils.getColorFromAttr(ctx, R.attr.ctx_menu_card_btn);
|
||||
strokeWidth = 2;
|
||||
} else {
|
||||
int strokeColor = ContextCompat.getColor(app, nightMode ? R.color.stroked_buttons_and_links_outline_dark
|
||||
: R.color.stroked_buttons_and_links_outline_light);
|
||||
rectContourDrawable.setStroke(AndroidUtils.dpToPx(app, 1), strokeColor);
|
||||
strokeColor = AndroidUtils.getColorFromAttr(ctx, R.attr.stroked_buttons_and_links_outline);
|
||||
backgroundColor = 0;
|
||||
strokeWidth = 1;
|
||||
}
|
||||
|
||||
rectContourDrawable.mutate();
|
||||
rectContourDrawable.setColor(backgroundColor);
|
||||
rectContourDrawable.setStroke(AndroidUtils.dpToPx(ctx, strokeWidth), strokeColor);
|
||||
holder.button.setImageDrawable(rectContourDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTextAndIconColor(TrackAppearanceViewHolder holder, TrackAppearanceItem item) {
|
||||
Context ctx = holder.itemView.getContext();
|
||||
boolean isSelected = item.getAttrName().equals(getSelectedAppearanceItem().getAttrName());
|
||||
int iconColorId;
|
||||
int textColorId;
|
||||
|
||||
if (isSelected) {
|
||||
iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.default_icon_color);
|
||||
textColorId = AndroidUtils.getColorFromAttr(ctx, android.R.attr.textColor);
|
||||
} else if (!item.isActive()) {
|
||||
iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.default_icon_color);
|
||||
textColorId = AndroidUtils.getColorFromAttr(ctx, android.R.attr.textColorSecondary);
|
||||
} else {
|
||||
iconColorId = AndroidUtils.getColorFromAttr(ctx, R.attr.colorPrimary);
|
||||
textColorId = iconColorId;
|
||||
}
|
||||
|
||||
if (item.getAttrName().equals(SOLID_COLOR)) {
|
||||
iconColorId = trackDrawInfo.getColor();
|
||||
}
|
||||
|
||||
holder.icon.setImageDrawable(app.getUIUtilities().getPaintedIcon(item.getIconId(), iconColorId));
|
||||
holder.title.setTextColor(textColorId);
|
||||
}
|
||||
|
||||
private void showSnackbar(View view, String attrName) {
|
||||
if (view == null || mapActivity == null) {
|
||||
return;
|
||||
}
|
||||
String text = attrName.equals(GradientScaleType.SPEED.getTypeName()) ?
|
||||
app.getString(R.string.track_has_no_speed) : app.getString(R.string.track_has_no_altitude);
|
||||
text += " " + app.getString(R.string.select_another_colorization);
|
||||
Snackbar snackbar = Snackbar.make(view, text, Snackbar.LENGTH_LONG)
|
||||
.setAnchorView(mapActivity.findViewById(R.id.dismiss_button));
|
||||
UiUtilities.setupSnackbar(snackbar, nightMode);
|
||||
snackbar.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return items.size();
|
||||
|
@ -209,10 +273,13 @@ public class TrackColoringCard extends BaseCard {
|
|||
@DrawableRes
|
||||
private int iconId;
|
||||
|
||||
public TrackAppearanceItem(String attrName, String localizedValue, int iconId) {
|
||||
private boolean isActive;
|
||||
|
||||
public TrackAppearanceItem(String attrName, String localizedValue, int iconId, boolean isActive) {
|
||||
this.attrName = attrName;
|
||||
this.localizedValue = localizedValue;
|
||||
this.iconId = iconId;
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
public String getAttrName() {
|
||||
|
@ -226,5 +293,9 @@ public class TrackColoringCard extends BaseCard {
|
|||
public int getIconId() {
|
||||
return iconId;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return isActive;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,9 @@ public class TrackDrawInfo {
|
|||
private String width;
|
||||
private GradientScaleType gradientScaleType;
|
||||
private int color;
|
||||
private int[] speedGradientPalette;
|
||||
private int[] altitudeGradientPalette;
|
||||
private int[] slopeGradientPalette;
|
||||
private int splitType;
|
||||
private double splitInterval;
|
||||
private boolean joinSegments;
|
||||
|
@ -44,8 +47,11 @@ public class TrackDrawInfo {
|
|||
public TrackDrawInfo(@NonNull OsmandApplication app, @NonNull GpxDataItem gpxDataItem, boolean currentRecording) {
|
||||
filePath = gpxDataItem.getFile().getPath();
|
||||
width = gpxDataItem.getWidth();
|
||||
gradientScaleType = gpxDataItem.getGradientScaleType();
|
||||
color = gpxDataItem.getColor();
|
||||
gradientScaleType = gpxDataItem.getGradientScaleType();
|
||||
speedGradientPalette = gpxDataItem.getGradientSpeedPalette();
|
||||
altitudeGradientPalette = gpxDataItem.getGradientAltitudePalette();
|
||||
slopeGradientPalette = gpxDataItem.getGradientSlopePalette();
|
||||
splitType = gpxDataItem.getSplitType();
|
||||
splitInterval = gpxDataItem.getSplitInterval();
|
||||
joinSegments = gpxDataItem.isJoinSegments();
|
||||
|
@ -82,6 +88,40 @@ public class TrackDrawInfo {
|
|||
this.color = color;
|
||||
}
|
||||
|
||||
public int[] getGradientPalette(@NonNull GradientScaleType scaleType) {
|
||||
if (scaleType == GradientScaleType.SPEED) {
|
||||
return speedGradientPalette;
|
||||
} else if (scaleType == GradientScaleType.ALTITUDE) {
|
||||
return altitudeGradientPalette;
|
||||
} else {
|
||||
return slopeGradientPalette;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getSpeedGradientPalette() {
|
||||
return speedGradientPalette;
|
||||
}
|
||||
|
||||
public int[] getAltitudeGradientPalette() {
|
||||
return altitudeGradientPalette;
|
||||
}
|
||||
|
||||
public int[] getSlopeGradientPalette() {
|
||||
return slopeGradientPalette;
|
||||
}
|
||||
|
||||
public void setSpeedGradientPalette(int[] palette) {
|
||||
this.speedGradientPalette = palette;
|
||||
}
|
||||
|
||||
public void setAltitudeGradientPalette(int[] palette) {
|
||||
this.altitudeGradientPalette = palette;
|
||||
}
|
||||
|
||||
public void setSlopeGradientPalette(int[] palette) {
|
||||
this.slopeGradientPalette = palette;
|
||||
}
|
||||
|
||||
public int getSplitType() {
|
||||
return splitType;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package net.osmand.plus.views;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.graphics.Shader;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.WptPt;
|
||||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.plus.views.layers.geometry.GeometryWay;
|
||||
import net.osmand.plus.track.GradientScaleType;
|
||||
import net.osmand.plus.views.layers.geometry.GpxGeometryWay;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
|
@ -25,6 +25,8 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
public class Renderable {
|
||||
|
||||
|
@ -65,6 +67,7 @@ public class Renderable {
|
|||
protected double zoom = -1;
|
||||
protected AsynchronousResampler culler = null; // The currently active resampler
|
||||
protected Paint paint = null; // MUST be set by 'updateLocalPaint' before use
|
||||
protected GradientScaleType scaleType = null;
|
||||
|
||||
protected GpxGeometryWay geometryWay;
|
||||
|
||||
|
@ -85,6 +88,10 @@ public class Renderable {
|
|||
paint.setStrokeWidth(p.getStrokeWidth());
|
||||
}
|
||||
|
||||
public void setGradientScaleType(GradientScaleType type) {
|
||||
this.scaleType = type;
|
||||
}
|
||||
|
||||
public GpxGeometryWay getGeometryWay() {
|
||||
return geometryWay;
|
||||
}
|
||||
|
@ -95,7 +102,20 @@ public class Renderable {
|
|||
|
||||
protected abstract void startCuller(double newZoom);
|
||||
|
||||
protected void drawSingleSegment(double zoom, Paint p, Canvas canvas, RotatedTileBox tileBox) {}
|
||||
protected void drawSingleSegment(double zoom, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
if (points.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateLocalPaint(p);
|
||||
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||
if (scaleType != null) {
|
||||
drawGradient(getPointsForDrawing(), p, canvas, tileBox);
|
||||
} else {
|
||||
drawSolid(getPointsForDrawing(), p, canvas, tileBox);
|
||||
}
|
||||
canvas.rotate(tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||
}
|
||||
|
||||
|
||||
public void drawSegment(double zoom, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
|
@ -124,42 +144,66 @@ public class Renderable {
|
|||
}
|
||||
}
|
||||
|
||||
protected void draw(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
if (pts.size() > 1) {
|
||||
updateLocalPaint(p);
|
||||
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||
QuadRect tileBounds = tileBox.getLatLonBounds();
|
||||
WptPt lastPt = pts.get(0);
|
||||
boolean recalculateLastXY = true;
|
||||
Path path = new Path();
|
||||
for (int i = 1; i < pts.size(); i++) {
|
||||
WptPt pt = pts.get(i);
|
||||
if (Math.min(pt.lon, lastPt.lon) < tileBounds.right && Math.max(pt.lon, lastPt.lon) > tileBounds.left
|
||||
&& Math.min(pt.lat, lastPt.lat) < tileBounds.top && Math.max(pt.lat, lastPt.lat) > tileBounds.bottom) {
|
||||
if (recalculateLastXY) {
|
||||
recalculateLastXY = false;
|
||||
float lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon);
|
||||
float lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon);
|
||||
if (!path.isEmpty()) {
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
path.reset();
|
||||
path.moveTo(lastX, lastY);
|
||||
protected void drawSolid(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
QuadRect tileBounds = tileBox.getLatLonBounds();
|
||||
WptPt lastPt = pts.get(0);
|
||||
boolean recalculateLastXY = true;
|
||||
Path path = new Path();
|
||||
for (int i = 1; i < pts.size(); i++) {
|
||||
WptPt pt = pts.get(i);
|
||||
if (arePointsInsideTile(pt, lastPt, tileBounds)) {
|
||||
if (recalculateLastXY) {
|
||||
recalculateLastXY = false;
|
||||
float lastX = tileBox.getPixXFromLatLon(lastPt.lat, lastPt.lon);
|
||||
float lastY = tileBox.getPixYFromLatLon(lastPt.lat, lastPt.lon);
|
||||
if (!path.isEmpty()) {
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
float x = tileBox.getPixXFromLatLon(pt.lat, pt.lon);
|
||||
float y = tileBox.getPixYFromLatLon(pt.lat, pt.lon);
|
||||
path.lineTo(x, y);
|
||||
} else {
|
||||
recalculateLastXY = true;
|
||||
path.reset();
|
||||
path.moveTo(lastX, lastY);
|
||||
}
|
||||
lastPt = pt;
|
||||
float x = tileBox.getPixXFromLatLon(pt.lat, pt.lon);
|
||||
float y = tileBox.getPixYFromLatLon(pt.lat, pt.lon);
|
||||
path.lineTo(x, y);
|
||||
} else {
|
||||
recalculateLastXY = true;
|
||||
}
|
||||
if (!path.isEmpty()) {
|
||||
lastPt = pt;
|
||||
}
|
||||
if (!path.isEmpty()) {
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawGradient(List<WptPt> pts, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
QuadRect tileBounds = tileBox.getLatLonBounds();
|
||||
Path path = new Path();
|
||||
Paint paint = new Paint(this.paint);
|
||||
WptPt prevPt = pts.get(0);
|
||||
for (int i = 1; i < pts.size(); i++) {
|
||||
WptPt currentPt = pts.get(i);
|
||||
if (arePointsInsideTile(currentPt, prevPt, tileBounds)) {
|
||||
float startX = tileBox.getPixXFromLatLon(prevPt.lat, prevPt.lon);
|
||||
float startY = tileBox.getPixYFromLatLon(prevPt.lat, prevPt.lon);
|
||||
float endX = tileBox.getPixXFromLatLon(currentPt.lat, currentPt.lon);
|
||||
float endY = tileBox.getPixYFromLatLon(currentPt.lat, currentPt.lon);
|
||||
int prevColor = prevPt.getColor(scaleType.toColorizationType());
|
||||
int currentColor = currentPt.getColor(scaleType.toColorizationType());
|
||||
LinearGradient gradient = new LinearGradient(startX, startY, endX, endY, prevColor, currentColor, Shader.TileMode.CLAMP);
|
||||
paint.setShader(gradient);
|
||||
path.reset();
|
||||
path.moveTo(startX, startY);
|
||||
path.lineTo(endX, endY);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
canvas.rotate(tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
|
||||
prevPt = currentPt;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean arePointsInsideTile(WptPt first, WptPt second, QuadRect tileBounds) {
|
||||
return Math.min(first.lon, second.lon) < tileBounds.right && Math.max(first.lon, second.lon) > tileBounds.left
|
||||
&& Math.min(first.lat, second.lat) < tileBounds.top && Math.max(first.lat, second.lat) > tileBounds.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StandardTrack extends RenderableSegment {
|
||||
|
@ -191,10 +235,6 @@ public class Renderable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void drawSingleSegment(double zoom, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
draw(culled.isEmpty() ? points : culled, p, canvas, tileBox);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CurrentTrack extends RenderableSegment {
|
||||
|
@ -213,9 +253,5 @@ public class Renderable {
|
|||
}
|
||||
|
||||
@Override protected void startCuller(double newZoom) {}
|
||||
|
||||
@Override public void drawSingleSegment(double zoom, Paint p, Canvas canvas, RotatedTileBox tileBox) {
|
||||
draw(points, p, canvas, tileBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ import net.osmand.plus.render.OsmandRenderer;
|
|||
import net.osmand.plus.render.OsmandRenderer.RenderingContext;
|
||||
import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu;
|
||||
import net.osmand.plus.settings.backend.CommonPreference;
|
||||
import net.osmand.plus.track.GradientScaleType;
|
||||
import net.osmand.plus.track.SaveGpxAsyncTask;
|
||||
import net.osmand.plus.track.TrackDrawInfo;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
|
@ -66,6 +67,7 @@ import net.osmand.plus.views.layers.geometry.GpxGeometryWayContext;
|
|||
import net.osmand.render.RenderingRuleProperty;
|
||||
import net.osmand.render.RenderingRuleSearchRequest;
|
||||
import net.osmand.render.RenderingRulesStorage;
|
||||
import net.osmand.router.RouteColorize;
|
||||
import net.osmand.util.Algorithms;
|
||||
import net.osmand.util.MapUtils;
|
||||
|
||||
|
@ -142,6 +144,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
private CommonPreference<String> defaultTrackWidthPref;
|
||||
|
||||
private CommonPreference<Integer> currentTrackColorPref;
|
||||
private CommonPreference<GradientScaleType> currentTrackScaleType;
|
||||
private CommonPreference<String> currentTrackSpeedGradientPalette;
|
||||
private CommonPreference<String> currentTrackAltitudeGradientPalette;
|
||||
private CommonPreference<String> currentTrackSlopeGradientPalette;
|
||||
private CommonPreference<String> currentTrackWidthPref;
|
||||
private CommonPreference<Boolean> currentTrackShowArrowsPref;
|
||||
private CommonPreference<Boolean> currentTrackShowStartFinishPref;
|
||||
|
@ -155,6 +161,10 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
osmandRenderer = view.getApplication().getResourceManager().getRenderer().getRenderer();
|
||||
|
||||
currentTrackColorPref = view.getSettings().CURRENT_TRACK_COLOR;
|
||||
currentTrackScaleType = view.getSettings().CURRENT_TRACK_COLORIZATION;
|
||||
currentTrackSpeedGradientPalette = view.getSettings().CURRENT_TRACK_SPEED_GRADIENT_PALETTE;
|
||||
currentTrackAltitudeGradientPalette = view.getSettings().CURRENT_TRACK_ALTITUDE_GRADIENT_PALETTE;
|
||||
currentTrackSlopeGradientPalette = view.getSettings().CURRENT_TRACK_SLOPE_GRADIENT_PALETTE;
|
||||
currentTrackWidthPref = view.getSettings().CURRENT_TRACK_WIDTH;
|
||||
currentTrackShowArrowsPref = view.getSettings().CURRENT_TRACK_SHOW_ARROWS;
|
||||
currentTrackShowStartFinishPref = view.getSettings().CURRENT_TRACK_SHOW_START_FINISH;
|
||||
|
@ -661,10 +671,22 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
|
||||
private void drawSelectedFileSegments(SelectedGpxFile selectedGpxFile, boolean currentTrack, Canvas canvas,
|
||||
RotatedTileBox tileBox, DrawSettings settings) {
|
||||
GPXFile gpxFile = selectedGpxFile.getGpxFile();
|
||||
List<TrkSegment> segments = selectedGpxFile.getPointsToDisplay();
|
||||
GradientScaleType scaleType = getGradientScaleType(gpxFile);
|
||||
List<RouteColorize.RouteColorizationPoint> colorsOfPoints = null;
|
||||
if (scaleType != null) {
|
||||
RouteColorize colorize = new RouteColorize(view.getZoom(), gpxFile, scaleType.toColorizationType());
|
||||
colorize.setPalette(getColorizationPalette(gpxFile, scaleType));
|
||||
colorsOfPoints = colorize.getResult(false);
|
||||
}
|
||||
int startIdx = 0;
|
||||
for (TrkSegment ts : segments) {
|
||||
String width = getTrackWidthName(selectedGpxFile.getGpxFile(), defaultTrackWidthPref.get());
|
||||
int color = getTrackColor(selectedGpxFile.getGpxFile(), ts.getColor(cachedColor));
|
||||
String width = getTrackWidthName(gpxFile, defaultTrackWidthPref.get());
|
||||
int color = getTrackColor(gpxFile, ts.getColor(cachedColor));
|
||||
if (colorsOfPoints != null) {
|
||||
startIdx = setColorsToPoints(ts, colorsOfPoints, scaleType, startIdx);
|
||||
}
|
||||
if (ts.renderer == null && !ts.points.isEmpty()) {
|
||||
Renderable.RenderableSegment renderer;
|
||||
if (currentTrack) {
|
||||
|
@ -677,11 +699,43 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
}
|
||||
updatePaints(color, width, selectedGpxFile.isRoutePoints(), currentTrack, settings, tileBox);
|
||||
if (ts.renderer instanceof Renderable.RenderableSegment) {
|
||||
((Renderable.RenderableSegment) ts.renderer).drawSegment(view.getZoom(), paint, canvas, tileBox);
|
||||
Renderable.RenderableSegment renderableSegment = (Renderable.RenderableSegment) ts.renderer;
|
||||
renderableSegment.setGradientScaleType(scaleType);
|
||||
renderableSegment.drawSegment(view.getZoom(), paint, canvas, tileBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int setColorsToPoints(TrkSegment segment, List<RouteColorize.RouteColorizationPoint> colors, GradientScaleType scaleType, int startIdx) {
|
||||
int pointsSize = segment.points.size();
|
||||
RouteColorize.RouteColorizationPoint startColor = colors.get(startIdx);
|
||||
RouteColorize.RouteColorizationPoint endColor = colors.get(startIdx + pointsSize - 1);
|
||||
WptPt firstPoint = segment.points.get(0);
|
||||
WptPt lastPoint = segment.points.get(pointsSize - 1);
|
||||
while (!compareCoordinates(firstPoint, startColor) && compareCoordinates(lastPoint, endColor)) {
|
||||
startIdx++;
|
||||
startColor = colors.get(startIdx);
|
||||
endColor = colors.get(startIdx + pointsSize - 1);
|
||||
}
|
||||
|
||||
for (int i = startIdx; i < startIdx + pointsSize; i++) {
|
||||
WptPt currentPoint = segment.points.get(i - startIdx);
|
||||
int currentColor = colors.get(i).color;
|
||||
if (scaleType == GradientScaleType.SPEED) {
|
||||
currentPoint.speedColor = currentColor;
|
||||
} else if (scaleType == GradientScaleType.ALTITUDE) {
|
||||
currentPoint.altitudeColor = currentColor;
|
||||
} else {
|
||||
currentPoint.slopeColor = currentColor;
|
||||
}
|
||||
}
|
||||
return startIdx;
|
||||
}
|
||||
|
||||
private boolean compareCoordinates(WptPt left, RouteColorize.RouteColorizationPoint right) {
|
||||
return left.lat == right.lat && left.lon == right.lon;
|
||||
}
|
||||
|
||||
private float getTrackWidth(String width, float defaultTrackWidth) {
|
||||
Float trackWidth = cachedTrackWidth.get(width);
|
||||
return trackWidth != null ? trackWidth : defaultTrackWidth;
|
||||
|
@ -702,6 +756,47 @@ public class GPXLayer extends OsmandMapLayer implements IContextMenuProvider, IM
|
|||
return color != 0 ? color : defaultColor;
|
||||
}
|
||||
|
||||
private GradientScaleType getGradientScaleType(GPXFile gpxFile) {
|
||||
if (hasTrackDrawInfoForTrack(gpxFile)) {
|
||||
return trackDrawInfo.getGradientScaleType();
|
||||
} else if (gpxFile.showCurrentTrack) {
|
||||
return currentTrackScaleType.get();
|
||||
} else {
|
||||
GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path));
|
||||
if (dataItem != null && dataItem.getGradientScaleType() != null) {
|
||||
return dataItem.getGradientScaleType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private int[] getColorizationPalette(GPXFile gpxFile, GradientScaleType scaleType) {
|
||||
if (hasTrackDrawInfoForTrack(gpxFile)) {
|
||||
return trackDrawInfo.getGradientPalette(scaleType);
|
||||
} else if (gpxFile.showCurrentTrack) {
|
||||
String palette;
|
||||
if (scaleType == GradientScaleType.SPEED) {
|
||||
palette = currentTrackSpeedGradientPalette.get();
|
||||
} else if (scaleType == GradientScaleType.ALTITUDE) {
|
||||
palette = currentTrackAltitudeGradientPalette.get();
|
||||
} else {
|
||||
palette = currentTrackSlopeGradientPalette.get();
|
||||
}
|
||||
return Algorithms.stringToArray(palette);
|
||||
}
|
||||
GpxDataItem dataItem = gpxDbHelper.getItem(new File(gpxFile.path));
|
||||
if (dataItem == null) {
|
||||
return RouteColorize.colors;
|
||||
}
|
||||
if (scaleType == GradientScaleType.SPEED) {
|
||||
return dataItem.getGradientSpeedPalette();
|
||||
} else if (scaleType == GradientScaleType.ALTITUDE) {
|
||||
return dataItem.getGradientAltitudePalette();
|
||||
} else {
|
||||
return dataItem.getGradientSlopePalette();
|
||||
}
|
||||
}
|
||||
|
||||
private String getTrackWidthName(GPXFile gpxFile, String defaultWidth) {
|
||||
String width = null;
|
||||
if (hasTrackDrawInfoForTrack(gpxFile)) {
|
||||
|
|
Loading…
Reference in a new issue