From 824aab5fbcac29c7a359aa1a42ce37771b3155ee Mon Sep 17 00:00:00 2001 From: Chumva Date: Fri, 1 Mar 2019 13:35:59 +0200 Subject: [PATCH 1/3] Route details initial commit --- .../net/osmand/router/RouteStatistics.java | 320 ++- .../osmand/router/TransportRoutePlanner.java | 4 + .../res/drawable/border_round_solid_light.xml | 9 + .../border_round_solid_light_small.xml | 9 + OsmAnd/res/drawable/walk_route_item_light.xml | 11 + OsmAnd/res/layout/route_info_card.xml | 67 + OsmAnd/res/layout/route_info_header.xml | 824 +++--- OsmAnd/res/layout/route_info_layout.xml | 341 +-- OsmAnd/res/layout/route_info_stat_item.xml | 29 - OsmAnd/res/values/sizes.xml | 1 + OsmAnd/res/values/strings.xml | 16 +- OsmAnd/src/net/osmand/AndroidUtils.java | 13 +- .../ShowRouteInfoDialogFragment.java | 2243 ++++++++++++++--- .../dashboard/DashNavigationFragment.java | 7 +- .../net/osmand/plus/helpers/GpxUiHelper.java | 127 +- .../MapContextMenuFragment.java | 12 +- .../plus/mapcontextmenu/MenuBuilder.java | 28 +- .../ChooseRouteFragment.java | 26 +- .../MapRouteInfoMenu.java | 2 +- .../WaypointsFragment.java | 6 +- .../routepreparationmenu/cards/BaseCard.java | 4 + .../cards/PublicTransportCard.java | 36 +- .../cards/RouteInfoCard.java | 116 + .../cards/RouteStatisticCard.java | 221 ++ .../cards/SimpleRouteCard.java | 34 +- .../plus/routing/TransportRoutingHelper.java | 2 +- .../plus/transport/TransportStopRoute.java | 11 + 27 files changed, 3166 insertions(+), 1353 deletions(-) create mode 100644 OsmAnd/res/drawable/border_round_solid_light.xml create mode 100644 OsmAnd/res/drawable/border_round_solid_light_small.xml create mode 100644 OsmAnd/res/drawable/walk_route_item_light.xml create mode 100644 OsmAnd/res/layout/route_info_card.xml delete mode 100644 OsmAnd/res/layout/route_info_stat_item.xml create mode 100644 OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java create mode 100644 OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java index 6435e5a45d..9876e46ed5 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatistics.java @@ -1,6 +1,12 @@ package net.osmand.router; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; public class RouteStatistics { @@ -39,8 +45,11 @@ public class RouteStatistics { private final List route; - public RouteStatisticComputer(List route) { + private final StatisticType type; + + public RouteStatisticComputer(List route, StatisticType type) { this.route = route; + this.type = type; } protected Map> makePartition(List> routeAttributes) { @@ -49,7 +58,7 @@ public class RouteStatistics { E key = attribute.getAttribute(); RouteSegmentAttribute pattr = partition.get(key); if (pattr == null) { - pattr = new RouteSegmentAttribute<>(attribute.getIndex(), attribute.getAttribute(), attribute.getColorAttrName()); + pattr = new RouteSegmentAttribute<>(attribute); partition.put(key, pattr); } pattr.incrementDistanceBy(attribute.getDistance()); @@ -79,8 +88,9 @@ public class RouteStatistics { index++; } if (index >= routes.size()) { - String colorAttrName = determineColor(current); - routes.add(new RouteSegmentAttribute<>(index, current, colorAttrName)); + String colorAttrName = getColorAttrName(current); + String colorName = getColorName(current); + routes.add(new RouteSegmentAttribute<>(index, current, colorAttrName, colorName)); } RouteSegmentAttribute surface = routes.get(index); surface.incrementDistanceBy(segment.getDistance()); @@ -93,19 +103,20 @@ public class RouteStatistics { List> routeAttributes = processRoute(); Map> partition = makePartition(routeAttributes); float totalDistance = computeTotalDistance(routeAttributes); - return new Statistics<>(routeAttributes, partition, totalDistance); + return new Statistics<>(routeAttributes, partition, totalDistance, type); } public abstract E getAttribute(RouteSegmentResult segment); - public abstract String determineColor(E attribute); + public abstract String getColorAttrName(E attribute); + public abstract String getColorName(E attribute); } private static class RouteSurfaceStatisticComputer extends RouteStatisticComputer { public RouteSurfaceStatisticComputer(List route) { - super(route); + super(route, StatisticType.SURFACE); } @Override @@ -122,22 +133,28 @@ public class RouteStatistics { return RoadSurface.UNDEFINED.name().toLowerCase(); } - @Override - public String determineColor(String attribute) { - RoadSurface roadSurface = RoadSurface.valueOf(attribute.toUpperCase()); - return roadSurface.getColorAttrName(); - } + @Override + public String getColorAttrName(String attribute) { + RoadSurface roadSurface = RoadSurface.valueOf(attribute.toUpperCase()); + return roadSurface.getColorAttrName(); + } + + @Override + public String getColorName(String attribute) { + RoadSurface roadSurface = RoadSurface.valueOf(attribute.toUpperCase()); + return roadSurface.getColorName(); + } } private static class RouteSmoothnessStatisticComputer extends RouteStatisticComputer { public RouteSmoothnessStatisticComputer(List route) { - super(route); + super(route, StatisticType.SMOOTHNESS); } @Override public String getAttribute(RouteSegmentResult segment) { - String segmentSmoothness = segment.getSurface(); + String segmentSmoothness = segment.getSmoothness(); if (segmentSmoothness == null) { return RoadSmoothness.UNDEFINED.name().toLowerCase(); } @@ -149,18 +166,23 @@ public class RouteStatistics { return RoadSmoothness.UNDEFINED.name().toLowerCase(); } - @Override - public String determineColor(String attribute) { - RoadSmoothness roadSmoothness = RoadSmoothness.valueOf(attribute.toUpperCase()); - return roadSmoothness.getColorAttrName(); - } - } + @Override + public String getColorAttrName(String attribute) { + RoadSmoothness roadSmoothness = RoadSmoothness.valueOf(attribute.toUpperCase()); + return roadSmoothness.getColorAttrName(); + } + @Override + public String getColorName(String attribute) { + RoadSmoothness roadSmoothness = RoadSmoothness.valueOf(attribute.toUpperCase()); + return roadSmoothness.getColorName(); + } + } private static class RouteClassStatisticComputer extends RouteStatisticComputer { public RouteClassStatisticComputer(List route) { - super(route); + super(route, StatisticType.CLASS); } @Override @@ -177,13 +199,18 @@ public class RouteStatistics { return RoadClass.UNDEFINED.name().toLowerCase(); } - @Override - public String determineColor(String attribute) { - RoadClass roadClass = RoadClass.valueOf(attribute.toUpperCase()); - return roadClass.getColorAttrName(); - } - } + @Override + public String getColorAttrName(String attribute) { + RoadClass roadClass = RoadClass.valueOf(attribute.toUpperCase()); + return roadClass.getColorAttrName(); + } + @Override + public String getColorName(String attribute) { + RoadClass roadClass = RoadClass.valueOf(attribute.toUpperCase()); + return roadClass.getColorName(); + } + } private static class RouteSteepnessStatisticComputer extends RouteStatisticComputer { @@ -193,7 +220,7 @@ public class RouteStatistics { private final List inclines; public RouteSteepnessStatisticComputer(List inclines) { - super(null); + super(null, StatisticType.STEEPNESS); this.inclines = inclines; } @@ -209,8 +236,9 @@ public class RouteStatistics { index++; } if (index >= routeInclines.size()) { - String colorAttrName = determineColor(current); - RouteSegmentAttribute attribute = new RouteSegmentAttribute<>(index, current, colorAttrName); + String colorAttrName = getColorAttrName(current); + String colorName = getColorName(current); + RouteSegmentAttribute attribute = new RouteSegmentAttribute<>(index, current, colorAttrName, colorName); if (prevIncline != null) { attribute.setInitDistance(prevIncline.getDistance()); } @@ -233,25 +261,38 @@ public class RouteStatistics { } @Override - public String determineColor(Boundaries attribute) { + public String getColorAttrName(Boundaries attribute) { return attribute.getLowerBoundary() >= 0 ? POSITIVE_INCLINE_COLOR_ATTR_NAME : NEGATIVE_INCLINE_COLOR_ATTR_NAME; } - } + @Override + public String getColorName(Boundaries attribute) { + return null; + } + } public static class RouteSegmentAttribute { private final int index; private final E attribute; private final String colorAttrName; + private final String colorName; private float distance; private float initDistance; - public RouteSegmentAttribute(int index, E attribute, String colorAttrName) { + public RouteSegmentAttribute(int index, E attribute, String colorAttrName, String colorName) { this.index = index; this.attribute = attribute; this.colorAttrName = colorAttrName; + this.colorName = colorName; + } + + public RouteSegmentAttribute(RouteSegmentAttribute segmentAttribute) { + this.index = segmentAttribute.getIndex(); + this.attribute = segmentAttribute.getAttribute(); + this.colorAttrName = segmentAttribute.getColorAttrName(); + this.colorName = segmentAttribute.getColorName(); } public int getIndex() { @@ -282,6 +323,10 @@ public class RouteStatistics { return colorAttrName; } + public String getColorName() { + return colorName; + } + @Override public String toString() { return "RouteSegmentAttribute{" + @@ -407,13 +452,15 @@ public class RouteStatistics { private final List> elements; private final Map> partition; private final float totalDistance; + private final StatisticType type; private Statistics(List> elements, Map> partition, - float totalDistance) { + float totalDistance, StatisticType type) { this.elements = elements; this.partition = partition; this.totalDistance = totalDistance; + this.type = type; } public float getTotalDistance() { @@ -427,104 +474,133 @@ public class RouteStatistics { public Map> getPartition() { return partition; } - } - public enum RoadClass { - UNDEFINED("whitewaterSectionGrade0Color", "undefined"), - MOTORWAY("motorwayRoadColor", "motorway", "motorway_link"), - STATE_ROAD("trunkRoadColor" , "trunk", "trunk_link", "primary", "primary_link"), - ROAD("secondaryRoadColor", "secondary", "secondary_link", "tertiary", "tertiary_link", "unclassified"), - STREET("residentialRoadColor" ,"residential", "living_street"), - SERVICE("serviceRoadColor", "service"), - TRACK("trackColor", "track", "road"), - FOOTWAY("footwayColor", "footway"), - PATH("pathColor", "path"), - CYCLE_WAY("cyclewayColor", "cycleway"); - - final Set roadClasses = new TreeSet<>(); - final String colorAttrName; - - RoadClass(String colorAttrName, String... classes) { - roadClasses.addAll(Arrays.asList(classes)); - this.colorAttrName = colorAttrName; - } - - boolean contains(String roadClass) { - return roadClasses.contains(roadClass); - } - - String getColorAttrName() { - return colorAttrName; + public StatisticType getStatisticType() { + return type; } } - public enum RoadSurface { - UNDEFINED("whitewaterSectionGrade0Color", "undefined"), - PAVED("motorwayRoadColor", "paved"), - UNPAVED("motorwayRoadShadowColor", "unpaved"), - ASPHALT("trunkRoadColor", "asphalt"), - CONCRETE("primaryRoadColor", "concrete"), - COMPACTED("secondaryRoadColor", "compacted"), - GRAVEL("tertiaryRoadColor", "gravel"), - FINE_GRAVEL("residentialRoadColor", "fine_gravel"), - PAVING_STONES("serviceRoadColor", "paving_stones"), - SETT("roadRoadColor", "sett"), - COBBLESTONE("pedestrianRoadColor", "cobblestone"), - PEBBLESTONE("racewayColor", "pebblestone"), - STONE("trackColor", "stone"), - METAL("footwayColor", "metal"), - GROUND("pathColor", "ground", "mud"), - WOOD("cycleRouteColor", "wood"), - GRASS_PAVER("osmcBlackColor", "grass_paver"), - GRASS("osmcBlueColor", "grass"), - SAND("osmcGreenColor", "sand"), - SALT("osmcRedColor", "salt"), - SNOW("osmcYellowColor", "snow"), - ICE("osmcOrangeColor", "ice"), - CLAY("osmcBrownColor", "clay"); + public enum RoadClass { + MOTORWAY(null, "#ffa200", "motorway", "motorway_link"), + STATE_ROAD(null, "#ffae1d", "trunk", "trunk_link", "primary", "primary_link"), + ROAD(null, "#ffb939", "secondary", "secondary_link", "tertiary", "tertiary_link", "unclassified"), + STREET(null, "#ffc554", "residential", "living_street"), + SERVICE(null, "#ffd070", "service"), + TRACK(null, "#ffdb8a", "track", "road"), + FOOTWAY(null, "#ffe7a7", "footway"), + CYCLE_WAY(null, "#fff4c6", "cycleway"), + PATH(null, "#fffadd", "path"), + UNDEFINED(null, "#DCDBDD", "undefined"); - final Set surfaces = new TreeSet<>(); - final String colorAttrName; + final Set roadClasses = new TreeSet<>(); + final String colorAttrName; + final String colorName; - RoadSurface(String colorAttrName, String... surfaces) { - this.surfaces.addAll(Arrays.asList(surfaces)); - this.colorAttrName = colorAttrName; - } + RoadClass(String colorAttrName, String colorName, String... classes) { + roadClasses.addAll(Arrays.asList(classes)); + this.colorAttrName = colorAttrName; + this.colorName = colorName; + } - boolean contains(String surface) { - return surfaces.contains(surface); - } + boolean contains(String roadClass) { + return roadClasses.contains(roadClass); + } - public String getColorAttrName() { - return this.colorAttrName; - } - } + String getColorAttrName() { + return colorAttrName; + } - public enum RoadSmoothness { - UNDEFINED("redColor", "undefined"), - EXCELLENT("orangeColor", "excellent"), - GOOD("brownColor", "good"), - INTERMEDIATE("darkyellowColor", "intermediate"), - BAD("yellowColor", "bad"), - VERY_BAD("lightgreenColor", "very_bad"), - HORRIBLE("greenColor", "horrible"), - VERY_HORRIBLE("lightblueColor", "very_horrible"), - IMPASSABLE("blueColor", "impassable"); + public String getColorName() { + return this.colorName; + } + } - final Set surfaces = new TreeSet<>(); - final String colorAttrName; + public enum RoadSurface { + UNDEFINED(null, "#e8e8e8", "undefined"), + PAVED(null, "#a7cdf8", "paved"), + UNPAVED(null, "#cc9900", "unpaved"), + ASPHALT(null, "#6f687e", "asphalt"), + CONCRETE(null, "#a7cdf8", "concrete"), + COMPACTED(null, "#cbcbe8", "compacted"), + GRAVEL(null, "#cbcbe8", "gravel"), + FINE_GRAVEL(null, "#cbcbe8", "fine_gravel"), + PAVING_STONES(null, "#a7cdf8", "paving_stones"), + SETT(null, "#a7cdf8", "sett"), + COBBLESTONE(null, "#a7cdf8", "cobblestone"), + PEBBLESTONE("#a7cdf8", "pebblestone"), + STONE(null, "#a7cdf8", "stone"), + METAL(null, "#a7cdf8", "metal"), + GROUND(null, "#cc9900", "ground", "mud"), + WOOD(null, "#a7cdf8", "wood"), + GRASS_PAVER(null, "#a7bef8", "grass_paver"), + GRASS(null, "#1fbe1f", "grass"), + SAND(null, "#ffd700", "sand"), + SALT(null, "#7eded8", "salt"), + SNOW(null, "#9feeef", "snow"), + ICE(null, "#9feeef", "ice"), + CLAY(null, "#cc9900", "clay"); - RoadSmoothness(String colorAttrName, String... surfaces) { - this.surfaces.addAll(Arrays.asList(surfaces)); - this.colorAttrName = colorAttrName; - } + final Set surfaces = new TreeSet<>(); + final String colorAttrName; + final String colorName; - boolean contains(String surface) { - return surfaces.contains(surface); - } + RoadSurface(String colorAttrName, String colorName, String... surfaces) { + this.surfaces.addAll(Arrays.asList(surfaces)); + this.colorAttrName = colorAttrName; + this.colorName = colorName; + } - public String getColorAttrName() { - return this.colorAttrName; - } - } + boolean contains(String surface) { + return surfaces.contains(surface); + } + + public String getColorAttrName() { + return this.colorAttrName; + } + + public String getColorName() { + return this.colorName; + } + } + + public enum RoadSmoothness { + UNDEFINED("redColor", null, "undefined"), + EXCELLENT("orangeColor", null, "excellent"), + GOOD("brownColor", null, "good"), + INTERMEDIATE("darkyellowColor", null, "intermediate"), + BAD("yellowColor", null, "bad"), + VERY_BAD("lightgreenColor", null, "very_bad"), + HORRIBLE("greenColor", null, "horrible"), + VERY_HORRIBLE("lightblueColor", null, "very_horrible"), + IMPASSABLE("blueColor", null, "impassable"); + + final Set surfaces = new TreeSet<>(); + final String colorAttrName; + final String colorName; + + RoadSmoothness(String colorAttrName, String colorName, String... surfaces) { + this.surfaces.addAll(Arrays.asList(surfaces)); + this.colorAttrName = colorAttrName; + this.colorName = colorName; + } + + boolean contains(String surface) { + return surfaces.contains(surface); + } + + public String getColorAttrName() { + return this.colorAttrName; + } + + public String getColorName() { + return this.colorName; + } + } + + public enum StatisticType { + CLASS, + SURFACE, + SMOOTHNESS, + STEEPNESS + } } diff --git a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java index ea844999eb..ede95eb8aa 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/TransportRoutePlanner.java @@ -301,6 +301,10 @@ public class TransportRoutePlanner { return route.getForwardStops().get(end); } + public List getTravelStops() { + return route.getForwardStops().subList(start, end); + } + public List getNodes() { List nodes = new ArrayList<>(); List ways = getGeometry(); diff --git a/OsmAnd/res/drawable/border_round_solid_light.xml b/OsmAnd/res/drawable/border_round_solid_light.xml new file mode 100644 index 0000000000..513b7f8915 --- /dev/null +++ b/OsmAnd/res/drawable/border_round_solid_light.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/border_round_solid_light_small.xml b/OsmAnd/res/drawable/border_round_solid_light_small.xml new file mode 100644 index 0000000000..6bb724f32e --- /dev/null +++ b/OsmAnd/res/drawable/border_round_solid_light_small.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/walk_route_item_light.xml b/OsmAnd/res/drawable/walk_route_item_light.xml new file mode 100644 index 0000000000..a468f5311c --- /dev/null +++ b/OsmAnd/res/drawable/walk_route_item_light.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/route_info_card.xml b/OsmAnd/res/layout/route_info_card.xml new file mode 100644 index 0000000000..36ffde51ba --- /dev/null +++ b/OsmAnd/res/layout/route_info_card.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/route_info_header.xml b/OsmAnd/res/layout/route_info_header.xml index 5927fb1f53..e10e4a6ecd 100644 --- a/OsmAnd/res/layout/route_info_header.xml +++ b/OsmAnd/res/layout/route_info_header.xml @@ -1,474 +1,354 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 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"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/route_info_layout.xml b/OsmAnd/res/layout/route_info_layout.xml index 822b7c87fd..73d4cc1e51 100644 --- a/OsmAnd/res/layout/route_info_layout.xml +++ b/OsmAnd/res/layout/route_info_layout.xml @@ -1,237 +1,166 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/OsmAnd/res/layout/route_info_stat_item.xml b/OsmAnd/res/layout/route_info_stat_item.xml deleted file mode 100644 index 2bb24fe6aa..0000000000 --- a/OsmAnd/res/layout/route_info_stat_item.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 310520c7a1..517c973bed 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -280,6 +280,7 @@ 60dp 56dp 54dp + 8dp 52dp diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index f9e58c78c6..498affe665 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -10,6 +10,11 @@ - For wording and consistency, please note https://osmand.net/help-online?id=technical-articles#Creating_a_Consistent_User_Experience Thx - Hardy --> + By %1$s + Step by step + Road types + Exit at + Sit on the stop Swap Show more Tracks on the map @@ -26,11 +31,10 @@ Add destination Add intermediate Add starting point - Intermediate point: %1$s - Waypoints: %1$s - Transfers: %1$s - On foot: %1$s - Way: %1$s + Intermediate point + Transfers + On foot + Way Points of interest (POI) Calculating route… Public transport @@ -39,7 +43,7 @@ Simulate navigation Choose track file to follow Voice announcements - Intermediate destinations: %1$s + Intermediate destinations Arrive at %1$s Subscriptions By OsmAnd diff --git a/OsmAnd/src/net/osmand/AndroidUtils.java b/OsmAnd/src/net/osmand/AndroidUtils.java index 9f6593f8d3..af578f1538 100644 --- a/OsmAnd/src/net/osmand/AndroidUtils.java +++ b/OsmAnd/src/net/osmand/AndroidUtils.java @@ -41,15 +41,13 @@ import android.view.View; import android.view.ViewParent; import android.view.inputmethod.InputMethodManager; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.TextView; import net.osmand.plus.R; import net.osmand.plus.download.DownloadActivity; -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -320,6 +318,15 @@ public class AndroidUtils { } } + public static void updateImageButton(Context ctx, ImageButton button, int iconLightId, int iconDarkId, int bgLightId, int bgDarkId, boolean night) { + button.setImageDrawable(ctx.getResources().getDrawable(night ? iconDarkId : iconLightId)); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { + button.setBackground(ctx.getResources().getDrawable(night ? bgDarkId : bgLightId, ctx.getTheme())); + } else { + button.setBackgroundDrawable(ctx.getResources().getDrawable(night ? bgDarkId : bgLightId)); + } + } + public static void setDashButtonBackground(Context ctx, View view, boolean night) { setBackground(ctx, view, night, R.drawable.dashboard_button_light, R.drawable.dashboard_button_dark); } diff --git a/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java b/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java index 32c4ca8c1e..2cc5efb42d 100644 --- a/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java @@ -1,80 +1,104 @@ package net.osmand.plus.activities; +import android.Manifest; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.annotation.TargetApi; +import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.v4.app.DialogFragment; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; +import android.support.v4.content.ContextCompat; import android.support.v7.widget.Toolbar; +import android.text.ClipboardManager; import android.text.Html; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.util.TypedValue; +import android.view.GestureDetector; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.VelocityTracker; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; +import android.view.ViewParent; +import android.view.ViewTreeObserver; +import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.ListView; +import android.widget.LinearLayout; +import android.widget.OverScroller; import android.widget.TextView; +import android.widget.Toast; -import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarDataSet; -import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.listener.ChartTouchListener; -import com.github.mikephil.charting.listener.OnChartGestureListener; import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.GPXUtilities.TrkSegment; +import net.osmand.GPXUtilities.WptPt; import net.osmand.Location; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; -import net.osmand.GPXUtilities; -import net.osmand.GPXUtilities.GPXFile; -import net.osmand.GPXUtilities.GPXTrackAnalysis; -import net.osmand.GPXUtilities.TrkSegment; -import net.osmand.GPXUtilities.WptPt; +import net.osmand.data.TransportRoute; +import net.osmand.data.TransportStop; +import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; -import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; +import net.osmand.plus.LockableScrollView; import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; +import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.UiUtilities; +import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.helpers.FontCache; import net.osmand.plus.helpers.GpxUiHelper; -import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetAxisType; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; -import net.osmand.plus.helpers.GpxUiHelper.OrderedLineDataSet; +import net.osmand.plus.mapcontextmenu.InterceptorLinearLayout; +import net.osmand.plus.mapcontextmenu.MenuBuilder; +import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.routepreparationmenu.cards.PublicTransportCard; +import net.osmand.plus.routepreparationmenu.cards.RouteInfoCard; +import net.osmand.plus.routepreparationmenu.cards.RouteStatisticCard; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.transport.TransportStopRoute; +import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.TurnPathHelper; -import net.osmand.render.RenderingRuleSearchRequest; -import net.osmand.render.RenderingRulesStorage; +import net.osmand.plus.views.controls.HorizontalSwipeConfirm; +import net.osmand.plus.widgets.TextViewEx; +import net.osmand.plus.widgets.style.CustomTypefaceSpan; import net.osmand.router.RouteSegmentResult; import net.osmand.router.RouteStatistics; import net.osmand.router.RouteStatistics.Incline; -import net.osmand.router.RouteStatistics.RouteSegmentAttribute; -import net.osmand.router.RouteStatistics.Statistics; +import net.osmand.router.TransportRoutePlanner; import net.osmand.util.Algorithms; import java.io.File; @@ -86,47 +110,76 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; -import java.util.Map; +import static net.osmand.plus.mapcontextmenu.MapContextMenuFragment.CURRENT_Y_UNDEFINED; +import static net.osmand.plus.mapcontextmenu.MenuBuilder.SHADOW_HEIGHT_TOP_DP; -public class ShowRouteInfoDialogFragment extends DialogFragment { +public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { public static final String TAG = "ShowRouteInfoDialogFragment"; - private RoutingHelper helper; + private static final String ROUTE_ID_KEY = "route_id_key"; + + public static class MenuState { + public static final int HEADER_ONLY = 1; + public static final int HALF_SCREEN = 2; + public static final int FULL_SCREEN = 4; + } + + private InterceptorLinearLayout mainView; private View view; - private ListView listView; - private RouteInfoAdapter adapter; - private GPXFile gpx; - private OrderedLineDataSet slopeDataSet; - private OrderedLineDataSet elevationDataSet; - private GpxDisplayItem gpxItem; + private View.OnLayoutChangeListener containerLayoutListener; + private View zoomButtonsView; + private ImageButton myLocButtonView; - public ShowRouteInfoDialogFragment() { - } + private boolean portrait; + private boolean nightMode; + private boolean moving; + private boolean forceUpdateLayout; + private boolean initLayout = true; + private boolean wasDrawerDisabled; - private OsmandApplication getMyApplication() { - return (OsmandApplication) getActivity().getApplication(); - } + private int minHalfY; + private int topScreenPosY; + private int menuFullHeightMax; + private int menuBottomViewHeight; + private int menuFullHeight; + private int screenHeight; + private int viewHeight; + private int topShadowMargin; + private int currentMenuState; + private int shadowHeight; + private int zoomButtonsHeight; + + private int routeId; + + private OsmandApplication app; + private RoutingHelper routingHelper; + private GPXUtilities.GPXFile gpx; + private GpxUiHelper.OrderedLineDataSet slopeDataSet; + private GpxUiHelper.OrderedLineDataSet elevationDataSet; + private GpxSelectionHelper.GpxDisplayItem gpxItem; + private List menuCards = new ArrayList<>(); @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - boolean isLightTheme = getMyApplication().getSettings().OSMAND_THEME.get() == OsmandSettings.OSMAND_LIGHT_THEME; - int themeId = isLightTheme ? R.style.OsmandLightThemeWithLightStatusBar : R.style.OsmandDarkTheme; - setStyle(STYLE_NO_FRAME, themeId); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - final OsmandApplication app = getMyApplication(); - helper = app.getRoutingHelper(); + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + app = getMyApplication(); + if (app == null) { + return null; + } + routingHelper = app.getRoutingHelper(); view = inflater.inflate(R.layout.route_info_layout, container, false); + AndroidUtils.addStatusBarPadding21v(getActivity(), view); + + Bundle args = getArguments(); + if (args != null) { + routeId = args.getInt(ROUTE_ID_KEY); + } Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar); - toolbar.setNavigationIcon(getMyApplication().getUIUtilities().getThemedIcon(R.drawable.ic_arrow_back)); + toolbar.setNavigationIcon(app.getUIUtilities().getThemedIcon(R.drawable.ic_arrow_back)); toolbar.setNavigationContentDescription(R.string.shared_string_close); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override @@ -135,97 +188,1244 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { } }); - ((ImageView) view.findViewById(R.id.distance_icon)) - .setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_route_distance)); - ((ImageView) view.findViewById(R.id.time_icon)) - .setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_time_span)); - buildMenuButtons(); - listView = (ListView) view.findViewById(android.R.id.list); - listView.setBackgroundColor(getResources().getColor( - app.getSettings().isLightContent() ? R.color.ctx_menu_info_view_bg_light - : R.color.ctx_menu_info_view_bg_dark)); + currentMenuState = getInitialMenuState(); + LinearLayout cardsContainer = (LinearLayout) view.findViewById(R.id.route_menu_cards_container); + AndroidUtils.setBackground(app, cardsContainer, nightMode, R.color.route_info_bg_light, R.color.route_info_bg_dark); - View topShadowView = inflater.inflate(R.layout.list_shadow_header, listView, false); - listView.addHeaderView(topShadowView, null, false); - View bottomShadowView = inflater.inflate(R.layout.list_shadow_footer, listView, false); - listView.addFooterView(bottomShadowView, null, false); + if (routeId != -1) { + List routes = routingHelper.getTransportRoutingHelper().getRoutes(); + if (routes != null && routes.size() > routeId) { + TransportRoutePlanner.TransportRouteResult routeResult = routingHelper.getTransportRoutingHelper().getRoutes().get(routeId); + PublicTransportCard card = new PublicTransportCard(getMapActivity(), routeResult, routeId); + menuCards.add(card); + cardsContainer.addView(card.build(getMapActivity())); + buildRowDivider(cardsContainer, false); + buildTransportRouteRow(cardsContainer, routeResult, null, true); + buildRowDivider(cardsContainer, false); + } + } else { + makeGpx(); + createRouteStatisticCards(cardsContainer); + createRouteDirections(cardsContainer); + } - adapter = new RouteInfoAdapter(helper.getRouteDirections()); - listView.setAdapter(adapter); - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + final MapActivity mapActivity = requireMapActivity(); + processScreenHeight(container); + + portrait = AndroidUiHelper.isOrientationPortrait(mapActivity); + topShadowMargin = AndroidUtils.dpToPx(mapActivity, 9f); + + shadowHeight = AndroidUtils.dpToPx(mapActivity, SHADOW_HEIGHT_TOP_DP); + topScreenPosY = addStatusBarHeightIfNeeded(-shadowHeight); + minHalfY = viewHeight - (int) (viewHeight * .75f); + + mainView = view.findViewById(R.id.main_view); + nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls(); + + // Zoom buttons + zoomButtonsView = view.findViewById(R.id.map_hud_controls); + ImageButton zoomInButtonView = (ImageButton) view.findViewById(R.id.map_zoom_in_button); + ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button); + myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button); + + AndroidUtils.updateImageButton(app, zoomInButtonView, R.drawable.map_zoom_in, R.drawable.map_zoom_in_night, + R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); + AndroidUtils.updateImageButton(app, zoomOutButtonView, R.drawable.map_zoom_out, R.drawable.map_zoom_out_night, + R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); + zoomInButtonView.setOnClickListener(new View.OnClickListener() { @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - if (position < 2) { - return; + public void onClick(View v) { + doZoomIn(); + } + }); + zoomOutButtonView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + doZoomOut(); + } + }); + + myLocButtonView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (OsmAndLocationProvider.isLocationPermissionAvailable(mapActivity)) { + mapActivity.getMapViewTrackingUtilities().backToLocationImpl(); + } else { + ActivityCompat.requestPermissions(mapActivity, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + OsmAndLocationProvider.REQUEST_LOCATION_PERMISSION); } - RouteDirectionInfo item = adapter.getItem(position - 2); - Location loc = helper.getLocationFromRouteDirection(item); + } + }); + updateMyLocation(mapActivity.getRoutingHelper()); + + zoomButtonsView.setVisibility(View.VISIBLE); + + LockableScrollView bottomScrollView = (LockableScrollView) view.findViewById(R.id.route_menu_bottom_scroll); + bottomScrollView.setScrollingEnabled(false); + AndroidUtils.setBackground(app, bottomScrollView, nightMode, R.color.route_info_bg_light, R.color.route_info_bg_dark); + + AndroidUtils.setBackground(getMapActivity(), mainView, nightMode, R.drawable.bg_map_context_menu_light, R.drawable.bg_map_context_menu_dark); + + if (!portrait) { + final TypedValue typedValueAttr = new TypedValue(); + mapActivity.getTheme().resolveAttribute(R.attr.left_menu_view_bg, typedValueAttr, true); + mainView.setBackgroundResource(typedValueAttr.resourceId); + mainView.setLayoutParams(new FrameLayout.LayoutParams(getResources().getDimensionPixelSize(R.dimen.dashboard_land_width), ViewGroup.LayoutParams.MATCH_PARENT)); + + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(AndroidUtils.dpToPx(mapActivity, 345f), ViewGroup.LayoutParams.WRAP_CONTENT); + params.gravity = Gravity.BOTTOM; + } + + runLayoutListener(); + + final GestureDetector swipeDetector = new GestureDetector(getMapActivity(), new HorizontalSwipeConfirm(true)); + + final View.OnTouchListener slideTouchListener = new View.OnTouchListener() { + private float dy; + private float dyMain; + private float mDownY; + + private int minimumVelocity; + private int maximumVelocity; + private VelocityTracker velocityTracker; + private OverScroller scroller; + + private boolean slidingUp; + private boolean slidingDown; + + { + scroller = new OverScroller(getMapActivity()); + final ViewConfiguration configuration = ViewConfiguration.get(getMapActivity()); + minimumVelocity = configuration.getScaledMinimumFlingVelocity(); + maximumVelocity = configuration.getScaledMaximumFlingVelocity(); + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + + if (!portrait) { + if (swipeDetector.onTouchEvent(event)) { + dismiss(); + + recycleVelocityTracker(); + return true; + } + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + mDownY = event.getRawY(); + dy = event.getY(); + dyMain = getViewY(); + + initOrResetVelocityTracker(); + velocityTracker.addMovement(event); + break; + + case MotionEvent.ACTION_MOVE: + if (Math.abs(event.getRawY() - mDownY) > mainView.getTouchSlop()) { + moving = true; + } + if (moving) { + float y = event.getY(); + float newY = getViewY() + (y - dy); + if (!portrait && newY > topScreenPosY) { + newY = topScreenPosY; + } + setViewY((int) newY, false, false); + + ViewGroup.LayoutParams lp = mainView.getLayoutParams(); + lp.height = view.getHeight() - (int) newY + 10; + mainView.setLayoutParams(lp); + mainView.requestLayout(); + + float newEventY = newY - (dyMain - dy); + MotionEvent ev = MotionEvent.obtain(event.getDownTime(), event.getEventTime(), event.getAction(), + event.getX(), newEventY, event.getMetaState()); + + initVelocityTrackerIfNotExists(); + velocityTracker.addMovement(ev); + } + + break; + + case MotionEvent.ACTION_UP: + if (moving) { + moving = false; + int currentY = getViewY(); + + final VelocityTracker velocityTracker = this.velocityTracker; + velocityTracker.computeCurrentVelocity(1000, maximumVelocity); + int initialVelocity = (int) velocityTracker.getYVelocity(); + + if ((Math.abs(initialVelocity) > minimumVelocity)) { + + scroller.abortAnimation(); + scroller.fling(0, currentY, 0, initialVelocity, 0, 0, + Math.min(viewHeight - menuFullHeightMax, getFullScreenTopPosY()), + screenHeight, + 0, 0); + currentY = scroller.getFinalY(); + scroller.abortAnimation(); + + slidingUp = initialVelocity < -2000; + slidingDown = initialVelocity > 2000; + } else { + slidingUp = false; + slidingDown = false; + } + + changeMenuState(currentY, slidingUp, slidingDown); + } + recycleVelocityTracker(); + break; + case MotionEvent.ACTION_CANCEL: + moving = false; + recycleVelocityTracker(); + break; + + } + return true; + } + + private void initOrResetVelocityTracker() { + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } else { + velocityTracker.clear(); + } + } + + private void initVelocityTrackerIfNotExists() { + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + velocityTracker.clear(); + } + } + + private void recycleVelocityTracker() { + if (velocityTracker != null) { + velocityTracker.recycle(); + velocityTracker = null; + } + } + }; + + ((InterceptorLinearLayout) mainView).setListener(slideTouchListener); + mainView.setOnTouchListener(slideTouchListener); + + containerLayoutListener = new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View view, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + if (forceUpdateLayout || bottom != oldBottom) { + forceUpdateLayout = false; + processScreenHeight(view.getParent()); + runLayoutListener(); + } + } + }; + + runLayoutListener(); + + return view; + } + + private void createRouteDirections(LinearLayout cardsContainer) { + TextViewEx routeDirectionsTitle = new TextViewEx(app); + AndroidUtils.setTextPrimaryColor(app, routeDirectionsTitle, nightMode); + routeDirectionsTitle.setTextSize(15); + routeDirectionsTitle.setGravity(Gravity.CENTER_VERTICAL); + routeDirectionsTitle.setPadding(dpToPx(16), dpToPx(16), AndroidUtils.dpToPx(app, 16), AndroidUtils.dpToPx(app, 16)); + routeDirectionsTitle.setText(R.string.step_by_step); + routeDirectionsTitle.setTypeface(FontCache.getRobotoMedium(app)); + cardsContainer.addView(routeDirectionsTitle); + + List routeDirections = routingHelper.getRouteDirections(); + for (int i = 0; i < routeDirections.size(); i++) { + RouteDirectionInfo routeDirectionInfo = routeDirections.get(i); + View.OnClickListener onClickListener = createRouteDirectionInfoViewClickListener(i, routeDirectionInfo); + View view = getRouteDirectionView(i, cardsContainer, routeDirectionInfo, routeDirections, onClickListener); + cardsContainer.addView(view); + } + } + + private View.OnClickListener createRouteDirectionInfoViewClickListener(final int directionInfoIndex, final RouteDirectionInfo routeDirectionInfo) { + return new View.OnClickListener() { + @Override + public void onClick(View view) { + Location loc = routingHelper.getLocationFromRouteDirection(routeDirectionInfo); if (loc != null) { - MapRouteInfoMenu.directionInfo = position - 2; - OsmandSettings settings = getMyApplication().getSettings(); + MapRouteInfoMenu.directionInfo = directionInfoIndex; + OsmandSettings settings = app.getSettings(); settings.setMapLocationToShow(loc.getLatitude(), loc.getLongitude(), Math.max(13, settings.getLastKnownMapZoom()), - new PointDescription(PointDescription.POINT_TYPE_MARKER, item.getDescriptionRoutePart() + " " + getTimeDescription(item)), + new PointDescription(PointDescription.POINT_TYPE_MARKER, routeDirectionInfo.getDescriptionRoutePart() + " " + getTimeDescription(routeDirectionInfo)), false, null); MapActivity.launchMapActivityMoveToTop(getActivity()); dismiss(); } } - }); + }; + } - int dist = helper.getLeftDistance(); - int time = helper.getLeftTime(); - int hours = time / (60 * 60); - int minutes = (time / 60) % 60; - ((TextView) view.findViewById(R.id.distance)).setText(OsmAndFormatter.getFormattedDistance(dist, app)); - StringBuilder timeStr = new StringBuilder(); - if (hours > 0) { - timeStr.append(hours).append(" ").append(getString(R.string.osmand_parking_hour)).append(" "); - } - if (minutes > 0) { - timeStr.append(minutes).append(" ").append(getString(R.string.osmand_parking_minute)); - } - ((TextView) view.findViewById(R.id.time)).setText(timeStr); - - view.findViewById(R.id.go_button).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - MapActivity activity = (MapActivity) getActivity(); - if (activity != null) { - activity.getMapLayers().getMapControlsLayer().startNavigation(); - dismiss(); - } - } - }); - - makeGpx(); + private void createRouteStatisticCards(LinearLayout cardsContainer) { if (gpx.hasAltitude) { - View headerView = inflater.inflate(R.layout.route_info_header, null); - buildHeader(headerView); - listView.addHeaderView(headerView); - } - - if (slopeDataSet != null) { - List inclines = createInclinesAndAdd100MetersWith0Incline(slopeDataSet.getValues()); - - List route = helper.getRoute().getOriginalRoute(); + RouteStatisticCard statisticCard = new RouteStatisticCard(getMapActivity(), gpx, new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + mainView.requestDisallowInterceptTouchEvent(true); + return false; + } + }); + menuCards.add(statisticCard); + cardsContainer.addView(statisticCard.build(getMapActivity())); + buildRowDivider(cardsContainer, false); + slopeDataSet = statisticCard.getSlopeDataSet(); + elevationDataSet = statisticCard.getElevationDataSet(); + List route = routingHelper.getRoute().getOriginalRoute(); if (route != null) { RouteStatistics routeStatistics = RouteStatistics.newRouteStatistic(route); - buildChartAndAttachLegend(app, view, inflater, R.id.route_class_stat_chart, - R.id.route_class_stat_items, routeStatistics.getRouteClassStatistic()); - buildChartAndAttachLegend(app, view, inflater, R.id.route_surface_stat_chart, - R.id.route_surface_stat_items, routeStatistics.getRouteSurfaceStatistic()); - buildChartAndAttachLegend(app, view, inflater, R.id.route_smoothness_stat_chart, - R.id.route_smoothness_stat_items, routeStatistics.getRouteSmoothnessStatistic()); - buildChartAndAttachLegend(app, view, inflater, R.id.route_steepness_stat_chart, - R.id.route_steepness_stat_items, routeStatistics.getRouteSteepnessStatistic(inclines)); + GPXUtilities.GPXTrackAnalysis analysis = gpx.getAnalysis(0); + + RouteInfoCard routeClassCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteClassStatistic(), analysis); + createRouteCard(cardsContainer, routeClassCard); + + RouteInfoCard routeSurfaceCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteSurfaceStatistic(), analysis); + createRouteCard(cardsContainer, routeSurfaceCard); + + if (slopeDataSet != null) { + List inclines = createInclinesAndAdd100MetersWith0Incline(slopeDataSet.getValues()); + RouteInfoCard routeSteepnessCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteSteepnessStatistic(inclines), analysis); + createRouteCard(cardsContainer, routeSteepnessCard); + } + + RouteInfoCard routeSmoothnessCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteSmoothnessStatistic(), analysis); + createRouteCard(cardsContainer, routeSmoothnessCard); } } + } + + private void createRouteCard(LinearLayout cardsContainer, RouteInfoCard routeInfoCard) { + menuCards.add(routeInfoCard); + cardsContainer.addView(routeInfoCard.build(app)); + buildRowDivider(cardsContainer, false); + } + + private void updateMyLocation(RoutingHelper rh) { + MapActivity mapActivity = getMapActivity(); + Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation(); + boolean enabled = lastKnownLocation != null; + boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); + + if (!enabled) { + myLocButtonView.setImageDrawable(getIcon(R.drawable.map_my_location, R.color.icon_color)); + AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle, R.drawable.btn_circle_night); + myLocButtonView.setContentDescription(mapActivity.getString(R.string.unknown_location)); + } else if (tracked) { + myLocButtonView.setImageDrawable(getIcon(R.drawable.map_my_location, R.color.color_myloc_distance)); + AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle, R.drawable.btn_circle_night); + } else { + myLocButtonView.setImageResource(R.drawable.map_my_location); + AndroidUtils.setBackground(app, myLocButtonView, nightMode, R.drawable.btn_circle_blue, R.drawable.btn_circle_blue); + myLocButtonView.setContentDescription(mapActivity.getString(R.string.map_widget_back_to_loc)); + } + if (app.accessibilityEnabled()) { + myLocButtonView.setClickable(enabled && !tracked && rh.isFollowingMode()); + } + } + + public void doZoomIn() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + OsmandMapTileView map = mapActivity.getMapView(); + if (map.isZooming() && map.hasCustomMapRatio()) { + mapActivity.changeZoom(2, System.currentTimeMillis()); + } else { + mapActivity.changeZoom(1, System.currentTimeMillis()); + } + } + } + + public void doZoomOut() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.changeZoom(-1, System.currentTimeMillis()); + } + } + + public Drawable getCollapseIcon(boolean collapsed) { + return app.getUIUtilities().getIcon(collapsed ? R.drawable.ic_action_arrow_down : R.drawable.ic_action_arrow_up, + !nightMode ? R.color.ctx_menu_collapse_icon_color_light : R.color.ctx_menu_collapse_icon_color_dark); + } + + private void buildSegmentItem(View view, TransportRoutePlanner.TransportRouteResultSegment segment, long startTime, View.OnClickListener listener) { + TransportRoute transportRoute = segment.route; + List stops = segment.getTravelStops(); + TransportStop startStop = stops.get(0); + TransportStopRoute transportStopRoute = TransportStopRoute.getTransportStopRoute(transportRoute, startStop); + + FrameLayout baseContainer = new FrameLayout(view.getContext()); + + ImageView routeLine = new ImageView(view.getContext()); + FrameLayout.LayoutParams routeLineParams = new FrameLayout.LayoutParams(dpToPx(8f), ViewGroup.LayoutParams.MATCH_PARENT); + routeLineParams.gravity = Gravity.START; + routeLineParams.setMargins(dpToPx(24), dpToPx(14), dpToPx(22), dpToPx(28)); + routeLine.setLayoutParams(routeLineParams); + int bgColor = transportStopRoute.getColor(app, nightMode); + routeLine.setBackgroundColor(bgColor); + baseContainer.addView(routeLine); + + LinearLayout stopsContainer = new LinearLayout(view.getContext()); + stopsContainer.setOrientation(LinearLayout.VERTICAL); + baseContainer.addView(stopsContainer, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + + int drawableResId = transportStopRoute.type == null ? R.drawable.ic_action_bus_dark : transportStopRoute.type.getResourceId(); + Drawable icon = getContentIcon(drawableResId); + + Typeface typeface = FontCache.getRobotoMedium(app); + String timeText = OsmAndFormatter.getFormattedTime(startTime, false); + + SpannableString secondaryText = new SpannableString(getString(R.string.sit_on_the_stop) + ":"); + secondaryText.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), 0, secondaryText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableString title = new SpannableString(startStop.getName()); + title.setSpan(new CustomTypefaceSpan(typeface), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + title.setSpan(new ForegroundColorSpan(getActiveColor()), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + buildStartStopRow(stopsContainer, icon, timeText, transportStopRoute, title, secondaryText, listener); + + MenuBuilder.CollapsableView collapsableView = null; + if (stops.size() > 2) { + collapsableView = getCollapsableTransportStopRoutesView(getMapActivity(), transportStopRoute, stops.subList(1, stops.size() - 1)); + } + SpannableStringBuilder spannable = new SpannableStringBuilder("~"); + int startIndex = spannable.length(); + spannable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.append(OsmAndFormatter.getFormattedDuration(segment.getArrivalTime(), app)); + spannable.setSpan(new CustomTypefaceSpan(typeface), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + startIndex = spannable.length(); + spannable.append(" • "); + spannable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), startIndex, startIndex + 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + startIndex = spannable.length(); + if (stops.size() > 2) { + spannable.append(String.valueOf(stops.size())).append(" ").append(getString(R.string.transport_stops)); + } + spannable.append(" • ").append(OsmAndFormatter.getFormattedDistance((float) segment.getTravelDist(), app)); + spannable.setSpan(new CustomTypefaceSpan(typeface), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableString textType = new SpannableString(getString(R.string.by_transport_type, transportStopRoute.type.name().toLowerCase() + ":")); + buildCollapsableRow(stopsContainer, spannable, textType, true, collapsableView, listener); + + TransportStop endStop = stops.get(stops.size() - 1); + long depTime = segment.depTime + segment.getArrivalTime(); + if (depTime <= 0) { + depTime = startTime + segment.getArrivalTime(); + } + String textTime = OsmAndFormatter.getFormattedTime(depTime, false); + + secondaryText = new SpannableString(getString(R.string.exit_at) + ":"); + secondaryText.setSpan(new CustomTypefaceSpan(typeface), 0, secondaryText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + int spaceIndex = secondaryText.toString().indexOf(" "); + if (spaceIndex != -1) { + secondaryText.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), 0, spaceIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + title = new SpannableString(endStop.getName()); + title.setSpan(new CustomTypefaceSpan(typeface), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + title.setSpan(new ForegroundColorSpan(getActiveColor()), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + buildEndStopRow(stopsContainer, icon, textTime, title, secondaryText, listener); + + ((ViewGroup) view).addView(baseContainer); + } + + private View createImagesContainer() { + LinearLayout imagesContainer = new LinearLayout(view.getContext()); + FrameLayout.LayoutParams imagesContainerParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT); + imagesContainer.setPadding(dpToPx(16), dpToPx(12), dpToPx(24), 0); + imagesContainer.setOrientation(LinearLayout.VERTICAL); + imagesContainer.setLayoutParams(imagesContainerParams); + return imagesContainer; + } + + private View createInfoContainer() { + LinearLayout infoContainer = new LinearLayout(view.getContext()); + FrameLayout.LayoutParams infoContainerParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + infoContainer.setOrientation(LinearLayout.VERTICAL); + infoContainer.setLayoutParams(infoContainerParams); + return infoContainer; + } + + private void buildTransportRouteRow(ViewGroup parent, TransportRoutePlanner.TransportRouteResult routeResult, View.OnClickListener listener, boolean showDivider) { + Typeface typeface = FontCache.getRobotoMedium(app); + TargetPointsHelper targetPointsHelper = app.getTargetPointsHelper(); + TargetPointsHelper.TargetPoint startPoint = targetPointsHelper.getPointToStart(); + TargetPointsHelper.TargetPoint endPoint = targetPointsHelper.getPointToNavigate(); + long startTime = System.currentTimeMillis() / 1000; + + List segments = routeResult.getSegments(); + boolean previousWalkItemUsed = false; + + for (int i = 0; i < segments.size(); i++) { + TransportRoutePlanner.TransportRouteResultSegment segment = segments.get(i); + long walkTime = (long) getWalkTime(segment.walkDist, routeResult.getWalkSpeed()); + + if (i == 0) { + buildStartItem(parent, startPoint, startTime, segment, routeResult.getWalkSpeed(), listener); + startTime += walkTime; + } else if (segment.walkDist > 0 && !previousWalkItemUsed) { + SpannableStringBuilder spannable = new SpannableStringBuilder("~"); + int startIndex = spannable.length(); + spannable.append(OsmAndFormatter.getFormattedDuration((int) walkTime, app)).append(" "); + spannable.setSpan(new CustomTypefaceSpan(typeface), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.append(getString(R.string.on_foot)).append(" ").append(", ").append(OsmAndFormatter.getFormattedDistance((float) segment.walkDist, app)); + + buildWalkRow(parent, spannable, listener, null); + buildRowDivider(parent, true); + startTime += walkTime; + } + + buildSegmentItem(parent, segment, startTime, listener); + + double finishWalkDist = routeResult.getFinishWalkDist(); + if (i == segments.size() - 1) { + buildDestinationItem(parent, endPoint, startTime, segment, routeResult.getWalkSpeed(), listener); + } else if (finishWalkDist > 0) { + walkTime = (long) getWalkTime(finishWalkDist, routeResult.getWalkSpeed()); + startTime += walkTime; + if (i < segments.size() - 1) { + TransportRoutePlanner.TransportRouteResultSegment nextSegment = segments.get(i + 1); + if (nextSegment.walkDist > 0) { + finishWalkDist += nextSegment.walkDist; + walkTime += getWalkTime(nextSegment.walkDist, routeResult.getWalkSpeed()); + previousWalkItemUsed = true; + } else { + previousWalkItemUsed = false; + } + } + buildRowDivider(parent, true); + + Spannable title = getWalkTitle(finishWalkDist, walkTime); + buildWalkRow(parent, title, listener, null); + } + if (showDivider && i != segments.size() - 1) { + buildRowDivider(parent, true); + } + } + } + + private Spannable getWalkTitle(double finishWalkDist, double walkTime) { + Typeface typeface = FontCache.getRobotoMedium(app); + SpannableStringBuilder title = new SpannableStringBuilder("~"); + int startIndex = title.length(); + title.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + title.append(OsmAndFormatter.getFormattedDuration((int) walkTime, app)).append(" "); + title.setSpan(new CustomTypefaceSpan(typeface), startIndex, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + startIndex = title.length(); + title.append(getString(R.string.on_foot)).append(", ").append(OsmAndFormatter.getFormattedDistance((float) finishWalkDist, app)); + title.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), startIndex, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return title; + } + + private void buildStartItem(View view, TargetPointsHelper.TargetPoint start, long startTime, TransportRoutePlanner.TransportRouteResultSegment segment, double walkSpeed, View.OnClickListener listener) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + + LinearLayout imagesContainer = (LinearLayout) createImagesContainer(); + baseItemView.addView(imagesContainer); + + LinearLayout infoContainer = (LinearLayout) createInfoContainer(); + baseItemView.addView(infoContainer); + + String name; + if (start != null) { + name = start.getOnlyName().length() > 0 ? start.getOnlyName() : + (getString(R.string.route_descr_map_location) + " " + getRoutePointDescription(start.getLatitude(), start.getLongitude())); + } else { + name = getString(R.string.shared_string_my_location); + } + Spannable startTitle = new SpannableString(name); + String text = OsmAndFormatter.getFormattedTime(startTime, false); + + int drawableId = start == null ? R.drawable.ic_action_location_color : R.drawable.list_startpoint; + Drawable icon = app.getUIUtilities().getIcon(drawableId); + + buildStartRow(infoContainer, icon, text, startTitle, listener, imagesContainer); + addWalkRouteIcon(imagesContainer); + buildRowDivider(infoContainer, true); + + long walkTime = (long) getWalkTime(segment.walkDist, walkSpeed); + SpannableStringBuilder title = new SpannableStringBuilder(Algorithms.capitalizeFirstLetter(getString(R.string.on_foot))); + title.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + int startIndex = title.length(); + title.append(" ").append(OsmAndFormatter.getFormattedDuration((int) walkTime, app)); + title.setSpan(new CustomTypefaceSpan(FontCache.getRobotoMedium(app)), startIndex, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + startIndex = title.length(); + title.append(", ").append(OsmAndFormatter.getFormattedDistance((float) segment.walkDist, app)); + title.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), startIndex, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + buildWalkRow(infoContainer, title, listener, imagesContainer); + buildRowDivider(infoContainer, true); + + ((ViewGroup) view).addView(baseItemView); + } + + private void addWalkRouteIcon(LinearLayout container) { + ImageView walkLineImage = new ImageView(view.getContext()); + walkLineImage.setImageDrawable(app.getUIUtilities().getIcon(R.drawable.walk_route_item_light)); + LinearLayout.LayoutParams walkImageLayoutParams = new LinearLayout.LayoutParams(dpToPx(10), dpToPx(14)); + walkImageLayoutParams.setMargins(dpToPx(7), dpToPx(6), 0, dpToPx(6)); + walkLineImage.setLayoutParams(walkImageLayoutParams); + container.addView(walkLineImage); + } + + private void buildDestinationItem(View view, TargetPointsHelper.TargetPoint destination, long startTime, TransportRoutePlanner.TransportRouteResultSegment segment, double walkSpeed, View.OnClickListener listener) { + Typeface typeface = FontCache.getRobotoMedium(app); + FrameLayout baseItemView = new FrameLayout(view.getContext()); + + LinearLayout imagesContainer = (LinearLayout) createImagesContainer(); + baseItemView.addView(imagesContainer); + + LinearLayout infoContainer = (LinearLayout) createInfoContainer(); + baseItemView.addView(infoContainer); + + buildRowDivider(infoContainer, true); + + long walkTime = (long) getWalkTime(segment.walkDist, walkSpeed); + + SpannableStringBuilder spannable = new SpannableStringBuilder("~"); + spannable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + int startIndex = spannable.length(); + spannable.append(OsmAndFormatter.getFormattedDuration((int) walkTime, app)).append(" "); + spannable.setSpan(new CustomTypefaceSpan(typeface), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + startIndex = spannable.length(); + spannable.append(getString(R.string.on_foot)).append(", ").append(OsmAndFormatter.getFormattedDistance((float) segment.walkDist, app)); + spannable.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.secondary_text_light)), startIndex, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + buildWalkRow(infoContainer, spannable, listener, imagesContainer); + buildRowDivider(infoContainer, true); + addWalkRouteIcon(imagesContainer); + + String timeStr = OsmAndFormatter.getFormattedTime(startTime + walkTime, false); + String name = getRoutePointDescription(destination.point, destination.getOnlyName()); + SpannableString title = new SpannableString(name); + title.setSpan(new CustomTypefaceSpan(typeface), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + title.setSpan(new ForegroundColorSpan(getActiveColor()), 0, title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableString secondaryText = new SpannableString(getString(R.string.route_descr_destination) + ":"); + secondaryText.setSpan(new CustomTypefaceSpan(typeface), 0, secondaryText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + secondaryText.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), 0, secondaryText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + SpannableStringBuilder locationStr = new SpannableStringBuilder(); + String loc = getPointName(destination); + if (!loc.equals(name)) { + locationStr.append(loc); + } + buildDestinationRow(infoContainer, timeStr, title, secondaryText, locationStr, listener, imagesContainer); + + ((ViewGroup) view).addView(baseItemView); + } + + private String getPointName(TargetPointsHelper.TargetPoint targetPoint) { + String name = ""; + if (targetPoint != null) { + PointDescription description = targetPoint.getOriginalPointDescription(); + if (description != null && !Algorithms.isEmpty(description.getName()) && + !description.getName().equals(getString(R.string.no_address_found))) { + name = description.getName(); + } else { + name = PointDescription.getLocationName(app, targetPoint.point.getLatitude(), targetPoint.point.getLongitude(), true).replace('\n', ' '); + } + } + return name; + } + + private int getActiveColor() { + return ContextCompat.getColor(app, !nightMode ? R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark); + } + + public void buildCollapsableRow(final View view, final Spannable title, Spannable secondaryText, boolean collapsable, + final MenuBuilder.CollapsableView collapsableView, View.OnClickListener onClickListener) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(48, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + + if (!TextUtils.isEmpty(secondaryText)) { + buildDescriptionView(secondaryText, llText, 8); + } + + buildTitleView(title, llText); + + final ImageView iconViewCollapse = new ImageView(view.getContext()); + if (collapsable && collapsableView != null) { + // Icon + LinearLayout llIconCollapse = new LinearLayout(view.getContext()); + llIconCollapse.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, dpToPx(48f))); + llIconCollapse.setOrientation(LinearLayout.HORIZONTAL); + llIconCollapse.setGravity(Gravity.CENTER_VERTICAL); + ll.addView(llIconCollapse); + + LinearLayout.LayoutParams llIconCollapseParams = new LinearLayout.LayoutParams(dpToPx(24f), dpToPx(24f)); + llIconCollapseParams.setMargins(0, dpToPx(12f), 0, dpToPx(12f)); + llIconCollapseParams.gravity = Gravity.CENTER_VERTICAL; + iconViewCollapse.setLayoutParams(llIconCollapseParams); + iconViewCollapse.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + iconViewCollapse.setImageDrawable(getCollapseIcon(collapsableView.getContenView().getVisibility() == View.GONE)); + llIconCollapse.addView(iconViewCollapse); + ll.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + LinearLayout contentView = (LinearLayout) collapsableView.getContenView(); + if (contentView.getVisibility() == View.VISIBLE) { + contentView.setVisibility(View.GONE); + iconViewCollapse.setImageDrawable(getCollapseIcon(true)); + collapsableView.setCollapsed(true); + contentView.getChildAt(contentView.getChildCount() - 1).setVisibility(View.VISIBLE); + } else { + contentView.setVisibility(View.VISIBLE); + iconViewCollapse.setImageDrawable(getCollapseIcon(false)); + collapsableView.setCollapsed(false); + } + } + }); + if (collapsableView.isCollapsed()) { + collapsableView.getContenView().setVisibility(View.GONE); + iconViewCollapse.setImageDrawable(getCollapseIcon(true)); + } + baseView.addView(collapsableView.getContenView()); + } + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + public void buildStartStopRow(final View view, Drawable icon, String timeText, TransportStopRoute transportStopRoute, + final Spannable title, Spannable secondaryText, View.OnClickListener onClickListener) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(48, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + if (icon != null) { + ImageView iconView = new ImageView(view.getContext()); + iconView.setImageDrawable(icon); + FrameLayout.LayoutParams imageViewLayoutParams = new FrameLayout.LayoutParams(dpToPx(28), dpToPx(28)); + imageViewLayoutParams.gravity = Gravity.TOP; + iconView.setLayoutParams(imageViewLayoutParams); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + imageViewLayoutParams.setMargins(dpToPx(14), dpToPx(8), dpToPx(22), 0); + iconView.setPadding(dpToPx(2), dpToPx(2), dpToPx(2), dpToPx(2)); + iconView.setBackgroundResource(R.drawable.border_round_solid_light); + baseItemView.addView(iconView); + } + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + + if (!TextUtils.isEmpty(secondaryText)) { + buildDescriptionView(secondaryText, llText, 8); + } + + buildTitleView(title, llText); + + if (!TextUtils.isEmpty(timeText)) { + TextView timeView = new TextView(view.getContext()); + FrameLayout.LayoutParams timeViewParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + timeViewParams.gravity = Gravity.END | Gravity.TOP; + timeViewParams.setMargins(0, dpToPx(8), 0, 0); + timeView.setLayoutParams(timeViewParams); + timeView.setPadding(0, 0, dpToPx(16), 0); + timeView.setTextSize(16); + AndroidUtils.setTextPrimaryColor(app, timeView, nightMode); + + timeView.setText(timeText); + baseItemView.addView(timeView); + } + + if (transportStopRoute != null) { + TextView routeTypeView = new TextView(view.getContext()); + LinearLayout.LayoutParams routeTypeParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + routeTypeParams.setMargins(0, dpToPx(4), 0, 0); + routeTypeView.setLayoutParams(routeTypeParams); + routeTypeView.setTextSize(16); + AndroidUtils.setTextSecondaryColor(app, routeTypeView, nightMode); + routeTypeView.setText(getString(R.string.layer_route) + ":"); + llText.addView(routeTypeView); + + View routeBadge = createRouteBadge(getMapActivity(), transportStopRoute, nightMode); + LinearLayout.LayoutParams routeBadgeParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + routeBadgeParams.setMargins(0, dpToPx(6), 0, dpToPx(8)); + routeBadge.setLayoutParams(routeBadgeParams); + llText.addView(routeBadge); + } + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + public void buildEndStopRow(final View view, Drawable icon, String timeText, final Spannable title, Spannable secondaryText, View.OnClickListener onClickListener) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(48, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + if (icon != null) { + ImageView iconView = new ImageView(view.getContext()); + iconView.setImageDrawable(icon); + FrameLayout.LayoutParams imageViewLayoutParams = new FrameLayout.LayoutParams(dpToPx(28), dpToPx(28)); + imageViewLayoutParams.gravity = Gravity.TOP; + iconView.setLayoutParams(imageViewLayoutParams); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + imageViewLayoutParams.setMargins(dpToPx(14), dpToPx(8), dpToPx(22), 0); + iconView.setPadding(dpToPx(2), dpToPx(2), dpToPx(2), dpToPx(2)); + iconView.setBackgroundResource(R.drawable.border_round_solid_light); + baseItemView.addView(iconView); + } + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + + if (!TextUtils.isEmpty(secondaryText)) { + buildDescriptionView(secondaryText, llText, 8); + } + + buildTitleView(title, llText); + + if (!TextUtils.isEmpty(timeText)) { + TextView timeView = new TextView(view.getContext()); + FrameLayout.LayoutParams timeViewParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + timeViewParams.gravity = Gravity.END | Gravity.TOP; + timeViewParams.setMargins(0, dpToPx(8), 0, 0); + timeView.setLayoutParams(timeViewParams); + timeView.setPadding(0, 0, dpToPx(16), 0); + timeView.setTextSize(16); + AndroidUtils.setTextPrimaryColor(app, timeView, nightMode); + + timeView.setText(timeText); + baseItemView.addView(timeView); + } + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + public void buildWalkRow(final View view, final Spannable title, View.OnClickListener onClickListener, LinearLayout imagesContainer) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(48, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + Drawable icon = getIcon(R.drawable.ic_action_pedestrian_dark, !nightMode ? R.color.ctx_menu_bottom_view_url_color_light : R.color.ctx_menu_bottom_view_url_color_dark); + ImageView iconView = new ImageView(view.getContext()); + iconView.setImageDrawable(icon); + FrameLayout.LayoutParams imageViewLayoutParams = new FrameLayout.LayoutParams(dpToPx(24), dpToPx(24)); + imageViewLayoutParams.gravity = imagesContainer != null ? Gravity.TOP : Gravity.CENTER_VERTICAL; + iconView.setLayoutParams(imageViewLayoutParams); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + if (imagesContainer != null) { + imagesContainer.addView(iconView); + } else { + imageViewLayoutParams.setMargins(dpToPx(16), 0, dpToPx(24), 0); + baseItemView.addView(iconView); + } + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + buildTitleView(title, llText); + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + public void buildStartRow(final View view, Drawable icon, String timeText, final Spannable title, View.OnClickListener onClickListener, LinearLayout imagesContainer) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(48, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + if (icon != null) { + ImageView iconView = new ImageView(view.getContext()); + iconView.setImageDrawable(icon); + FrameLayout.LayoutParams imageViewLayoutParams = new FrameLayout.LayoutParams(dpToPx(24), dpToPx(24)); + iconView.setLayoutParams(imageViewLayoutParams); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + if (imagesContainer != null) { + imagesContainer.addView(iconView); + } else { + imageViewLayoutParams.setMargins(dpToPx(16), 0, dpToPx(24), 0); + baseItemView.addView(iconView); + } + } + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + + buildTitleView(title, llText); + + if (!TextUtils.isEmpty(timeText)) { + TextView timeView = new TextView(view.getContext()); + FrameLayout.LayoutParams timeViewParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + timeViewParams.gravity = Gravity.END | Gravity.TOP; + timeViewParams.setMargins(0, dpToPx(8), 0, 0); + timeView.setLayoutParams(timeViewParams); + timeView.setPadding(0, 0, dpToPx(16), 0); + timeView.setTextSize(16); + AndroidUtils.setTextPrimaryColor(app, timeView, nightMode); + + timeView.setText(timeText); + baseItemView.addView(timeView); + } + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + public void buildDestinationRow(final View view, String timeText, final Spannable title, Spannable secondaryText, + Spannable locationText, View.OnClickListener onClickListener, LinearLayout imagesContainer) { + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(48, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + Drawable destinationIcon = app.getUIUtilities().getIcon(R.drawable.list_destination); + ImageView iconView = new ImageView(view.getContext()); + iconView.setImageDrawable(destinationIcon); + FrameLayout.LayoutParams imageViewLayoutParams = new FrameLayout.LayoutParams(dpToPx(24), dpToPx(24)); + iconView.setLayoutParams(imageViewLayoutParams); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + if (imagesContainer != null) { + imagesContainer.addView(iconView); + } else { + imageViewLayoutParams.setMargins(dpToPx(16), 0, dpToPx(24), 0); + baseItemView.addView(iconView); + } + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + + buildDescriptionView(secondaryText, llText, 8); + buildTitleView(title, llText); + + if (!TextUtils.isEmpty(locationText)) { + buildDescriptionView(locationText, llText, 4); + } + + if (!TextUtils.isEmpty(timeText)) { + TextView timeView = new TextView(view.getContext()); + FrameLayout.LayoutParams timeViewParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + timeViewParams.gravity = Gravity.END | Gravity.TOP; + timeViewParams.setMargins(0, dpToPx(8), 0, 0); + timeView.setLayoutParams(timeViewParams); + timeView.setPadding(0, 0, dpToPx(16), 0); + timeView.setTextSize(16); + AndroidUtils.setTextPrimaryColor(app, timeView, nightMode); + + timeView.setText(timeText); + baseItemView.addView(timeView); + } + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + private void buildIntermediateRow(final View view, Drawable icon, final Spannable title, View.OnClickListener onClickListener) { + + FrameLayout baseItemView = new FrameLayout(view.getContext()); + FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + baseItemView.setLayoutParams(baseViewLayoutParams); + + LinearLayout baseView = new LinearLayout(view.getContext()); + baseView.setOrientation(LinearLayout.VERTICAL); + baseView.setLayoutParams(baseViewLayoutParams); + baseView.setGravity(Gravity.END); + baseView.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + baseItemView.addView(baseView); + + LinearLayout ll = buildHorizontalContainerView(36, new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + copyToClipboard(title.toString(), view.getContext()); + return true; + } + }); + baseView.addView(ll); + + // Icon + if (icon != null) { + ImageView iconView = new ImageView(view.getContext()); + iconView.setImageDrawable(icon); + FrameLayout.LayoutParams imageViewLayoutParams = new FrameLayout.LayoutParams(dpToPx(22), dpToPx(22)); + imageViewLayoutParams.gravity = Gravity.CENTER_VERTICAL; + iconView.setLayoutParams(imageViewLayoutParams); + iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + + imageViewLayoutParams.setMargins(dpToPx(17), 0, dpToPx(25), 0); + iconView.setPadding(dpToPx(2), dpToPx(2), dpToPx(2), dpToPx(2)); + iconView.setBackgroundResource(R.drawable.border_round_solid_light_small); + baseItemView.addView(iconView); + } + + LinearLayout llText = buildTextContainerView(); + ll.addView(llText); + + buildTitleView(title, llText); + + if (onClickListener != null) { + ll.setOnClickListener(onClickListener); + } + + ((LinearLayout) view).addView(baseItemView); + } + + private MenuBuilder.CollapsableView getCollapsableTransportStopRoutesView(final Context context, TransportStopRoute transportStopRoute, List stops) { + LinearLayout view = (LinearLayout) buildCollapsableContentView(context, false); + int drawableResId = transportStopRoute.type == null ? R.drawable.ic_action_bus_dark : transportStopRoute.type.getResourceId(); + Drawable icon = getContentIcon(drawableResId); + for (int i = 0; i < stops.size(); i++) { + buildIntermediateRow(view, icon, new SpannableString(stops.get(i).getName()), null); + } + return new MenuBuilder.CollapsableView(view, null, false); + } + + protected LinearLayout buildCollapsableContentView(Context context, boolean collapsed) { + final LinearLayout view = new LinearLayout(context); + view.setOrientation(LinearLayout.VERTICAL); + view.setVisibility(collapsed ? View.GONE : View.VISIBLE); + LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + view.setLayoutParams(llParams); return view; } + private void buildTitleView(Spannable title, LinearLayout container) { + TextViewEx titleView = new TextViewEx(view.getContext()); + FrameLayout.LayoutParams titleParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + titleParams.gravity = Gravity.CENTER_VERTICAL; + titleView.setTypeface(FontCache.getRobotoRegular(view.getContext())); + titleView.setLayoutParams(titleParams); + titleView.setTextSize(16); + AndroidUtils.setTextPrimaryColor(app, titleView, nightMode); + + titleView.setText(title); + container.addView(titleView); + } + + private void buildDescriptionView(Spannable description, LinearLayout container, int paddingTop) { + TextViewEx textViewDescription = new TextViewEx(view.getContext()); + LinearLayout.LayoutParams descriptionParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + descriptionParams.setMargins(0, dpToPx(paddingTop), 0, 0); + textViewDescription.setLayoutParams(descriptionParams); + textViewDescription.setTypeface(FontCache.getRobotoRegular(view.getContext())); + textViewDescription.setTextSize(14); + AndroidUtils.setTextSecondaryColor(app, textViewDescription, nightMode); + textViewDescription.setText(description); + container.addView(textViewDescription); + } + + private LinearLayout buildTextContainerView() { + LinearLayout llText = new LinearLayout(view.getContext()); + llText.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams llTextViewParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT); + llTextViewParams.weight = 1f; + llTextViewParams.gravity = Gravity.CENTER_VERTICAL; + llText.setLayoutParams(llTextViewParams); + return llText; + } + + private LinearLayout buildHorizontalContainerView(int minHeight, View.OnLongClickListener onLongClickListener) { + LinearLayout ll = new LinearLayout(view.getContext()); + ll.setOrientation(LinearLayout.HORIZONTAL); + LinearLayout.LayoutParams llParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + ll.setMinimumHeight(dpToPx(minHeight)); + ll.setPadding(dpToPx(64), 0, dpToPx(16), 0); + ll.setLayoutParams(llParams); + ll.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); + ll.setOnLongClickListener(onLongClickListener); + return ll; + } + + public static View createRouteBadge(MapActivity mapActivity, TransportStopRoute transportStopRoute, boolean nightMode) { + LinearLayout convertView = (LinearLayout) mapActivity.getLayoutInflater().inflate(R.layout.transport_stop_route_item_with_icon, null, false); + if (transportStopRoute != null) { + + String routeRef = transportStopRoute.route.getAdjustedRouteRef(); + int bgColor = transportStopRoute.getColor(mapActivity.getMyApplication(), nightMode); + + TextView transportStopRouteTextView = (TextView) convertView.findViewById(R.id.transport_stop_route_text); + ImageView transportStopRouteImageView = (ImageView) convertView.findViewById(R.id.transport_stop_route_icon); + + int drawableResId = transportStopRoute.type == null ? R.drawable.ic_action_bus_dark : transportStopRoute.type.getResourceId(); + + transportStopRouteImageView.setImageDrawable(mapActivity.getMyApplication().getUIUtilities().getPaintedIcon(drawableResId, UiUtilities.getContrastColor(mapActivity, bgColor, true))); + transportStopRouteTextView.setText(routeRef); + GradientDrawable gradientDrawableBg = (GradientDrawable) convertView.getBackground(); + gradientDrawableBg.setColor(bgColor); + transportStopRouteTextView.setTextColor(UiUtilities.getContrastColor(mapActivity, bgColor, true)); + } + + return convertView; + } + + public String getRoutePointDescription(double lat, double lon) { + return getString(R.string.route_descr_lat_lon, lat, lon); + } + + public String getRoutePointDescription(LatLon l, String d) { + if (d != null && d.length() > 0) { + return d.replace(':', ' '); + } + if (l != null) { + return getString(R.string.route_descr_lat_lon, l.getLatitude(), l.getLongitude()); + } + return ""; + } + + private double getWalkTime(double walkDist, double walkSpeed) { + return walkDist / walkSpeed; + } + + public void buildRowDivider(View view, boolean needMargin) { + View horizontalLine = new View(view.getContext()); + LinearLayout.LayoutParams llHorLineParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dpToPx(1f)); + llHorLineParams.gravity = Gravity.BOTTOM; + if (needMargin) { + llHorLineParams.setMargins(dpToPx(64), 0, 0, 0); + } + horizontalLine.setLayoutParams(llHorLineParams); + horizontalLine.setBackgroundColor(app.getResources().getColor(!nightMode ? R.color.ctx_menu_bottom_view_divider_light : R.color.ctx_menu_bottom_view_divider_dark)); + ((LinearLayout) view).addView(horizontalLine); + } + + public int dpToPx(float dp) { + return AndroidUtils.dpToPx(app, dp); + } + + protected void copyToClipboard(String text, Context ctx) { + ((ClipboardManager) app.getSystemService(Activity.CLIPBOARD_SERVICE)).setText(text); + Toast.makeText(ctx, + ctx.getResources().getString(R.string.copied_to_clipboard) + ":\n" + text, + Toast.LENGTH_SHORT).show(); + } + private List createInclinesAndAdd100MetersWith0Incline(List entries) { int size = entries.size(); List inclines = new ArrayList<>(); @@ -246,85 +1446,10 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { return inclines; } - private int getColorFromStyle(String colorAttrName) { - RenderingRulesStorage rrs = getMyApplication().getRendererRegistry().getCurrentSelectedRenderer(); - RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs); - boolean nightMode = false; - req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, nightMode); - if (req.searchRenderingAttribute(colorAttrName)) { - return req.getIntPropertyValue(rrs.PROPS.R_ATTR_COLOR_VALUE); - } - return 0; - } - - private void buildStatisticChart(View view, int chartId, Statistics routeStatistics) { - List> segments = routeStatistics.getElements(); - HorizontalBarChart hbc = view.findViewById(chartId); - List entries = new ArrayList<>(); - float[] stacks = new float[segments.size()]; - int[] colors = new int[segments.size()]; - for (int i = 0; i < stacks.length; i++) { - RouteSegmentAttribute segment = segments.get(i); - stacks[i] = segment.getDistance(); - colors[i] = getColorFromStyle(segment.getColorAttrName()); - } - entries.add(new BarEntry(0, stacks)); - BarDataSet barDataSet = new BarDataSet(entries, ""); - barDataSet.setColors(colors); - BarData data = new BarData(barDataSet); - data.setDrawValues(false); - hbc.setData(data); - hbc.setDrawBorders(false); - hbc.setTouchEnabled(false); - hbc.disableScroll(); - hbc.getLegend().setEnabled(false); - hbc.getDescription().setEnabled(false); - XAxis xAxis = hbc.getXAxis(); - xAxis.setEnabled(false); - YAxis leftYAxis = hbc.getAxisLeft(); - YAxis rightYAxis = hbc.getAxisRight(); - rightYAxis.setDrawLabels(true); - rightYAxis.setGranularity(1f); - rightYAxis.setValueFormatter(new IAxisValueFormatter() { - @Override - public String getFormattedValue(float value, AxisBase axis) { - if (value > 100) { - return String.valueOf(value); - } - return ""; - } - }); - rightYAxis.setDrawGridLines(false); - leftYAxis.setDrawLabels(false); - leftYAxis.setEnabled(false); - hbc.invalidate(); - } - - private void attachLegend(OsmandApplication app, LayoutInflater inflater, ViewGroup container, Statistics routeStatistics) { - Map> partition = routeStatistics.getPartition(); - for (E key : partition.keySet()) { - RouteSegmentAttribute segment = partition.get(key); - View view = inflater.inflate(R.layout.route_info_stat_item, container, false); - TextView textView = view.findViewById(R.id.route_stat_item_text); - String formattedDistance = OsmAndFormatter.getFormattedDistance(segment.getDistance(), getMyApplication()); - textView.setText(String.format("%s - %s", key, formattedDistance)); - Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle,getColorFromStyle(segment.getColorAttrName())); - ImageView imageView = view.findViewById(R.id.route_stat_item_image); - imageView.setImageDrawable(circle); - container.addView(view); - } - } - - private void buildChartAndAttachLegend(OsmandApplication app, View view, LayoutInflater inflater, int chartId, int containerId, Statistics routeStatistics) { - ViewGroup container = view.findViewById(containerId); - buildStatisticChart(view, chartId, routeStatistics); - attachLegend(app, inflater, container, routeStatistics); - } - private void makeGpx() { - gpx = GpxUiHelper.makeGpxFromRoute(helper.getRoute(), getMyApplication()); - String groupName = getMyApplication().getString(R.string.current_route); - GpxDisplayGroup group = getMyApplication().getSelectedGpxHelper().buildGpxDisplayGroup(gpx, 0, groupName); + gpx = GpxUiHelper.makeGpxFromRoute(routingHelper.getRoute(), app); + String groupName = getString(R.string.current_route); + GpxDisplayGroup group = app.getSelectedGpxHelper().buildGpxDisplayGroup(gpx, 0, groupName); if (group != null && group.getModifiableList().size() > 0) { gpxItem = group.getModifiableList().get(0); if (gpxItem != null) { @@ -333,125 +1458,6 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { } } - private void buildHeader(View headerView) { - OsmandApplication app = getMyApplication(); - final LineChart mChart = (LineChart) headerView.findViewById(R.id.chart); - GpxUiHelper.setupGPXChart(app, mChart, 4); - mChart.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - listView.requestDisallowInterceptTouchEvent(true); - return false; - } - }); - - GPXTrackAnalysis analysis = gpx.getAnalysis(0); - if (analysis.hasElevationData) { - List dataSets = new ArrayList<>(); - elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, mChart, analysis, - GPXDataSetAxisType.DISTANCE, false, true); - if (elevationDataSet != null) { - dataSets.add(elevationDataSet); - } - slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, mChart, analysis, - GPXDataSetAxisType.DISTANCE, elevationDataSet.getValues(), true, true); - if (slopeDataSet != null) { - dataSets.add(slopeDataSet); - } - LineData data = new LineData(dataSets); - mChart.setData(data); - - mChart.setOnChartGestureListener(new OnChartGestureListener() { - - float highlightDrawX = -1; - - @Override - public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - if (mChart.getHighlighted() != null && mChart.getHighlighted().length > 0) { - highlightDrawX = mChart.getHighlighted()[0].getDrawX(); - } else { - highlightDrawX = -1; - } - } - - @Override - public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - gpxItem.chartMatrix = new Matrix(mChart.getViewPortHandler().getMatrixTouch()); - Highlight[] highlights = mChart.getHighlighted(); - if (highlights != null && highlights.length > 0) { - gpxItem.chartHighlightPos = highlights[0].getX(); - } else { - gpxItem.chartHighlightPos = -1; - } - } - - @Override - public void onChartLongPressed(MotionEvent me) { - } - - @Override - public void onChartDoubleTapped(MotionEvent me) { - } - - @Override - public void onChartSingleTapped(MotionEvent me) { - } - - @Override - public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { - } - - @Override - public void onChartScale(MotionEvent me, float scaleX, float scaleY) { - } - - @Override - public void onChartTranslate(MotionEvent me, float dX, float dY) { - if (highlightDrawX != -1) { - Highlight h = mChart.getHighlightByTouchPoint(highlightDrawX, 0f); - if (h != null) { - mChart.highlightValue(h); - } - } - } - }); - - mChart.setVisibility(View.VISIBLE); - } else { - elevationDataSet = null; - slopeDataSet = null; - mChart.setVisibility(View.GONE); - } - ((TextView) headerView.findViewById(R.id.average_text)) - .setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app)); - - String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app); - String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app); - ((TextView) headerView.findViewById(R.id.range_text)) - .setText(min + " - " + max); - - String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app); - String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app); - ((TextView) headerView.findViewById(R.id.descent_text)).setText(desc); - ((TextView) headerView.findViewById(R.id.ascent_text)).setText(asc); - - ((ImageView) headerView.findViewById(R.id.average_icon)) - .setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_altitude_average)); - ((ImageView) headerView.findViewById(R.id.range_icon)) - .setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_altitude_average)); - ((ImageView) headerView.findViewById(R.id.descent_icon)) - .setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_altitude_descent)); - ((ImageView) headerView.findViewById(R.id.ascent_icon)) - .setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_altitude_ascent)); - - headerView.findViewById(R.id.details_view).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - openDetails(); - } - }); - } - void openDetails() { if (gpxItem != null) { LatLon location = null; @@ -486,7 +1492,7 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { if (activity != null) { dismiss(); - final OsmandSettings settings = activity.getMyApplication().getSettings(); + final OsmandSettings settings = app.getSettings(); settings.setMapLocationToShow(location.getLatitude(), location.getLongitude(), settings.getLastKnownMapZoom(), new PointDescription(PointDescription.POINT_TYPE_WPT, gpxItem.name), @@ -514,7 +1520,7 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { } private void buildMenuButtons() { - UiUtilities iconsCache = getMyApplication().getUIUtilities(); + UiUtilities iconsCache = app.getUIUtilities(); ImageButton printRoute = (ImageButton) view.findViewById(R.id.print_route); printRoute.setImageDrawable(iconsCache.getThemedIcon(R.drawable.ic_action_gprint_dark)); printRoute.setOnClickListener(new View.OnClickListener() { @@ -529,7 +1535,7 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { saveRoute.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - MapActivityActions.createSaveDirections(getActivity(), helper).show(); + MapActivityActions.createSaveDirections(getActivity(), routingHelper).show(); } }); @@ -539,9 +1545,9 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { @Override public void onClick(View v) { final String trackName = new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date()); - final GPXFile gpx = helper.generateGPXFileWithRoute(trackName); + final GPXFile gpx = routingHelper.generateGPXFileWithRoute(trackName); final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(gpx.path)); - File dir = new File(getActivity().getCacheDir(), "share"); + File dir = new File(app.getCacheDir(), "share"); if (!dir.exists()) { dir.mkdir(); } @@ -552,8 +1558,8 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { fw.close(); final Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(generateHtml(adapter, - helper.getGeneralRouteInformation()).toString())); + sendIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(generateHtml(routingHelper.getRouteDirections(), + routingHelper.getGeneralRouteInformation()).toString())); sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_route_subject)); sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); sendIntent.putExtra( @@ -570,94 +1576,74 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { }); } - public static void showDialog(FragmentManager fragmentManager) { - ShowRouteInfoDialogFragment fragment = new ShowRouteInfoDialogFragment(); - fragment.show(fragmentManager, TAG); + public class CumulativeInfo { + public int distance; + public int time; + + public CumulativeInfo() { + distance = 0; + time = 0; + } } - class RouteInfoAdapter extends ArrayAdapter { - public class CumulativeInfo { - public int distance; - public int time; - - public CumulativeInfo() { - distance = 0; - time = 0; - } + public View getRouteDirectionView(int position, ViewGroup parent, RouteDirectionInfo model, List directionsInfo, View.OnClickListener onClickListener) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity == null) { + return null; } + View row = mapActivity.getLayoutInflater().inflate(R.layout.route_info_list_item, parent, false); + row.setBackgroundResource(AndroidUtils.resolveAttribute(view.getContext(), android.R.attr.selectableItemBackground)); - private final int lastItemIndex; - private boolean light; + TextView label = (TextView) row.findViewById(R.id.description); + TextView distanceLabel = (TextView) row.findViewById(R.id.distance); + TextView timeLabel = (TextView) row.findViewById(R.id.time); + TextView cumulativeDistanceLabel = (TextView) row.findViewById(R.id.cumulative_distance); + TextView cumulativeTimeLabel = (TextView) row.findViewById(R.id.cumulative_time); + ImageView icon = (ImageView) row.findViewById(R.id.direction); + row.findViewById(R.id.divider).setVisibility(position == directionsInfo.size() - 1 ? View.INVISIBLE : View.VISIBLE); - RouteInfoAdapter(List list) { - super(getActivity(), R.layout.route_info_list_item, list); - lastItemIndex = list.size() - 1; - this.setNotifyOnChange(false); - light = getMyApplication().getSettings().isLightContent(); - } + TurnPathHelper.RouteDrawable drawable = new TurnPathHelper.RouteDrawable(getResources(), true); + drawable.setColorFilter(new PorterDuffColorFilter(!nightMode ? getResources().getColor(R.color.icon_color) : Color.WHITE, PorterDuff.Mode.SRC_ATOP)); + drawable.setRouteType(model.getTurnType()); + icon.setImageDrawable(drawable); - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - if (row == null) { - LayoutInflater inflater = - (LayoutInflater) getMyApplication().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - row = inflater.inflate(R.layout.route_info_list_item, parent, false); + label.setText(model.getDescriptionRoutePart()); + if (model.distance > 0) { + distanceLabel.setText(OsmAndFormatter.getFormattedDistance(model.distance, app)); + timeLabel.setText(getTimeDescription(model)); + row.setContentDescription(label.getText() + " " + timeLabel.getText()); //$NON-NLS-1$ + } else { + if (Algorithms.isEmpty(label.getText().toString())) { + label.setText(getString((position != directionsInfo.size() - 1) ? R.string.arrived_at_intermediate_point : R.string.arrived_at_destination)); } - RouteDirectionInfo model = getItem(position); - TextView label = (TextView) row.findViewById(R.id.description); - TextView distanceLabel = (TextView) row.findViewById(R.id.distance); - TextView timeLabel = (TextView) row.findViewById(R.id.time); - TextView cumulativeDistanceLabel = (TextView) row.findViewById(R.id.cumulative_distance); - TextView cumulativeTimeLabel = (TextView) row.findViewById(R.id.cumulative_time); - ImageView icon = (ImageView) row.findViewById(R.id.direction); - row.findViewById(R.id.divider).setVisibility(position == getCount() - 1 ? View.INVISIBLE : View.VISIBLE); - - TurnPathHelper.RouteDrawable drawable = new TurnPathHelper.RouteDrawable(getResources(), true); - drawable.setColorFilter(new PorterDuffColorFilter(light ? getResources().getColor(R.color.icon_color) : Color.WHITE, PorterDuff.Mode.SRC_ATOP)); - drawable.setRouteType(model.getTurnType()); - icon.setImageDrawable(drawable); - - label.setText(String.valueOf(position + 1) + ". " + model.getDescriptionRoutePart()); - if (model.distance > 0) { - distanceLabel.setText(OsmAndFormatter.getFormattedDistance( - model.distance, getMyApplication())); - timeLabel.setText(getTimeDescription(model)); - row.setContentDescription(label.getText() + " " + timeLabel.getText()); //$NON-NLS-1$ - } else { - if (label.getText().equals(String.valueOf(position + 1) + ". ")) { - label.setText(String.valueOf(position + 1) + ". " + getString((position != lastItemIndex) ? R.string.arrived_at_intermediate_point : R.string.arrived_at_destination)); - } - distanceLabel.setText(""); //$NON-NLS-1$ - timeLabel.setText(""); //$NON-NLS-1$ - row.setContentDescription(""); //$NON-NLS-1$ - } - CumulativeInfo cumulativeInfo = getRouteDirectionCumulativeInfo(position); - cumulativeDistanceLabel.setText(OsmAndFormatter.getFormattedDistance( - cumulativeInfo.distance, getMyApplication())); - cumulativeTimeLabel.setText(Algorithms.formatDuration(cumulativeInfo.time, getMyApplication().accessibilityEnabled())); - return row; + distanceLabel.setText(""); + timeLabel.setText(""); + row.setContentDescription(""); } + CumulativeInfo cumulativeInfo = getRouteDirectionCumulativeInfo(position, directionsInfo); + cumulativeDistanceLabel.setText(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance, app)); + cumulativeTimeLabel.setText(Algorithms.formatDuration(cumulativeInfo.time, app.accessibilityEnabled())); + row.setOnClickListener(onClickListener); + return row; + } - public CumulativeInfo getRouteDirectionCumulativeInfo(int position) { - CumulativeInfo cumulativeInfo = new CumulativeInfo(); - for (int i = 0; i < position; i++) { - RouteDirectionInfo routeDirectionInfo = (RouteDirectionInfo) getItem(i); - cumulativeInfo.time += routeDirectionInfo.getExpectedTime(); - cumulativeInfo.distance += routeDirectionInfo.distance; - } - return cumulativeInfo; + public CumulativeInfo getRouteDirectionCumulativeInfo(int position, List routeDirections) { + CumulativeInfo cumulativeInfo = new CumulativeInfo(); + for (int i = position; i < routeDirections.size(); i++) { + RouteDirectionInfo routeDirectionInfo = routeDirections.get(i); + cumulativeInfo.time += routeDirectionInfo.getExpectedTime(); + cumulativeInfo.distance += routeDirectionInfo.distance; } + return cumulativeInfo; } private String getTimeDescription(RouteDirectionInfo model) { final int timeInSeconds = model.getExpectedTime(); - return Algorithms.formatDuration(timeInSeconds, getMyApplication().accessibilityEnabled()); + return Algorithms.formatDuration(timeInSeconds, app.accessibilityEnabled()); } void print() { - File file = generateRouteInfoHtml(adapter, helper.getGeneralRouteInformation()); + File file = generateRouteInfoHtml(routingHelper.getRouteDirections(), routingHelper.getGeneralRouteInformation()); if (file.exists()) { Uri uri = AndroidUtils.getUriForFile(getMyApplication(), file); Intent browserIntent; @@ -673,14 +1659,14 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { } } - private File generateRouteInfoHtml(RouteInfoAdapter routeInfo, String title) { + private File generateRouteInfoHtml(List directionsInfo, String title) { File file = null; - if (routeInfo == null) { + if (directionsInfo == null) { return file; } final String fileName = "route_info.html"; - StringBuilder html = generateHtmlPrint(routeInfo, title); + StringBuilder html = generateHtmlPrint(directionsInfo, title); FileOutputStream fos = null; try { file = getMyApplication().getAppPath(fileName); @@ -704,7 +1690,7 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { return file; } - private StringBuilder generateHtml(RouteInfoAdapter routeInfo, String title) { + private StringBuilder generateHtml(List directionInfos, String title) { StringBuilder html = new StringBuilder(); if (!TextUtils.isEmpty(title)) { html.append("

"); @@ -713,8 +1699,8 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { } final String NBSP = " "; final String BR = "
"; - for (int i = 0; i < routeInfo.getCount(); i++) { - RouteDirectionInfo routeDirectionInfo = (RouteDirectionInfo) routeInfo.getItem(i); + for (int i = 0; i < directionInfos.size(); i++) { + RouteDirectionInfo routeDirectionInfo = directionInfos.get(i); StringBuilder sb = new StringBuilder(); sb.append(OsmAndFormatter.getFormattedDistance(routeDirectionInfo.distance, getMyApplication())); sb.append(", ").append(NBSP); @@ -727,7 +1713,8 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { return html; } - private StringBuilder generateHtmlPrint(RouteInfoAdapter routeInfo, String title) { + private StringBuilder generateHtmlPrint(List directionsInfo, String title) { + boolean accessibilityEnabled = app.accessibilityEnabled(); StringBuilder html = new StringBuilder(); html.append(""); html.append(""); @@ -744,7 +1731,6 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { html.append(""); html.append(""); - if (!TextUtils.isEmpty(title)) { html.append("

"); html.append(title); @@ -753,8 +1739,8 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { html.append(""); final String NBSP = " "; final String BR = "
"; - for (int i = 0; i < routeInfo.getCount(); i++) { - RouteDirectionInfo routeDirectionInfo = (RouteDirectionInfo) routeInfo.getItem(i); + for (int i = 0; i < directionsInfo.size(); i++) { + RouteDirectionInfo routeDirectionInfo = directionsInfo.get(i); html.append(""); StringBuilder sb = new StringBuilder(); sb.append(OsmAndFormatter.getFormattedDistance(routeDirectionInfo.distance, getMyApplication())); @@ -766,20 +1752,18 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { html.append(""); String description = routeDirectionInfo.getDescriptionRoutePart(); html.append(""); - RouteInfoAdapter.CumulativeInfo cumulativeInfo = routeInfo.getRouteDirectionCumulativeInfo(i); + CumulativeInfo cumulativeInfo = getRouteDirectionCumulativeInfo(i, directionsInfo); html.append(""); @@ -791,4 +1775,425 @@ public class ShowRouteInfoDialogFragment extends DialogFragment { return html; } -} + private int getInitialMenuState() { + return MenuState.FULL_SCREEN; + } + + public boolean slideUp() { + int v = currentMenuState; + for (int i = 0; i < 2; i++) { + v = v << 1; + if ((v & getSupportedMenuStates()) != 0) { + currentMenuState = v; + return true; + } + } + return false; + } + + public boolean slideDown() { + int v = currentMenuState; + for (int i = 0; i < 2; i++) { + v = v >> 1; + if ((v & getSupportedMenuStates()) != 0) { + currentMenuState = v; + return true; + } + } + return false; + } + + public int getCurrentMenuState() { + return currentMenuState; + } + + public int getSupportedMenuStates() { + if (!portrait) { + return MenuState.FULL_SCREEN; + } else { + return getSupportedMenuStatesPortrait(); + } + } + + protected int getSupportedMenuStatesPortrait() { + return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN; + } + + public static boolean showInstance(final MapActivity mapActivity, int routeId) { + try { + Bundle args = new Bundle(); + args.putInt(ROUTE_ID_KEY, routeId); + + ShowRouteInfoDialogFragment fragment = new ShowRouteInfoDialogFragment(); + fragment.setArguments(args); + mapActivity.getSupportFragmentManager() + .beginTransaction() + .replace(R.id.routeMenuContainer, fragment, TAG) + .addToBackStack(TAG) + .commitAllowingStateLoss(); + + return true; + + } catch (RuntimeException e) { + return false; + } + } + + @Nullable + private MapActivity getMapActivity() { + FragmentActivity activity = getActivity(); + if (activity instanceof MapActivity) { + return (MapActivity) activity; + } else { + return null; + } + } + + @NonNull + private MapActivity requireMapActivity() { + FragmentActivity activity = getActivity(); + if (!(activity instanceof MapActivity)) { + throw new IllegalStateException("Fragment " + this + " not attached to an activity."); + } + return (MapActivity) activity; + } + + @Override + public void onResume() { + super.onResume(); + + ViewParent parent = view.getParent(); + if (parent != null && containerLayoutListener != null) { + ((View) parent).addOnLayoutChangeListener(containerLayoutListener); + } + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.getMapLayers().getMapControlsLayer().showMapControlsIfHidden(); + wasDrawerDisabled = mapActivity.isDrawerDisabled(); + if (!wasDrawerDisabled) { + mapActivity.disableDrawer(); + } + } + } + + @Override + public void onPause() { + super.onPause(); + if (view != null) { + ViewParent parent = view.getParent(); + if (parent != null && containerLayoutListener != null) { + ((View) parent).removeOnLayoutChangeListener(containerLayoutListener); + } + } + MapActivity mapActivity = getMapActivity(); + if (!wasDrawerDisabled && mapActivity != null) { + mapActivity.enableDrawer(); + } + } + + @Override + public int getStatusBarColorId() { + if (view != null) { + if (Build.VERSION.SDK_INT >= 23) { + view.setSystemUiVisibility(view.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } + return nightMode ? R.color.dialog_divider_dark : R.color.dialog_divider_light; + } + return -1; + } + + private int getViewY() { + return (int) mainView.getY(); + } + + private void setViewY(int y, boolean animated, boolean adjustMapPos) { + mainView.setY(y); + zoomButtonsView.setY(getZoomButtonsY(y)); + } + + private void updateZoomButtonsVisibility(int menuState) { + if (menuState == MenuController.MenuState.HEADER_ONLY) { + if (zoomButtonsView.getVisibility() != View.VISIBLE) { + zoomButtonsView.setVisibility(View.VISIBLE); + } + } else { + if (zoomButtonsView.getVisibility() == View.VISIBLE) { + zoomButtonsView.setVisibility(View.INVISIBLE); + } + } + } + + private void processScreenHeight(ViewParent parent) { + View container = (View) parent; + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + screenHeight = container.getHeight() + AndroidUtils.getStatusBarHeight(mapActivity); + viewHeight = screenHeight - AndroidUtils.getStatusBarHeight(mapActivity); + } + } + + private int getFullScreenTopPosY() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + return topShadowMargin + mapActivity.getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar); + } else { + return 0; + } + } + + private int addStatusBarHeightIfNeeded(int res) { + MapActivity mapActivity = getMapActivity(); + if (Build.VERSION.SDK_INT >= 21 && mapActivity != null) { + return res + AndroidUtils.getStatusBarHeight(mapActivity); + } + return res; + } + + private int getHeaderOnlyTopY() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + if (!menuCards.isEmpty()) { + return viewHeight - menuCards.get(0).getViewHeight() - shadowHeight; + } else { + return viewHeight - dpToPx(48f) - shadowHeight; + } + } else { + return 0; + } + } + + private int getMenuStatePosY(int menuState) { + if (!portrait) { + return topScreenPosY; + } + switch (menuState) { + case MenuState.HEADER_ONLY: + return getHeaderOnlyTopY(); + case MenuState.HALF_SCREEN: + return minHalfY; + case MenuState.FULL_SCREEN: + return getFullScreenTopPosY(); + default: + return 0; + } + } + + private void changeMenuState(int currentY, boolean slidingUp, boolean slidingDown) { + boolean needCloseMenu = false; + + int currentMenuState = getCurrentMenuState(); + if (portrait) { + int headerDist = Math.abs(currentY - getMenuStatePosY(MenuState.HEADER_ONLY)); + int halfDist = Math.abs(currentY - getMenuStatePosY(MenuState.HALF_SCREEN)); + int fullDist = Math.abs(currentY - getMenuStatePosY(MenuState.FULL_SCREEN)); + int newState; + if (headerDist < halfDist && headerDist < fullDist) { + newState = MenuState.HEADER_ONLY; + } else if (halfDist < headerDist && halfDist < fullDist) { + newState = MenuState.HALF_SCREEN; + } else { + newState = MenuState.FULL_SCREEN; + } + + if (slidingDown && currentMenuState == MenuState.FULL_SCREEN && getViewY() < getFullScreenTopPosY()) { + slidingDown = false; + newState = MenuState.FULL_SCREEN; + } + if (menuBottomViewHeight > 0 && slidingUp) { + while (getCurrentMenuState() != newState) { + if (!slideUp()) { + break; + } + } + } else if (slidingDown) { + if (currentMenuState == MenuState.HEADER_ONLY) { + needCloseMenu = true; + } else { + while (getCurrentMenuState() != newState) { + if (!slideDown()) { + needCloseMenu = true; + break; + } + } + } + } else { + if (currentMenuState < newState) { + while (getCurrentMenuState() != newState) { + if (!slideUp()) { + break; + } + } + } else { + while (getCurrentMenuState() != newState) { + if (!slideDown()) { + break; + } + } + } + } + } + int newMenuState = getCurrentMenuState(); + boolean needMapAdjust = currentMenuState != newMenuState && newMenuState != MenuState.FULL_SCREEN; + + applyPosY(currentY, needCloseMenu, needMapAdjust, currentMenuState, newMenuState, 0); + } + + + private int getPosY(final int currentY, boolean needCloseMenu, int previousState) { + if (needCloseMenu) { + return screenHeight; + } + MapActivity mapActivity = getMapActivity(); + if (mapActivity == null) { + return 0; + } + + int destinationState = getCurrentMenuState(); + updateZoomButtonsVisibility(destinationState); + + int posY = 0; + switch (destinationState) { + case MenuState.HEADER_ONLY: + posY = getMenuStatePosY(MenuState.HEADER_ONLY); + break; + case MenuState.HALF_SCREEN: + posY = getMenuStatePosY(MenuState.HALF_SCREEN); + break; + case MenuState.FULL_SCREEN: + if (currentY != CURRENT_Y_UNDEFINED) { + int maxPosY = viewHeight - menuFullHeightMax; + int minPosY = getMenuStatePosY(MenuState.FULL_SCREEN); + if (maxPosY > minPosY) { + maxPosY = minPosY; + } + if (currentY > minPosY || previousState != MenuState.FULL_SCREEN) { + posY = minPosY; + } else if (currentY < maxPosY) { + posY = maxPosY; + } else { + posY = currentY; + } + } else { + posY = getMenuStatePosY(MenuState.FULL_SCREEN); + } + break; + default: + break; + } + + return posY; + } + + private void updateMainViewLayout(int posY) { + MapActivity mapActivity = getMapActivity(); + if (view != null && mapActivity != null) { + ViewGroup.LayoutParams lp = mainView.getLayoutParams(); + lp.height = view.getHeight() - posY; + mainView.setLayoutParams(lp); + mainView.requestLayout(); + } + } + + private void applyPosY(final int currentY, final boolean needCloseMenu, boolean needMapAdjust, + final int previousMenuState, final int newMenuState, int dZoom) { + final int posY = getPosY(currentY, needCloseMenu, previousMenuState); + if (getViewY() != posY || dZoom != 0) { + if (posY < getViewY()) { + updateMainViewLayout(posY); + } + + mainView.animate().y(posY) + .setDuration(200) + .setInterpolator(new DecelerateInterpolator()) + .setListener(new AnimatorListenerAdapter() { + + boolean canceled = false; + + @Override + public void onAnimationCancel(Animator animation) { + canceled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (!canceled) { + if (needCloseMenu) { + dismiss(); + } else { + updateMainViewLayout(posY); + if (previousMenuState != 0 && newMenuState != 0 && previousMenuState != newMenuState) { + doAfterMenuStateChange(previousMenuState, newMenuState); + } + } + } + } + }).start(); + + zoomButtonsView.animate().y(getZoomButtonsY(posY)) + .setDuration(200) + .setInterpolator(new DecelerateInterpolator()) + .start(); + } + } + + private int getZoomButtonsY(int y) { + return y - zoomButtonsHeight - shadowHeight; + } + + private void doAfterMenuStateChange(int previousState, int newState) { + runLayoutListener(); + } + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) + private void runLayoutListener() { + if (view != null) { + ViewTreeObserver vto = view.getViewTreeObserver(); + vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (view != null) { + ViewTreeObserver obs = view.getViewTreeObserver(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + obs.removeOnGlobalLayoutListener(this); + } else { + obs.removeGlobalOnLayoutListener(this); + } + + if (getActivity() == null) { + return; + } + zoomButtonsHeight = zoomButtonsView.getHeight(); + + menuFullHeight = mainView.getHeight(); + menuBottomViewHeight = menuFullHeight; + + menuFullHeightMax = view.findViewById(R.id.route_menu_cards_container).getHeight(); + + if (!moving) { + doLayoutMenu(); + } + initLayout = false; + } + } + }); + } + } + + private void doLayoutMenu() { + final int posY = getPosY(getViewY(), false, getCurrentMenuState()); + setViewY(posY, true, !initLayout); + updateMainViewLayout(posY); + } + + public void dismiss() { + FragmentActivity activity = getActivity(); + if (activity != null) { + try { + activity.getSupportFragmentManager().popBackStack(TAG, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + } catch (Exception e) { + // + } + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/dashboard/DashNavigationFragment.java b/OsmAnd/src/net/osmand/plus/dashboard/DashNavigationFragment.java index 02b229732e..d4b70a9975 100644 --- a/OsmAnd/src/net/osmand/plus/dashboard/DashNavigationFragment.java +++ b/OsmAnd/src/net/osmand/plus/dashboard/DashNavigationFragment.java @@ -1,5 +1,6 @@ package net.osmand.plus.dashboard; +import android.app.Activity; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.Nullable; @@ -39,8 +40,10 @@ public class DashNavigationFragment extends DashBaseFragment { (view.findViewById(R.id.show_all)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - - ShowRouteInfoDialogFragment.showDialog(getActivity().getSupportFragmentManager()); + Activity activity = getActivity(); + if (activity instanceof MapActivity) { + ShowRouteInfoDialogFragment.showInstance((MapActivity) activity, -1); + } } }); return view; diff --git a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java index 84b93a5c12..4fc6583056 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/GpxUiHelper.java @@ -9,6 +9,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; +import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -37,12 +38,16 @@ import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; +import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -86,7 +91,9 @@ import net.osmand.plus.dialogs.ConfigureMapMenu.GpxAppearanceAdapter; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.render.RenderingRuleProperty; +import net.osmand.render.RenderingRuleSearchRequest; import net.osmand.render.RenderingRulesStorage; +import net.osmand.router.RouteStatistics; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; @@ -1040,7 +1047,7 @@ public class GpxUiHelper { legend.setEnabled(false); } - private static float setupXAxisDistance(OsmandApplication ctx, XAxis xAxis, float meters) { + private static float setupAxisDistance(OsmandApplication ctx, AxisBase axisBase, float meters) { OsmandSettings settings = ctx.getSettings(); OsmandSettings.MetricsConstants mc = settings.METRIC_SYSTEM.get(); float divX; @@ -1099,8 +1106,8 @@ public class GpxUiHelper { final String formatX = fmt; final String mainUnitX = ctx.getString(mainUnitStr); - xAxis.setGranularity(granularity); - xAxis.setValueFormatter(new IAxisValueFormatter() { + axisBase.setGranularity(granularity); + axisBase.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { @@ -1191,6 +1198,114 @@ public class GpxUiHelper { return values; } + public static void setupHorizontalGPXChart(HorizontalBarChart chart, int yLabelsCount, float topOffset, float bottomOffset, boolean useGesturesAndScale) { + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + chart.setHardwareAccelerationEnabled(false); + } else { + chart.setHardwareAccelerationEnabled(true); + } + chart.setTouchEnabled(useGesturesAndScale); + chart.setDragEnabled(useGesturesAndScale); + chart.setScaleYEnabled(false); + chart.setAutoScaleMinMaxEnabled(true); + chart.setDrawBorders(false); + chart.getDescription().setEnabled(false); + chart.setDragDecelerationEnabled(false); + + chart.setExtraTopOffset(topOffset); + chart.setExtraBottomOffset(bottomOffset); + + XAxis xl = chart.getXAxis(); + xl.setDrawLabels(false); + xl.setEnabled(false); + xl.setDrawAxisLine(false); + xl.setDrawGridLines(false); + + YAxis yl = chart.getAxisLeft(); + yl.setLabelCount(yLabelsCount); + yl.setDrawLabels(false); + yl.setEnabled(false); + yl.setDrawAxisLine(false); + yl.setDrawGridLines(false); + yl.setAxisMinimum(0f); + + YAxis yr = chart.getAxisRight(); + yr.setLabelCount(yLabelsCount); + yr.setDrawAxisLine(false); + yr.setDrawGridLines(false); + yr.setAxisMinimum(0f); + + chart.setFitBars(true); + + Legend l = chart.getLegend(); + l.setEnabled(false); + } + + public static BarData buildStatisticChart(@NonNull OsmandApplication app, + @NonNull HorizontalBarChart mChart, + @NonNull RouteStatistics.Statistics routeStatistics, + @NonNull GPXTrackAnalysis analysis, + boolean useRightAxis, + boolean nightMode) { + + XAxis xAxis = mChart.getXAxis(); + xAxis.setEnabled(false); + + YAxis yAxis; + if (useRightAxis) { + yAxis = mChart.getAxisRight(); + yAxis.setEnabled(true); + } else { + yAxis = mChart.getAxisLeft(); + } + float divX = setupAxisDistance(app, yAxis, analysis.totalDistance); + + List> segments = routeStatistics.getElements(); + List entries = new ArrayList<>(); + float[] stacks = new float[segments.size()]; + int[] colors = new int[segments.size()]; + for (int i = 0; i < stacks.length; i++) { + RouteStatistics.RouteSegmentAttribute segment = segments.get(i); + stacks[i] = segment.getDistance() / divX; + colors[i] = getColorFromRouteSegmentAttribute(app, segment, nightMode); + } + entries.add(new BarEntry(0, stacks)); + BarDataSet barDataSet = new BarDataSet(entries, ""); + barDataSet.setColors(colors); + BarData dataSet = new BarData(barDataSet); + dataSet.setDrawValues(false); + + mChart.getAxisRight().setAxisMaximum(dataSet.getYMax()); + mChart.getAxisLeft().setAxisMaximum(dataSet.getYMax()); + + return dataSet; + } + + public static int getColorFromRouteSegmentAttribute(OsmandApplication app, RouteStatistics.RouteSegmentAttribute segment, boolean nightMode) { + String colorAttrName = segment.getColorAttrName(); + String colorName = segment.getColorName(); + int color = 0; + if (colorName != null) { + try { + color = Color.parseColor(colorName); + } catch (Exception e) { + } + } else if (colorAttrName != null) { + color = GpxUiHelper.getColorFromStyle(app, colorAttrName, nightMode); + } + return color; + } + + public static int getColorFromStyle(OsmandApplication app, String colorAttrName, boolean nightMode) { + RenderingRulesStorage rrs = app.getRendererRegistry().getCurrentSelectedRenderer(); + RenderingRuleSearchRequest req = new RenderingRuleSearchRequest(rrs); + req.setBooleanFilter(rrs.PROPS.R_NIGHT_MODE, nightMode); + if (req.searchRenderingAttribute(colorAttrName)) { + return req.getIntPropertyValue(rrs.PROPS.R_ATTR_COLOR_VALUE); + } + return 0; + } + public static OrderedLineDataSet createGPXElevationDataSet(@NonNull OsmandApplication ctx, @NonNull LineChart mChart, @NonNull GPXTrackAnalysis analysis, @@ -1208,7 +1323,7 @@ public class GpxUiHelper { if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) { divX = setupXAxisTime(xAxis, analysis.timeSpan); } else { - divX = setupXAxisDistance(ctx, xAxis, analysis.totalDistance); + divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance); } final String mainUnitY = useFeet ? ctx.getString(R.string.foot) : ctx.getString(R.string.m); @@ -1292,7 +1407,7 @@ public class GpxUiHelper { if (axisType == GPXDataSetAxisType.TIME && analysis.isTimeSpecified()) { divX = setupXAxisTime(xAxis, analysis.timeSpan); } else { - divX = setupXAxisDistance(ctx, xAxis, analysis.totalDistance); + divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance); } OsmandSettings.SpeedConstants sps = settings.SPEED_SYSTEM.get(); @@ -1445,7 +1560,7 @@ public class GpxUiHelper { final float totalDistance = analysis.totalDistance; XAxis xAxis = mChart.getXAxis(); - float divX = setupXAxisDistance(ctx, xAxis, analysis.totalDistance); + float divX = setupAxisDistance(ctx, xAxis, analysis.totalDistance); final String mainUnitY = "%"; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java index 9b1ae5e72f..3e31469a53 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java @@ -3,6 +3,7 @@ package net.osmand.plus.mapcontextmenu; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.TargetApi; +import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.drawable.Drawable; @@ -484,10 +485,13 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo zoomInButtonView = (ImageButton) view.findViewById(R.id.context_menu_zoom_in_button); zoomOutButtonView = (ImageButton) view.findViewById(R.id.context_menu_zoom_out_button); if (menu.zoomButtonsVisible()) { - updateImageButton(zoomInButtonView, R.drawable.map_zoom_in, R.drawable.map_zoom_in_night, - R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); - updateImageButton(zoomOutButtonView, R.drawable.map_zoom_out, R.drawable.map_zoom_out_night, - R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); + Context ctx = getContext(); + if (ctx != null) { + AndroidUtils.updateImageButton(ctx, zoomInButtonView, R.drawable.map_zoom_in, R.drawable.map_zoom_in_night, + R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); + AndroidUtils.updateImageButton(ctx, zoomOutButtonView, R.drawable.map_zoom_out, R.drawable.map_zoom_out_night, + R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); + } zoomInButtonView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index aa2bfb5c39..e9d029ed40 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -168,14 +168,14 @@ public class MenuBuilder { private boolean collapsed; private CollapseExpandListener collapseExpandListener; - public CollapsableView(@NonNull View contenView, @NonNull MenuBuilder menuBuilder, + public CollapsableView(@NonNull View contenView, MenuBuilder menuBuilder, @NonNull OsmandPreference collapsedPref) { this.contenView = contenView; this.menuBuilder = menuBuilder; this.collapsedPref = collapsedPref; } - public CollapsableView(@NonNull View contenView, @NonNull MenuBuilder menuBuilder, boolean collapsed) { + public CollapsableView(@NonNull View contenView, MenuBuilder menuBuilder, boolean collapsed) { this.contenView = contenView; this.collapsed = collapsed; this.menuBuilder = menuBuilder; @@ -202,7 +202,7 @@ public class MenuBuilder { if (collapseExpandListener != null) { collapseExpandListener.onCollapseExpand(collapsed); } - if (menuBuilder.collapseExpandListener != null) { + if (menuBuilder != null && menuBuilder.collapseExpandListener != null) { menuBuilder.collapseExpandListener.onCollapseExpand(collapsed); } } @@ -770,26 +770,8 @@ public class MenuBuilder { } } - private String adjustRouteRef(String ref) { - if (ref != null) { - int charPos = ref.lastIndexOf(':'); - if (charPos != -1) { - ref = ref.substring(0, charPos); - } - if (ref.length() > 4) { - ref = ref.substring(0, 4); - } - } - return ref; - } - public int dpToPx(float dp) { - Resources r = app.getResources(); - return (int) TypedValue.applyDimension( - COMPLEX_UNIT_DIP, - dp, - r.getDisplayMetrics() - ); + return AndroidUtils.dpToPx(app, dp); } public Drawable getCollapseIcon(boolean collapsed) { @@ -823,7 +805,7 @@ public class MenuBuilder { transportRect.setTextColor(UiUtilities.getContrastColor(app, bgColor, true)); transportRect.setBackgroundDrawable(shape); - transportRect.setText(adjustRouteRef(route.route.getRef())); + transportRect.setText(route.route.getAdjustedRouteRef()); baseView.addView(transportRect); LinearLayout infoView = new LinearLayout(view.getContext()); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java index 533d7dfcad..fea72f9462 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java @@ -2,7 +2,6 @@ package net.osmand.plus.routepreparationmenu; import android.Manifest; import android.graphics.drawable.Drawable; -import android.os.Build; import android.os.Bundle; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; @@ -28,6 +27,7 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.ShowRouteInfoDialogFragment; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.routepreparationmenu.cards.PublicTransportCard; @@ -115,9 +115,9 @@ public class ChooseRouteFragment extends BaseOsmAndFragment { ImageButton zoomOutButtonView = (ImageButton) view.findViewById(R.id.map_zoom_out_button); myLocButtonView = (ImageButton) view.findViewById(R.id.map_my_location_button); if (portrait) { - updateImageButton(zoomInButtonView, R.drawable.map_zoom_in, R.drawable.map_zoom_in_night, + AndroidUtils.updateImageButton(mapActivity, zoomInButtonView, R.drawable.map_zoom_in, R.drawable.map_zoom_in_night, R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); - updateImageButton(zoomOutButtonView, R.drawable.map_zoom_out, R.drawable.map_zoom_out_night, + AndroidUtils.updateImageButton(mapActivity,zoomOutButtonView, R.drawable.map_zoom_out, R.drawable.map_zoom_out_night, R.drawable.btn_circle_trans, R.drawable.btn_circle_night, nightMode); zoomInButtonView.setOnClickListener(new View.OnClickListener() { @Override @@ -273,16 +273,6 @@ public class ChooseRouteFragment extends BaseOsmAndFragment { getMapActivity().changeZoom(-1, System.currentTimeMillis()); } - private void updateImageButton(ImageButton button, int iconLightId, int iconDarkId, int bgLightId, int bgDarkId, boolean night) { - button.setImageDrawable(getMapActivity().getMyApplication().getUIUtilities().getIcon(night ? iconDarkId : iconLightId)); - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { - button.setBackground(getMapActivity().getResources().getDrawable(night ? bgDarkId : bgLightId, - getMapActivity().getTheme())); - } else { - button.setBackgroundDrawable(getMapActivity().getResources().getDrawable(night ? bgDarkId : bgLightId)); - } - } - @Override protected Drawable getContentIcon(@DrawableRes int id) { return getIcon(id, nightMode ? R.color.ctx_menu_info_text_dark : R.color.icon_color); @@ -304,7 +294,7 @@ public class ChooseRouteFragment extends BaseOsmAndFragment { try { fragment.setRetainInstance(true); fragmentManager.beginTransaction() - .add(R.id.fragmentContainer, fragment, ChooseRouteFragment.TAG) + .add(R.id.routeMenuContainer, fragment, ChooseRouteFragment.TAG) .commitAllowingStateLoss(); return true; } catch (Exception e) { @@ -355,8 +345,12 @@ public class ChooseRouteFragment extends BaseOsmAndFragment { view.findViewById(R.id.details_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mapActivity.getMyApplication().getTransportRoutingHelper().setCurrentRoute(cards.get(position).getRouteId()); - mapActivity.getMapView().refreshMap(true); + if (position < cards.size()) { + int routeId = cards.get(position).getRouteId(); + mapActivity.getMyApplication().getTransportRoutingHelper().setCurrentRoute(routeId); + mapActivity.getMapView().refreshMap(true); + ShowRouteInfoDialogFragment.showInstance(mapActivity, routeId); + } } }); view.findViewById(R.id.show_button).setOnClickListener(new View.OnClickListener() { diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index 07745df707..4f219a0dc0 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -1038,7 +1038,7 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener viaLayout.setVisibility(View.VISIBLE); viaLayoutDivider.setVisibility(View.VISIBLE); ((TextView) mainView.findViewById(R.id.ViaView)).setText(via); - ((TextView) mainView.findViewById(R.id.ViaSubView)).setText(app.getString(R.string.intermediate_destinations, getTargets().getIntermediatePoints().size())); + ((TextView) mainView.findViewById(R.id.ViaSubView)).setText(app.getString(R.string.intermediate_destinations) + ": " + getTargets().getIntermediatePoints().size()); } FrameLayout viaButton = (FrameLayout) mainView.findViewById(R.id.via_button); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/WaypointsFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/WaypointsFragment.java index 19f702d1a2..3594c3b60c 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/WaypointsFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/WaypointsFragment.java @@ -595,7 +595,8 @@ public class WaypointsFragment extends BaseOsmAndFragment implements ObservableS private void updateTitle() { final TextViewEx title = (TextViewEx) view.findViewById(R.id.title); int pointsSize = app.getTargetPointsHelper().getAllPoints().size(); - title.setText(app.getString(R.string.waypoints, (pointsSize != 0 ? pointsSize : 1))); + String text = getString(R.string.shared_string_waypoints) + ": " + (pointsSize != 0 ? pointsSize : 1); + title.setText(text); } private void applyPointsChanges() { @@ -861,8 +862,7 @@ public class WaypointsFragment extends BaseOsmAndFragment implements ObservableS return new PointDescription(PointDescription.POINT_TYPE_TARGET, ctx.getString(R.string.route_descr_destination) + ":", point.getOnlyName()); } else { - return new PointDescription(PointDescription.POINT_TYPE_TARGET, ctx.getString(R.string.intermediate_waypoint, "" + (point.index + 1)), - point.getOnlyName()); + return new PointDescription(PointDescription.POINT_TYPE_TARGET, ctx.getString(R.string.intermediate_waypoint) + ": " + (point.index + 1), point.getOnlyName()); } } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java index ff0660bf1e..44201e7f88 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/BaseCard.java @@ -39,6 +39,10 @@ public abstract class BaseCard { public abstract int getCardLayoutId(); + public int getViewHeight() { + return view != null ? view.getHeight() : 0; + } + public void update() { if (view != null) { updateContent(); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java index 49cfc15399..9ab50066ae 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/PublicTransportCard.java @@ -15,15 +15,14 @@ import android.widget.TextView; import net.osmand.AndroidUtils; import net.osmand.data.TransportRoute; -import net.osmand.data.TransportStop; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.activities.ShowRouteInfoDialogFragment; import net.osmand.plus.helpers.FontCache; -import net.osmand.plus.widgets.FlowLayout; import net.osmand.plus.transport.TransportStopRoute; -import net.osmand.plus.transport.TransportStopType; +import net.osmand.plus.widgets.FlowLayout; import net.osmand.plus.widgets.style.CustomTypefaceSpan; import net.osmand.router.TransportRoutePlanner.TransportRouteResult; import net.osmand.router.TransportRoutePlanner.TransportRouteResultSegment; @@ -69,6 +68,7 @@ public class PublicTransportCard extends BaseCard { public void onClick(View v) { app.getTransportRoutingHelper().setCurrentRoute(routeId); getMapActivity().refreshMap(); + ShowRouteInfoDialogFragment.showInstance(mapActivity, routeId); } }); view.findViewById(R.id.bottom_shadow).setVisibility(showBottomShadow ? View.VISIBLE : View.GONE); @@ -129,7 +129,7 @@ public class PublicTransportCard extends BaseCard { String firstLine = app.getString(R.string.route_from) + " " + name; if (segments.size() > 1) { - firstLine += ", " + app.getString(R.string.transfers, (segments.size() - 1)); + firstLine += ", " + app.getString(R.string.transfers) +": "+(segments.size() - 1); } SpannableString firstLineDesc = new SpannableString(firstLine); @@ -146,9 +146,9 @@ public class PublicTransportCard extends BaseCard { Typeface typeface = FontCache.getRobotoMedium(app); String travelTime = OsmAndFormatter.getFormattedDuration((int) routeResult.getTravelTime(), app); String walkTime = OsmAndFormatter.getFormattedDuration((int) routeResult.getWalkTime(), app); - String walkDistance = OsmAndFormatter.getFormattedDistance((int) routeResult.getTravelDist(), app); + String walkDistance = OsmAndFormatter.getFormattedDistance((int) routeResult.getWalkDist(), app); - String secondLine = app.getString(R.string.route_way, travelTime) + " • " + app.getString(R.string.on_foot, walkTime) + " • " + walkDistance; + String secondLine = app.getString(R.string.route_way) + ": " + travelTime + " • " + app.getString(R.string.on_foot) + ": " + walkTime + " • " + walkDistance; SpannableString secondLineDesc = new SpannableString(secondLine); @@ -172,7 +172,7 @@ public class PublicTransportCard extends BaseCard { Iterator iterator = segments.iterator(); while (iterator.hasNext()) { TransportRouteResultSegment s = iterator.next(); - if (s.walkDist != 0) { + if (s.walkDist > 0) { double walkTime = getWalkTime(s.walkDist, routeResult.getWalkSpeed()); if (walkTime > MIN_WALK_TIME) { String walkTimeS = OsmAndFormatter.getFormattedDuration((int) walkTime, app); @@ -201,7 +201,7 @@ public class PublicTransportCard extends BaseCard { LinearLayout convertView = (LinearLayout) getMapActivity().getLayoutInflater().inflate(R.layout.transport_stop_route_item_with_icon, null, false); if (segment != null) { TransportRoute transportRoute = segment.route; - TransportStopRoute transportStopRoute = getTransportStopRoute(transportRoute, segment.getStart()); + TransportStopRoute transportStopRoute = TransportStopRoute.getTransportStopRoute(transportRoute, segment.getStart()); String routeRef = segment.route.getAdjustedRouteRef(); int bgColor = transportStopRoute.getColor(app, nightMode); @@ -209,7 +209,8 @@ public class PublicTransportCard extends BaseCard { TextView transportStopRouteTextView = (TextView) convertView.findViewById(R.id.transport_stop_route_text); ImageView transportStopRouteImageView = (ImageView) convertView.findViewById(R.id.transport_stop_route_icon); - transportStopRouteImageView.setImageDrawable(app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_bus_dark, UiUtilities.getContrastColor(app, bgColor, true))); + int drawableResId = transportStopRoute.type == null ? R.drawable.ic_action_bus_dark : transportStopRoute.type.getResourceId(); + transportStopRouteImageView.setImageDrawable(app.getUIUtilities().getPaintedIcon(drawableResId, UiUtilities.getContrastColor(app, bgColor, true))); transportStopRouteTextView.setText(routeRef); GradientDrawable gradientDrawableBg = (GradientDrawable) convertView.getBackground(); gradientDrawableBg.setColor(bgColor); @@ -227,11 +228,11 @@ public class PublicTransportCard extends BaseCard { TextView transportStopRouteTextView = (TextView) convertView.findViewById(R.id.transport_stop_route_text); ImageView transportStopRouteImageView = (ImageView) convertView.findViewById(R.id.transport_stop_route_icon); - transportStopRouteImageView.setImageDrawable(getActiveIcon(R.drawable.ic_action_pedestrian_dark)); + transportStopRouteImageView.setImageDrawable(getColoredIcon(R.drawable.ic_action_pedestrian_dark, nightMode ? R.color.ctx_menu_bottom_view_url_color_dark : R.color.ctx_menu_bottom_view_url_color_light )); transportStopRouteTextView.setText(walkTime); GradientDrawable gradientDrawableBg = (GradientDrawable) convertView.getBackground(); gradientDrawableBg.setColor(bgColor); - transportStopRouteTextView.setTextColor(bgColor); + transportStopRouteTextView.setTextColor(ContextCompat.getColor(app, nightMode ? R.color.ctx_menu_bottom_view_url_color_dark : R.color.ctx_menu_bottom_view_url_color_light)); AndroidUtils.setBackground(app, convertView, nightMode, R.drawable.btn_border_active_light, R.drawable.btn_border_active_dark); } @@ -242,22 +243,11 @@ public class PublicTransportCard extends BaseCard { private View createArrow() { LinearLayout container = new LinearLayout(app); ImageView arrow = new ImageView(app); - arrow.setImageDrawable(getContentIcon(R.drawable.ic_arrow_forward)); + arrow.setImageDrawable(getContentIcon(R.drawable.ic_action_arrow_forward_16)); container.addView(arrow, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, AndroidUtils.dpToPx(app, 28))); return container; } - private TransportStopRoute getTransportStopRoute(TransportRoute rs, TransportStop s) { - TransportStopType type = TransportStopType.findType(rs.getType()); - TransportStopRoute r = new TransportStopRoute(); - r.type = type; - r.desc = rs.getName(); - r.route = rs; - r.stop = s; - r.refStop = s; - return r; - } - private double getWalkTime(double walkDist, double walkSpeed) { return walkDist / walkSpeed; } diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java new file mode 100644 index 0000000000..790faa7973 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteInfoCard.java @@ -0,0 +1,116 @@ +package net.osmand.plus.routepreparationmenu.cards; + +import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.style.StyleSpan; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.data.BarData; + +import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.router.RouteStatistics; +import net.osmand.util.Algorithms; + +import java.util.Map; + +public class RouteInfoCard extends BaseCard { + + private MapActivity mapActivity; + private RouteStatistics.Statistics routeStatistics; + private GPXUtilities.GPXTrackAnalysis analysis; + + public RouteInfoCard(MapActivity mapActivity, RouteStatistics.Statistics routeStatistics, GPXUtilities.GPXTrackAnalysis analysis) { + super(mapActivity); + this.mapActivity = mapActivity; + this.routeStatistics = routeStatistics; + this.analysis = analysis; + } + + @Override + public int getCardLayoutId() { + return R.layout.route_info_card; + } + + @Override + protected void updateContent() { + updateTitle(); + final HorizontalBarChart chart = (HorizontalBarChart) view.findViewById(R.id.chart); + GpxUiHelper.setupHorizontalGPXChart(chart, 5, 10, 10, true); + BarData barData = GpxUiHelper.buildStatisticChart(app, chart, routeStatistics, analysis, true, nightMode); + chart.setData(barData); + LinearLayout container = view.findViewById(R.id.route_items); + attachLegend(container, routeStatistics); + } + + @Override + protected void applyDayNightMode() { + view.setBackgroundColor(ContextCompat.getColor(mapActivity, nightMode ? R.color.route_info_bg_dark : R.color.route_info_bg_light)); + TextView details = (TextView) view.findViewById(R.id.info_type_details); + details.setTextColor(ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_dark : R.color.active_buttons_and_links_light)); + TextView title = (TextView) view.findViewById(R.id.info_type_title); + AndroidUtils.setTextPrimaryColor(app, title, nightMode); + } + + private void updateTitle() { + TextView title = (TextView) view.findViewById(R.id.info_type_title); + String name = getInfoType(); + title.setText(name); + } + + private String getInfoType() { + if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.CLASS) { + return app.getString(R.string.road_types); + } else if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.STEEPNESS) { + return app.getString(R.string.route_steepness_stat_container); + } else if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.SMOOTHNESS) { + return app.getString(R.string.route_smoothness_stat_container); + } else if (routeStatistics.getStatisticType() == RouteStatistics.StatisticType.SURFACE) { + return app.getString(R.string.route_surface_stat_container); + } else { + return ""; + } + } + + private void attachLegend(ViewGroup container, RouteStatistics.Statistics routeStatistics) { + Map> partition = routeStatistics.getPartition(); + for (E key : partition.keySet()) { + RouteStatistics.RouteSegmentAttribute segment = partition.get(key); + int color = GpxUiHelper.getColorFromRouteSegmentAttribute(app, segment, nightMode); + Drawable circle = app.getUIUtilities().getPaintedIcon(R.drawable.ic_action_circle, color); + Spannable text = getSpanLegend(key.toString(), segment); + + TextView legend = new TextView(app); + AndroidUtils.setTextPrimaryColor(app, legend, nightMode); + legend.setTextSize(15); + legend.setGravity(Gravity.CENTER_VERTICAL); + legend.setCompoundDrawablePadding(AndroidUtils.dpToPx(app, 16)); + legend.setPadding(AndroidUtils.dpToPx(app, 16), AndroidUtils.dpToPx(app, 4), AndroidUtils.dpToPx(app, 16), AndroidUtils.dpToPx(app, 4)); + legend.setCompoundDrawablesWithIntrinsicBounds(circle, null, null, null); + legend.setText(text); + + container.addView(legend); + } + } + + private Spannable getSpanLegend(String title, RouteStatistics.RouteSegmentAttribute segment) { + String formattedDistance = OsmAndFormatter.getFormattedDistance(segment.getDistance(), getMyApplication()); + title = Algorithms.capitalizeFirstLetter(title); + SpannableStringBuilder spannable = new SpannableStringBuilder(title); + spannable.append(": "); + spannable.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.append(formattedDistance); + + return spannable; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java new file mode 100644 index 0000000000..1e2aacd29d --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/RouteStatisticCard.java @@ -0,0 +1,221 @@ +package net.osmand.plus.routepreparationmenu.cards; + +import android.graphics.Matrix; +import android.support.v4.content.ContextCompat; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.listener.ChartTouchListener; +import com.github.mikephil.charting.listener.OnChartGestureListener; + +import net.osmand.AndroidUtils; +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.plus.GpxSelectionHelper; +import net.osmand.plus.OsmAndFormatter; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.routing.RoutingHelper; + +import java.util.ArrayList; +import java.util.List; + +public class RouteStatisticCard extends BaseCard { + + private MapActivity mapActivity; + private GPXFile gpx; + private GpxSelectionHelper.GpxDisplayItem gpxItem; + private GpxUiHelper.OrderedLineDataSet slopeDataSet; + private GpxUiHelper.OrderedLineDataSet elevationDataSet; + private View.OnTouchListener onTouchListener; + + public RouteStatisticCard(MapActivity mapActivity, GPXFile gpx, View.OnTouchListener onTouchListener) { + super(mapActivity); + this.mapActivity = mapActivity; + this.gpx = gpx; + this.onTouchListener = onTouchListener; + makeGpxDisplayItem(); + } + + @Override + public int getCardLayoutId() { + return R.layout.route_info_header; + } + + @Override + protected void updateContent() { + RoutingHelper routingHelper = mapActivity.getRoutingHelper(); + + view.setBackgroundColor(ContextCompat.getColor(mapActivity, nightMode ? R.color.route_info_bg_dark : R.color.route_info_bg_light)); + + OsmandApplication app = getMyApplication(); + + ((ImageView) view.findViewById(R.id.distance_icon)).setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_route_distance)); + ((ImageView) view.findViewById(R.id.time_icon)).setImageDrawable(app.getUIUtilities().getThemedIcon(R.drawable.ic_action_time_span)); + + int dist = routingHelper.getLeftDistance(); + int time = routingHelper.getLeftTime(); + int hours = time / (60 * 60); + int minutes = (time / 60) % 60; + TextView distanceTv = (TextView) view.findViewById(R.id.distance); + AndroidUtils.setTextSecondaryColor(app, distanceTv, nightMode); + String text = OsmAndFormatter.getFormattedDistance(dist, app); + SpannableStringBuilder distanceStr = new SpannableStringBuilder(text); + int spaceIndex = text.indexOf(" "); + if (spaceIndex != -1) { + distanceStr.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), 0, spaceIndex, 0); + } + distanceTv.setText(distanceStr); + SpannableStringBuilder timeStr = new SpannableStringBuilder(); + if (hours > 0) { + timeStr.append(String.valueOf(hours)).append(" ").append(app.getString(R.string.osmand_parking_hour)).append(" "); + } + if (minutes > 0) { + timeStr.append(String.valueOf(minutes)).append(" ").append(app.getString(R.string.osmand_parking_minute)); + } + spaceIndex = timeStr.toString().lastIndexOf(" "); + if (spaceIndex != -1) { + timeStr.setSpan(new ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), 0, spaceIndex, 0); + } + TextView timeTv = (TextView) view.findViewById(R.id.time); + AndroidUtils.setTextSecondaryColor(app, timeTv, nightMode); + timeTv.setText(timeStr); + + TextView arriveTimeTv = (TextView) view.findViewById(R.id.time_desc); + String arriveStr = app.getString(R.string.arrive_at_time, OsmAndFormatter.getFormattedTime(time, true)); + arriveTimeTv.setText(arriveStr); + + GPXUtilities.GPXTrackAnalysis analysis = gpx.getAnalysis(0); + + buildHeader(analysis); + + ((TextView) view.findViewById(R.id.average_text)).setText(OsmAndFormatter.getFormattedAlt(analysis.avgElevation, app)); + + String min = OsmAndFormatter.getFormattedAlt(analysis.minElevation, app); + String max = OsmAndFormatter.getFormattedAlt(analysis.maxElevation, app); + ((TextView) view.findViewById(R.id.range_text)).setText(min + " - " + max); + + String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app); + String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app); + ((TextView) view.findViewById(R.id.descent_text)).setText(desc); + ((TextView) view.findViewById(R.id.ascent_text)).setText(asc); + + ((ImageView) view.findViewById(R.id.average_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_altitude_average)); + ((ImageView) view.findViewById(R.id.range_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_altitude_average)); + ((ImageView) view.findViewById(R.id.descent_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_altitude_descent)); + ((ImageView) view.findViewById(R.id.ascent_icon)).setImageDrawable(getContentIcon(R.drawable.ic_action_altitude_ascent)); + } + + @Override + protected void applyDayNightMode() { + } + + public GpxUiHelper.OrderedLineDataSet getSlopeDataSet() { + return slopeDataSet; + } + + public GpxUiHelper.OrderedLineDataSet getElevationDataSet() { + return elevationDataSet; + } + + private void makeGpxDisplayItem() { + String groupName = getMyApplication().getString(R.string.current_route); + GpxSelectionHelper.GpxDisplayGroup group = getMyApplication().getSelectedGpxHelper().buildGpxDisplayGroup(gpx, 0, groupName); + if (group != null && group.getModifiableList().size() > 0) { + gpxItem = group.getModifiableList().get(0); + if (gpxItem != null) { + gpxItem.route = true; + } + } + } + + private void buildHeader(GPXUtilities.GPXTrackAnalysis analysis) { + final LineChart mChart = (LineChart) view.findViewById(R.id.chart); + GpxUiHelper.setupGPXChart(app, mChart, 4); + mChart.setOnTouchListener(onTouchListener); + + if (analysis.hasElevationData) { + List dataSets = new ArrayList<>(); + elevationDataSet = GpxUiHelper.createGPXElevationDataSet(app, mChart, analysis, + GpxUiHelper.GPXDataSetAxisType.DISTANCE, false, true); + if (elevationDataSet != null) { + dataSets.add(elevationDataSet); + } + slopeDataSet = GpxUiHelper.createGPXSlopeDataSet(app, mChart, analysis, + GpxUiHelper.GPXDataSetAxisType.DISTANCE, elevationDataSet.getValues(), true, true); + if (slopeDataSet != null) { + dataSets.add(slopeDataSet); + } + LineData data = new LineData(dataSets); + mChart.setData(data); + + mChart.setOnChartGestureListener(new OnChartGestureListener() { + + float highlightDrawX = -1; + + @Override + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + if (mChart.getHighlighted() != null && mChart.getHighlighted().length > 0) { + highlightDrawX = mChart.getHighlighted()[0].getDrawX(); + } else { + highlightDrawX = -1; + } + } + + @Override + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + gpxItem.chartMatrix = new Matrix(mChart.getViewPortHandler().getMatrixTouch()); + Highlight[] highlights = mChart.getHighlighted(); + if (highlights != null && highlights.length > 0) { + gpxItem.chartHighlightPos = highlights[0].getX(); + } else { + gpxItem.chartHighlightPos = -1; + } + } + + @Override + public void onChartLongPressed(MotionEvent me) { + } + + @Override + public void onChartDoubleTapped(MotionEvent me) { + } + + @Override + public void onChartSingleTapped(MotionEvent me) { + } + + @Override + public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { + } + + @Override + public void onChartScale(MotionEvent me, float scaleX, float scaleY) { + } + + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + if (highlightDrawX != -1) { + Highlight h = mChart.getHighlightByTouchPoint(highlightDrawX, 0f); + if (h != null) { + mChart.highlightValue(h); + } + } + } + }); + mChart.setVisibility(View.VISIBLE); + } else { + mChart.setVisibility(View.GONE); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/SimpleRouteCard.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/SimpleRouteCard.java index e0201a3735..79e9d69f4b 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/SimpleRouteCard.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/cards/SimpleRouteCard.java @@ -56,7 +56,7 @@ public class SimpleRouteCard extends BaseCard { info.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - ShowRouteInfoDialogFragment.showDialog(mapActivity.getSupportFragmentManager()); + ShowRouteInfoDialogFragment.showInstance(mapActivity, -1); } }); @@ -64,42 +64,42 @@ public class SimpleRouteCard extends BaseCard { ImageView durationIcon = (ImageView) view.findViewById(R.id.DurationIcon); View infoDistanceView = view.findViewById(R.id.InfoDistance); View infoDurationView = view.findViewById(R.id.InfoDuration); - if (directionInfo >= 0) { - infoIcon.setVisibility(View.GONE); - durationIcon.setVisibility(View.GONE); - infoDistanceView.setVisibility(View.GONE); - infoDurationView.setVisibility(View.GONE); - } else { +// if (directionInfo >= 0) { +// infoIcon.setVisibility(View.GONE); +// durationIcon.setVisibility(View.GONE); +// infoDistanceView.setVisibility(View.GONE); +// infoDurationView.setVisibility(View.GONE); +// } else { infoIcon.setImageDrawable(getColoredIcon(R.drawable.ic_action_route_distance, R.color.route_info_unchecked_mode_icon_color)); infoIcon.setVisibility(View.VISIBLE); durationIcon.setImageDrawable(getColoredIcon(R.drawable.ic_action_time_span, R.color.route_info_unchecked_mode_icon_color)); durationIcon.setVisibility(View.VISIBLE); infoDistanceView.setVisibility(View.VISIBLE); infoDurationView.setVisibility(View.VISIBLE); - } - if (directionInfo >= 0 && routingHelper.getRouteDirections() != null - && directionInfo < routingHelper.getRouteDirections().size()) { - RouteDirectionInfo ri = routingHelper.getRouteDirections().get(directionInfo); - } else { +// } +// if (directionInfo >= 0 && routingHelper.getRouteDirections() != null +// && directionInfo < routingHelper.getRouteDirections().size()) { +// RouteDirectionInfo ri = routingHelper.getRouteDirections().get(directionInfo); +// } else { TextView distanceText = (TextView) view.findViewById(R.id.DistanceText); TextView distanceTitle = (TextView) view.findViewById(R.id.DistanceTitle); TextView durationText = (TextView) view.findViewById(R.id.DurationText); TextView durationTitle = (TextView) view.findViewById(R.id.DurationTitle); - distanceText.setText(OsmAndFormatter.getFormattedDistance(app.getRoutingHelper().getLeftDistance(), app)); + distanceText.setText(OsmAndFormatter.getFormattedDistance(routingHelper.getLeftDistance(), app)); - durationText.setText(OsmAndFormatter.getFormattedDuration(app.getRoutingHelper().getLeftTime(), app)); - durationTitle.setText(app.getString(R.string.arrive_at_time, OsmAndFormatter.getFormattedTime(app.getRoutingHelper().getLeftTime(), true))); + durationText.setText(OsmAndFormatter.getFormattedDuration(routingHelper.getLeftTime(), app)); + durationTitle.setText(app.getString(R.string.arrive_at_time, OsmAndFormatter.getFormattedTime(routingHelper.getLeftTime(), true))); AndroidUtils.setTextPrimaryColor(app, distanceText, nightMode); AndroidUtils.setTextSecondaryColor(app, distanceTitle, nightMode); AndroidUtils.setTextPrimaryColor(app, durationText, nightMode); AndroidUtils.setTextSecondaryColor(app, durationTitle, nightMode); - } +// } view.findViewById(R.id.details_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - ShowRouteInfoDialogFragment.showDialog(mapActivity.getSupportFragmentManager()); + ShowRouteInfoDialogFragment.showInstance(mapActivity, -1); } }); diff --git a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java index 910ad05ffe..af4170adab 100644 --- a/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/TransportRoutingHelper.java @@ -91,7 +91,7 @@ public class TransportRoutingHelper { @Nullable public TransportRouteResult getCurrentRouteResult() { - if (routes != null && currentRoute < routes.size()) { + if (routes != null && currentRoute != -1 && currentRoute < routes.size()) { return routes.get(currentRoute); } return null; diff --git a/OsmAnd/src/net/osmand/plus/transport/TransportStopRoute.java b/OsmAnd/src/net/osmand/plus/transport/TransportStopRoute.java index 75ab3d98fb..de7453e138 100644 --- a/OsmAnd/src/net/osmand/plus/transport/TransportStopRoute.java +++ b/OsmAnd/src/net/osmand/plus/transport/TransportStopRoute.java @@ -27,6 +27,17 @@ public class TransportStopRoute { private boolean cachedNight; private Map, Integer> cachedRouteColors = new HashMap<>(); + public static TransportStopRoute getTransportStopRoute(TransportRoute rs, TransportStop s) { + TransportStopType type = TransportStopType.findType(rs.getType()); + TransportStopRoute r = new TransportStopRoute(); + r.type = type; + r.desc = rs.getName(); + r.route = rs; + r.stop = s; + r.refStop = s; + return r; + } + public String getDescription(OsmandApplication ctx, boolean useDistance) { if (useDistance && distance > 0) { String nm = OsmAndFormatter.getFormattedDistance(distance, ctx); From 052767131ec7b9bb4703ce923f6d34f854fa1b4d Mon Sep 17 00:00:00 2001 From: Chumva Date: Fri, 1 Mar 2019 13:37:24 +0200 Subject: [PATCH 2/3] Fix strings translations --- OsmAnd/res/values-ar/strings.xml | 11 +++++------ OsmAnd/res/values-b+ast/strings.xml | 5 ++--- OsmAnd/res/values-be-rBY/strings.xml | 11 +++++------ OsmAnd/res/values-be/strings.xml | 11 +++++------ OsmAnd/res/values-ca/strings.xml | 11 +++++------ OsmAnd/res/values-cs/strings.xml | 11 +++++------ OsmAnd/res/values-da/strings.xml | 11 +++++------ OsmAnd/res/values-de/strings.xml | 11 +++++------ OsmAnd/res/values-eo/strings.xml | 11 +++++------ OsmAnd/res/values-es-rAR/strings.xml | 11 +++++------ OsmAnd/res/values-es-rUS/strings.xml | 11 +++++------ OsmAnd/res/values-es/strings.xml | 11 +++++------ OsmAnd/res/values-eu/strings.xml | 11 +++++------ OsmAnd/res/values-fa/strings.xml | 11 +++++------ OsmAnd/res/values-fr/strings.xml | 11 +++++------ OsmAnd/res/values-gl/strings.xml | 11 +++++------ OsmAnd/res/values-he/strings.xml | 11 +++++------ OsmAnd/res/values-hu/strings.xml | 11 +++++------ OsmAnd/res/values-is/strings.xml | 11 +++++------ OsmAnd/res/values-it/strings.xml | 11 +++++------ OsmAnd/res/values-large/sizes.xml | 4 ++++ OsmAnd/res/values-nb/strings.xml | 11 +++++------ OsmAnd/res/values-pl/strings.xml | 11 +++++------ OsmAnd/res/values-pt-rBR/strings.xml | 11 +++++------ OsmAnd/res/values-pt/strings.xml | 11 +++++------ OsmAnd/res/values-ru/strings.xml | 11 +++++------ OsmAnd/res/values-sc/strings.xml | 11 +++++------ OsmAnd/res/values-sk/strings.xml | 11 +++++------ OsmAnd/res/values-sl/strings.xml | 11 +++++------ OsmAnd/res/values-sr/strings.xml | 11 +++++------ OsmAnd/res/values-sv/strings.xml | 11 +++++------ OsmAnd/res/values-zh-rTW/strings.xml | 11 +++++------ 32 files changed, 156 insertions(+), 183 deletions(-) diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index ca1f64ea44..72d7a7e400 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -2736,11 +2736,10 @@ إضافة وجهة أضف وجهة وسيطة إضافة نقطة البدء - النقطة المتوسط : %1$s - نقاط الطريق: %1$s - النقل:%1$s - سيرا على الأقدام: %1$s - الطريقة: %1$s + النقطة المتوسط + النقل + سيرا على الأقدام + الطريقة نقطة اهتمام (POI) في انتظار لحساب المسار النقل العام @@ -2749,7 +2748,7 @@ محاكاة الملاحة اختر مسار للمتابعة إعلان صوتي - الوجهات المتوسطة : %1$s + الوجهات المتوسطة الوصول إلى %1$s سوف نقوم بإرسال استعلام البحث الخاص بك: \"%1$s\"، وكذالك الموقع الخاص بك.

نحن لا نجمع معلومات شخصية، ونحن فقط بحاجة إلى البحث عن البيانات لتحسين خوارزمية البحث.
diff --git a/OsmAnd/res/values-b+ast/strings.xml b/OsmAnd/res/values-b+ast/strings.xml index 26ec6486bf..cbfe30883c 100644 --- a/OsmAnd/res/values-b+ast/strings.xml +++ b/OsmAnd/res/values-b+ast/strings.xml @@ -1599,7 +1599,7 @@ Beneficiarios d\'OSM Puntos d\'interés (PdI) Esperando pol cálculu de la ruta - Destinos intermedios: %1$s + Destinos intermedios Fallu na importación del mapa Simular la to posición Desactivar @@ -1615,7 +1615,7 @@ Altor Intercambiar l\'aniciu y destín Amiestu d\'un puntu d\'aniciu - Puntu intermediu: %1$s + Puntu intermediu Consigui OsmAnd pa desbloquiar toles caratuerístiques: Anovamientos diarios del mapa con descargues ensin llende, tolos plugins de pagu y de baldre, Wikipedia, Wikivoyage y muncho más. Según los artículos qu\'amestesti a marcadores, aconséyase que baxes los mapes de darréu: Destinos sonaos @@ -1688,7 +1688,6 @@ Amuesa\'l rindimientu del renderizáu. Planificación d\'un viaxe Guetes nel mapa - Puntos: %1$s Descarga d\'un ficheru Desaniciáronse los puntos de los marcadores del mapa Posar/siguir cola navegación diff --git a/OsmAnd/res/values-be-rBY/strings.xml b/OsmAnd/res/values-be-rBY/strings.xml index b6e4053a99..33bcde7565 100644 --- a/OsmAnd/res/values-be-rBY/strings.xml +++ b/OsmAnd/res/values-be-rBY/strings.xml @@ -3182,11 +3182,10 @@ Praparcyjnaj pamiacі %4$s MB (Abmiežavańnie Android %5$s MB, Dalvik %6$s MB). Dadać punkt pryznačennia Dadać pramiežkavy punkt Dadać pačatkovy punkt - Pramiežkavy punkt: %1$s - Punkty šliachu: %1$s - transfiery: %1$s - pieššu: %1$s - Šliach: %1$s + Pramiežkavy punkt + transfiery + pieššu + Šliach Punkty cikavasciaŭ (POI) Čakannie padliku maršrutu Hramadski transpart @@ -3195,7 +3194,7 @@ Praparcyjnaj pamiacі %4$s MB (Abmiežavańnie Android %5$s MB, Dalvik %6$s MB). Simuliavać navihacyju Abiarycie fajl sliedu Halasavyja apaviaščenni - Pramiežkavyja punkty: %1$s + Pramiežkavyja punkty Prybyccio a %1$s Naciskannie na knopku dziejannia pierakliučaje načny i dzionny režymy OsmAnd Dzionny režym diff --git a/OsmAnd/res/values-be/strings.xml b/OsmAnd/res/values-be/strings.xml index 1dfab41a5a..db91106858 100644 --- a/OsmAnd/res/values-be/strings.xml +++ b/OsmAnd/res/values-be/strings.xml @@ -2894,11 +2894,10 @@ Дадаць пункт прызначэння Дадаць прамежкавы пункт Дадаць пачатковы пункт - Прамежкавы пункт: %1$s - Пункты шляху: %1$s - трансферы: %1$s - пешшу: %1$s - Шлях: %1$s + Прамежкавы пункт + трансферы + пешшу + Шлях Пункты цікавасцяў (POI) Чаканне падліку маршруту Грамадскі транспарт @@ -2907,7 +2906,7 @@ Сімуляваць навігацыю Абярыце файл следу Галасавыя апавяшчэнні - Прамежкавыя пункты: %1$s + Прамежкавыя пункты Прыбыццё а %1$s Націсканне на кнопку дзеяння пераключае начны і дзённы рэжымы OsmAnd Дзённы рэжым diff --git a/OsmAnd/res/values-ca/strings.xml b/OsmAnd/res/values-ca/strings.xml index bf2629f7e0..f258d9a7b6 100644 --- a/OsmAnd/res/values-ca/strings.xml +++ b/OsmAnd/res/values-ca/strings.xml @@ -2901,11 +2901,10 @@ Abasta l\'àrea: %1$s x %2$s
Afegeix destinació Afegeix punt intermedi Afegeix punt d\'Inici - Punt intermedi: %1$s - Fites: %1$s - transferències: %1$s - a peu: %1$s - Via: %1$s + Punt intermedi + transferències + a peu + Via Punts d\'interès(PDI) Esperant el càlcul de la ruta Transport públic @@ -2914,7 +2913,7 @@ Abasta l\'àrea: %1$s x %2$s Simula la navegació Seleccioneu l\'arxiu de la traça a seguir Anuncis de veu - Destinacions intermèdies: %1$s + Destinacions intermèdies Arribada a %1$s t diff --git a/OsmAnd/res/values-cs/strings.xml b/OsmAnd/res/values-cs/strings.xml index d5348b21b8..3954ae4e69 100644 --- a/OsmAnd/res/values-cs/strings.xml +++ b/OsmAnd/res/values-cs/strings.xml @@ -2860,11 +2860,10 @@ Zobrazená oblast: %1$s x %2$s Přidat cíl Přidat mezicíl Přidat startovní bod - Mezicíl: %1$s - Body na cestě: %1$s - přestupy: %1$s - pěšky: %1$s - Cesta: %1$s + Mezicíl + přestupy + pěšky + Cesta Body zájmu (POI) Čekám na výpočet trasy Veřejná doprava @@ -2873,7 +2872,7 @@ Zobrazená oblast: %1$s x %2$s Simulovat navigaci Vyberte soubor s trasou, kterou chcete následovat Hlasová oznámení - Mezicíle: %1$s + Mezicíle Příjezd v %1$s Nejdříve prosím zadejte cíl Předchozí trasa diff --git a/OsmAnd/res/values-da/strings.xml b/OsmAnd/res/values-da/strings.xml index e6487fe3ec..15270a29cb 100644 --- a/OsmAnd/res/values-da/strings.xml +++ b/OsmAnd/res/values-da/strings.xml @@ -2891,17 +2891,16 @@ Repræsenterer område: %1$s x %2$s Tilføj destination Tilføj mellemliggende Tilføj startpunkt - Mellemliggende punkt: %1$s - Rutepunkter: %1$s - overførsler: %1$s - til fods: %1$s + Mellemliggende punkt + overførsler + til fods Interessepunkter (IP) Venter på ruteberegningen Offentlig transport Vælg vejen på kortet eller fra nedenstående liste, der skal undgås under navigation: Vis langs ruten Simulere navigation - Mellemliggende destinationer: %1$s + Mellemliggende destinationer Dag tilstand Nat tilstand Skift dag/nat tilstand @@ -2910,7 +2909,7 @@ Repræsenterer område: %1$s x %2$s Kapacitet Bredde Højde - Vej: %1$s + Vej Vælg sporfil til at følge Skift start og destination Stemmemeddelelser diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index fc23dd2dd1..90f3c698ce 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -2898,11 +2898,10 @@ Abgedeckte Fläche: %1$s x %2$s Ziel hinzufügen Zwischenpunkt hinzufügen Startpunkt hinzufügen - Zwischenpunkt: %1$s - Wegpunkte: %1$s - Umstiege: %1$s - Zu Fuß: %1$s - Weg: %1$s + Zwischenpunkt + Umstiege + Zu Fuß + Weg Orte von Interesse(OVI) Warten auf Routenberechung Öffentlicher Verkehr @@ -2911,7 +2910,7 @@ Abgedeckte Fläche: %1$s x %2$s Navigation simulieren Wähle Track-Datei zum Verfolgen aus Sprachmeldungen - Zwischenziele: %1$s + Zwischenziele Ankunftszeit um %1$s t diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index 160b72c944..a7e9fd8e31 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -2875,11 +2875,10 @@ Indikas lokon: %1$s x %2$s" Aldoni celon Aldoni intercelon Aldoni komencpunkton - Intercelo: %1$s - Navigadpunktoj: %1$s - transveturiliĝoj: %1$s - piede: %1$s - Vojo: %1$s + Intercelo + transveturiliĝoj + piede + Vojo Interesejoj Atendu ĝis la kurso kalkuliĝos Transporto publika @@ -2888,7 +2887,7 @@ Indikas lokon: %1$s x %2$s" Simuli navigadon Elektu dosieron de kurso por sekvi Voĉaj anoncoj - Interceloj: %1$s + Interceloj Alveno je %1$s Mg diff --git a/OsmAnd/res/values-es-rAR/strings.xml b/OsmAnd/res/values-es-rAR/strings.xml index 55f96c6823..9140e4d3af 100644 --- a/OsmAnd/res/values-es-rAR/strings.xml +++ b/OsmAnd/res/values-es-rAR/strings.xml @@ -2892,11 +2892,10 @@ Lon %2$s Añadir destino Añadir punto intermedio Añadir punto de partida - Punto intermedio: %1$s - Puntos de referencia: %1$s - transferencias: %1$s - a pie: %1$s - Ruta: %1$s + Punto intermedio + transferencias + a pie + Ruta Puntos de interés (PDI) Esperando el cálculo de la ruta Transporte público @@ -2905,7 +2904,7 @@ Lon %2$s Simular navegación Elige el archivo de la traza a seguir Anuncios de voz - Destinos intermedios: %1$s + Destinos intermedios Llegará a las %1$s ton diff --git a/OsmAnd/res/values-es-rUS/strings.xml b/OsmAnd/res/values-es-rUS/strings.xml index e7e84a2f95..872c3be46d 100644 --- a/OsmAnd/res/values-es-rUS/strings.xml +++ b/OsmAnd/res/values-es-rUS/strings.xml @@ -2893,11 +2893,10 @@ Lon %2$s Añadir destino Añadir punto intermedio Añadir punto de partida - Punto intermedio: %1$s - Puntos de referencia: %1$s - transferencias: %1$s - a pie: %1$s - Ruta: %1$s + Punto intermedio + transferencias + a pie + Ruta Puntos de interés (PDI) Esperando el cálculo de la ruta Transporte público @@ -2906,7 +2905,7 @@ Lon %2$s Simular navegación Elige el archivo de la traza a seguir Anuncios de voz - Destinos intermedios: %1$s + Destinos intermedios Llegará a las %1$s ton diff --git a/OsmAnd/res/values-es/strings.xml b/OsmAnd/res/values-es/strings.xml index 6ec1dbd332..e53524d9ee 100644 --- a/OsmAnd/res/values-es/strings.xml +++ b/OsmAnd/res/values-es/strings.xml @@ -2894,11 +2894,10 @@ Añadir destino Añadir punto intermedio Añadir punto de partida - Punto intermedio: %1$s - Puntos de referencia: %1$s - transferencias: %1$s - a pie: %1$s - Camino: %1$s + Punto intermedio + transferencias + a pie + Camino Puntos de interés (PDI) Esperando el cálculo de la ruta Transporte público @@ -2907,7 +2906,7 @@ Simular navegación Elija el archivo de la traza a seguir Anuncios de voz - Destinos intermedios: %1$s + Destinos intermedios Llegará a las %1$s ton diff --git a/OsmAnd/res/values-eu/strings.xml b/OsmAnd/res/values-eu/strings.xml index 3914dc3cba..5581ff4a87 100644 --- a/OsmAnd/res/values-eu/strings.xml +++ b/OsmAnd/res/values-eu/strings.xml @@ -2889,16 +2889,15 @@ Area honi dagokio: %1$s x %2$s Gehitu helburua Gehitu tarteko puntua Gehitu abiapuntua - Tarteko puntua: %1$s - Bide-puntuak: %1$s - transferentziak: %1$s - oinez: %1$s - Bidea: %1$s + Tarteko puntua + transferentziak + oinez + Bidea Puntu interesgarriak (POI) Garraio publikoa Simulatu nabigazioa Ahots bidezko iragarpenak - Tarteko helburuak: %1$s + Tarteko helburuak Heltzeko ordua: %1$s Guaraniera Eguneko modua diff --git a/OsmAnd/res/values-fa/strings.xml b/OsmAnd/res/values-fa/strings.xml index 06634a39fd..81f8f7cb1e 100644 --- a/OsmAnd/res/values-fa/strings.xml +++ b/OsmAnd/res/values-fa/strings.xml @@ -2932,11 +2932,10 @@ افزودن مقصد افزودن نقطهٔ میانی افزودن نقطهٔ شروع - نقطهٔ میانی: %1$s - نقاط بین‌راهی: %1$s - انتقال‌ها: %1$s - روی پا: %1$s - راه: %1$s + نقطهٔ میانی + انتقال‌ها + روی پا + راه نقاط پرکاربرد (POI) در انتظار محاسبهٔ مسیر حمل‌ونقل عمومی @@ -2945,7 +2944,7 @@ شبیه‌سازی ناوبری فایل رد را برای دنبال‌کردن انتخاب کنید پیام‌های گفتاری - مقصدهای میانی: %1$s + مقصدهای میانی زمان رسیدن: %1$s مترمکعب تن diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index efff1c900c..6bad9b1191 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -2867,11 +2867,10 @@ représentant la zone : %1$s x %2$s Ajouter destination Ajouter étape Ajouter départ - Étape : %1$s - Points de passage : %1$s - transferts : %1$s - à pied : %1$s - Mode : %1$s + Étape + transferts + à pied + Mode Points d\'intérêt (PI) Calcul de l\'itinéraire en cours Transports publics @@ -2880,7 +2879,7 @@ représentant la zone : %1$s x %2$s Simuler la navigation Sélectionner un fichier de trace à suivre Annonces vocales - Destinations intermédiaires : %1$s + Destinations intermédiaires Arrivée à %1$s t diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index 5af73f0021..c300cee5ac 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -2955,11 +2955,10 @@ Lon %2$s Engadir destino Engadir punto intermedio Engadir punto inicial - Punto intermedio: %1$s - Puntos de pasaxe: %1$s - transferencias: %1$s - a pé: %1$s - Vía: %1$s + Punto intermedio + transferencias + a pé + Vía Puntos de interese (PDI) Estase a agardar polo cálculo da rota Transporte público @@ -2968,7 +2967,7 @@ Lon %2$s Simular navegación Escolle o ficheiro da pista a seguir Anuncios de voz - Destinos intermedios: %1$s + Destinos intermedios Chegada ás %1$s Guaraní Premendo neste botón de acción, troca entre o modo \"Noite\" e \"Día\" para o OsmAnd diff --git a/OsmAnd/res/values-he/strings.xml b/OsmAnd/res/values-he/strings.xml index 0877b5c42c..340025bef9 100644 --- a/OsmAnd/res/values-he/strings.xml +++ b/OsmAnd/res/values-he/strings.xml @@ -2878,11 +2878,10 @@ הוספת יעד הוספת נקודת ביניים הוספת נקודת התחלה - נקודת ביניים: %1$s - נקודות דרך: %1$s - החלפות: %1$s - ברגל: %1$s - דרך: %1$s + נקודת ביניים + החלפות + ברגל + דרך נקודות עניין (נ״ע) בהמתנה לחישוב מסלול תחבורה ציבורית @@ -2891,7 +2890,7 @@ הדמיית ניווט נא לבחור קובץ מסלול להצגה הכרזות קוליות - יעדי ביניים: %1$s + יעדי ביניים הגעה ב־%1$s נגיעה בכפתור פעולה זה תחליף בין מצבי יום ולילה עבור OsmAnd מצב יום diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml index c1450df337..da94fe26a6 100644 --- a/OsmAnd/res/values-hu/strings.xml +++ b/OsmAnd/res/values-hu/strings.xml @@ -2786,11 +2786,10 @@ Kérlek adj meg egy teljes kódot Célpont hozzáadása Köztes célpont hozzáadása Kiindulópont hozzáadása - "Köztes célpont: %1$s " - Útpontok: %1$s - átszállások: %1$s - gyalog: %1$s - Út: %1$s + Köztes célpont + átszállások + gyalog + Út Érdekes helyek (POI) Várakozás az útvonal kiszámítására Tömegközlekedés @@ -2799,7 +2798,7 @@ Kérlek adj meg egy teljes kódot Navigáció szimulálása Válaszd ki a követendő nyomvonalfájlt Hangbemondások - Köztes célpontok: %1$s + Köztes célpontok Érkezés ekkor: %1$s A motorháztető alatt: OsmAnd Harmadik féltől származó alkalmazás diff --git a/OsmAnd/res/values-is/strings.xml b/OsmAnd/res/values-is/strings.xml index eea8fd26c8..d0da16e48f 100644 --- a/OsmAnd/res/values-is/strings.xml +++ b/OsmAnd/res/values-is/strings.xml @@ -2903,11 +2903,10 @@ Stendur fyrir svæði: %1$s x %2$s Bæta við áfangastað Bæta við milliáfanga Bæta við upphafspunkti - Millipunktur: %1$s - Ferilpunktar: %1$s - millifærslur: %1$s - gangandi: %1$s - Leið: %1$s + Millipunktur + millifærslur + gangandi + Leið Merkisstaðir (POI) Bíð eftir útreikningi leiðar Almenningssamgöngur @@ -2916,7 +2915,7 @@ Stendur fyrir svæði: %1$s x %2$s Herma eftir leiðsögn Veldu ferilskrá til að fylgja Raddtilkynningar - Milliáfangar: %1$s + Milliáfangar Koma klukkan %1$s Guaraní Ef ýtt er á þennan aðgerðahnapp verður skipt á milli Dags- og Næturhams í OsmAnd diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index 5610fa48d6..c4881ba8b0 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -2875,11 +2875,10 @@ Rappresenta l\'area: %1$s x %2$s Aggiungi destinazione Aggiungi punto intermedio Aggiungi punto di partenza - Punto intermedio: %1$s - Punto di passaggio: %1$s - trasferimenti: %1$s - a piedi: %1$s - Via: %1$s + Punto intermedio + trasferimenti + a piedi + Via Punti d\'interesse(PDI) In attesa del calcolo del percorso Trasporto pubblico @@ -2888,7 +2887,7 @@ Rappresenta l\'area: %1$s x %2$s Simula la navigazione "Scegli il file della traccia da seguire " Annunci vocali - Destinazioni intermedie: %1$s + Destinazioni intermedie Arrivo alle %1$s Toccando questo bottone si cambierà fra la modalità Notte e Giorno per OsmAnd Modalità Giorno diff --git a/OsmAnd/res/values-large/sizes.xml b/OsmAnd/res/values-large/sizes.xml index bed5a6585f..a03ce9090d 100644 --- a/OsmAnd/res/values-large/sizes.xml +++ b/OsmAnd/res/values-large/sizes.xml @@ -185,6 +185,10 @@ 9dp 48dp 60dp + 90dp + 84dp + 78dp + 12dp 78dp diff --git a/OsmAnd/res/values-nb/strings.xml b/OsmAnd/res/values-nb/strings.xml index 9dd561921f..50742596e3 100644 --- a/OsmAnd/res/values-nb/strings.xml +++ b/OsmAnd/res/values-nb/strings.xml @@ -2891,11 +2891,10 @@ Legg til reisemål Legg til mellomliggende Legg til startpunkt - Mellomliggende punkt: %1$s - Rutepunkter: %1$s - overføringer: %1$s - til fots: %1$s - Vei: %1$s + Mellomliggende punkt + overføringer + til fots + Vei Interessepunkter (POI) Venter på ruteberegning Velg vei på kartet fra listen nedenfor som du ønsker å unngå under navigering: @@ -2903,7 +2902,7 @@ Simuler navigering Velg sporfil å følge Talemeldinger - Mellomstasjoner: %1$s + Mellomstasjoner Ankom klokken %1$s t diff --git a/OsmAnd/res/values-pl/strings.xml b/OsmAnd/res/values-pl/strings.xml index fc9412d683..52a31a8fc6 100644 --- a/OsmAnd/res/values-pl/strings.xml +++ b/OsmAnd/res/values-pl/strings.xml @@ -2897,11 +2897,10 @@ Reprezentuje obszar: %1$s x %2$s Dodaj cel trasy Dodaj punkt pośredni Dodaj punkt początkowy - Punkt pośredni: %1$s - Punkty trasy: %1$s - przesiadki: %1$s - pieszo: %1$s - Trasa: %1$s + Punkt pośredni + przesiadki + pieszo + Trasa Użyteczne miejsca (UM) Oczekiwanie na wyznaczenie trasy Transport publiczny @@ -2910,7 +2909,7 @@ Reprezentuje obszar: %1$s x %2$s Symulacja nawigacji Wybierz plik trasy do śledzenia Komunikaty głosowe - Pośrednie cele podróży: %1$s + Pośrednie cele podróży Dotrzesz do celu o %1$s Naciśnięcie przycisku zmieni pomiędzy trybem Dziennym i Nocnym w OsmAndzie Tryb Dzienny diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml index 5e895c0f30..05487884ee 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -2829,11 +2829,10 @@ Pôr do Sol: %2$s Adicionar destino Adicionar intermediário Adicionar ponto inicial - Ponto intermediário: %1$s - Ponto de trajeto: %1$s - transferências: %1$s - a pé: %1$s - Via: %1$s + Ponto intermediário + transferências + a pé + Via Ponto de interesse (PDI) Esperando por cálculo de rota Transporte público @@ -2842,7 +2841,7 @@ Pôr do Sol: %2$s Simular navegação Escolha arquivo de trilha para seguir Avisos por voz - Destinos intermediários: %1$s + Destinos intermediários Chegada em %1$s Guarani Tocando neste botão de ação, alterne entre os modos Dia e Noite para OsmAnd diff --git a/OsmAnd/res/values-pt/strings.xml b/OsmAnd/res/values-pt/strings.xml index 4240b21682..796c20e170 100644 --- a/OsmAnd/res/values-pt/strings.xml +++ b/OsmAnd/res/values-pt/strings.xml @@ -2841,11 +2841,10 @@ Adicionar destino Adicionar intermediário Adicionar ponto de partida - Ponto intermédio: %1$s - Pontos de passagem: %1$s - transferências: %1$s - a pé: %1$s - Caminho: %1$s + Ponto intermédio + transferências + a pé + Caminho Pontos de interesse (POI) Aguardando o cálculo da rota Transporte público @@ -2854,6 +2853,6 @@ Simular navegação Escolha o ficheiro de caminho a seguir Anúncios de voz - Destinos intermediários: %1$s + Destinos intermediários Chegar às %1$s \ No newline at end of file diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index f5b8466216..17f7636072 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -1,8 +1,7 @@ - Промежуточная точка: %1$s - Путевые точки: %1$s - Промежуточные точки: %1$s + Промежуточная точка + Промежуточные точки Прибытие в %1$s Файл GPX с координатами и данными выбранных заметок. Файл GPX с координатами и данными всех заметок. @@ -2878,7 +2877,7 @@ Добавить пункт назначения Добавить промежуточный пункт Добавить пункт отправления - Путь: %1$s + Путь Точки интереса (POI) Ожидание расчета маршрута Общественный транспорт @@ -2895,8 +2894,8 @@ Объем Ширина Высота - трансферы: %1$s - пешком: %1$s + трансферы + пешком Показывать вдоль маршрута Поверхность Класс diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml index 6424d3137f..c68a4e165c 100644 --- a/OsmAnd/res/values-sc/strings.xml +++ b/OsmAnd/res/values-sc/strings.xml @@ -2875,7 +2875,6 @@ Pro praghere iscrie su còdighe intreu Modalidade pro sa note Cola intre Die/Note Annanghe una destinatzione - Puntos de coladòrgiu: %1$s t Capatzidade @@ -2884,10 +2883,10 @@ Pro praghere iscrie su còdighe intreu Cuncàmbia sa partèntzia e sa destinatzione Annanghe unu puntu de coladòrgiu Annanghe unu puntu de incumintzu - Puntu de coladòrgiu: %1$s - tramudadas: %1$s - a pede: %1$s - Modalidade: %1$s + Puntu de coladòrgiu + tramudadas + a pede + Modalidade Puntos de interesse (PDI) Isetende pro su càlculu de s\'àndala Trasportu pùblicu @@ -2896,7 +2895,7 @@ Pro praghere iscrie su còdighe intreu Sìmula su nàvigu Ischerta unu documentu de rasta de sighire Annùntzios vocales - Destinatziones intermèdias: %1$s + Destinatziones intermèdias Arribada a sas %1$s Classe Superfìtzie diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml index 06ba3bb627..85660a351b 100644 --- a/OsmAnd/res/values-sk/strings.xml +++ b/OsmAnd/res/values-sk/strings.xml @@ -2883,11 +2883,10 @@ Zodpovedá oblasti: %1$s x %2$s Pridať cieľ Pridať medzicieľ Pridať štartovací bod - Prechodný bod: %1$s - Body na ceste: %1$s - prestupy: %1$s - peši: %1$s - Cesta: %1$s + Prechodný bod + prestupy + peši + Cesta Body záujmu (POI) Čakám na výpočet trasy Verejná doprava @@ -2896,7 +2895,7 @@ Zodpovedá oblasti: %1$s x %2$s Simulovať navigáciu Zvoľte súbor trasy, ktorú chcete nasledovať Hlasové oznámenia - Medziciele: %1$s + Medziciele Príjazd o %1$s Trieda Povrch diff --git a/OsmAnd/res/values-sl/strings.xml b/OsmAnd/res/values-sl/strings.xml index 09b4f4bb56..c0ec7af733 100644 --- a/OsmAnd/res/values-sl/strings.xml +++ b/OsmAnd/res/values-sl/strings.xml @@ -3197,11 +3197,10 @@ Koda predstavlja območje: %1$s x %2$s Dodaj cilj Dodaj vmesni cilj Dodaj začetno točko - Vmesna točka: %1$s - Vmesne točke: %1$s - prevozi: %1$s - hoja: %1$s - Pot: %1$s + Vmesna točka + prevozi + hoja + Pot Točke zanimanja (POI) Poteka preračunavanje poti Javni prevozi @@ -3210,7 +3209,7 @@ Koda predstavlja območje: %1$s x %2$s Izvedi navidezno navigacijo Izberite datoteko poti za sledenje Glasovne najave - Vmesni cilji: %1$s + Vmesni cilji Prihod ob %1$s S podporo OsmAnd Pokaži le 360° slike diff --git a/OsmAnd/res/values-sr/strings.xml b/OsmAnd/res/values-sr/strings.xml index eb4f42e989..a550b8ab38 100644 --- a/OsmAnd/res/values-sr/strings.xml +++ b/OsmAnd/res/values-sr/strings.xml @@ -2909,11 +2909,10 @@ Додај одредиште Додај успутну станицу Додај почетну тачку - "Успутне тачке: %1$s " - Пролазне тачке: %1$s - преседања: %1$s - "пешице: %1$s " - Пут: %1$s + Успутне тачке + преседања + пешице + Пут Тачке од интереса (POI) Чекање на израчунавање пута Јавни саобраћај @@ -2922,7 +2921,7 @@ Симулирај навођење Одаберите фајл путање за праћење Гласовне најаве - "Успутна одредишта: %1$s " + Успутна одредишта "Долазак у %1$s " Класа Подлога diff --git a/OsmAnd/res/values-sv/strings.xml b/OsmAnd/res/values-sv/strings.xml index 3811fd658a..ec6e10f979 100644 --- a/OsmAnd/res/values-sv/strings.xml +++ b/OsmAnd/res/values-sv/strings.xml @@ -2770,11 +2770,10 @@ Vänligen tillhandahåll fullständig kod Lägg till destination Lägg till hållplats Lägg till startpunkt - Hållplats: %1$s - Hållpunkter: %1$s - övergångar: %1$s - till fots: %1$s - Väg: %1$s + Hållplats + övergångar + till fots + Väg Intressepunkter (IP) Väntar på beräkning av rutten Kollektivtrafik @@ -2783,6 +2782,6 @@ Vänligen tillhandahåll fullständig kod Simulera navigering Välj en spårfil att följa Röstmeddelanden - Mellanliggande destinationer: %1$s + Mellanliggande destinationer Ankomst klockan %1$s \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rTW/strings.xml b/OsmAnd/res/values-zh-rTW/strings.xml index ac0208b66e..7ee52e1032 100644 --- a/OsmAnd/res/values-zh-rTW/strings.xml +++ b/OsmAnd/res/values-zh-rTW/strings.xml @@ -2875,16 +2875,15 @@ 增加目的地 增加中轉 新增起始點 - 中轉地點:%1$s - 航點:%1$s - 移動:%1$s + 中轉地點 + 移動 立方公尺 公噸 容量 寬度 高度 - 步行:%1$s - 道路:%1$s + 步行 + 道路 興趣點 (POI) 等待計算路徑 大眾運輸 @@ -2893,7 +2892,7 @@ 模擬導航 選擇要跟隨的軌跡檔案 語音通知 - 中轉地點:%1$s + 中轉地點 到達 %1$s 輕觸此動作按鈕以在 OsmAnd 的日間與夜間模式間切換 日間模式 From 3fe0d010f9418a444639a6fea1af95446415edc7 Mon Sep 17 00:00:00 2001 From: Chumva Date: Fri, 1 Mar 2019 13:58:50 +0200 Subject: [PATCH 3/3] Remove unnecessary menu state class and fix possible npe --- .../ShowRouteInfoDialogFragment.java | 129 +++++++++--------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java b/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java index 2cc5efb42d..1d37a7e6fd 100644 --- a/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/ShowRouteInfoDialogFragment.java @@ -113,6 +113,9 @@ import java.util.Locale; import static net.osmand.plus.mapcontextmenu.MapContextMenuFragment.CURRENT_Y_UNDEFINED; import static net.osmand.plus.mapcontextmenu.MenuBuilder.SHADOW_HEIGHT_TOP_DP; +import static net.osmand.plus.routepreparationmenu.MapRouteInfoMenu.MenuState.FULL_SCREEN; +import static net.osmand.plus.routepreparationmenu.MapRouteInfoMenu.MenuState.HALF_SCREEN; +import static net.osmand.plus.routepreparationmenu.MapRouteInfoMenu.MenuState.HEADER_ONLY; public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { @@ -120,12 +123,6 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { private static final String ROUTE_ID_KEY = "route_id_key"; - public static class MenuState { - public static final int HEADER_ONLY = 1; - public static final int HALF_SCREEN = 2; - public static final int FULL_SCREEN = 4; - } - private InterceptorLinearLayout mainView; private View view; private View.OnLayoutChangeListener containerLayoutListener; @@ -165,9 +162,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { app = getMyApplication(); - if (app == null) { - return null; - } + final MapActivity mapActivity = requireMapActivity(); routingHelper = app.getRoutingHelper(); view = inflater.inflate(R.layout.route_info_layout, container, false); @@ -198,9 +193,9 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { List routes = routingHelper.getTransportRoutingHelper().getRoutes(); if (routes != null && routes.size() > routeId) { TransportRoutePlanner.TransportRouteResult routeResult = routingHelper.getTransportRoutingHelper().getRoutes().get(routeId); - PublicTransportCard card = new PublicTransportCard(getMapActivity(), routeResult, routeId); + PublicTransportCard card = new PublicTransportCard(mapActivity, routeResult, routeId); menuCards.add(card); - cardsContainer.addView(card.build(getMapActivity())); + cardsContainer.addView(card.build(mapActivity)); buildRowDivider(cardsContainer, false); buildTransportRouteRow(cardsContainer, routeResult, null, true); buildRowDivider(cardsContainer, false); @@ -210,8 +205,6 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { createRouteStatisticCards(cardsContainer); createRouteDirections(cardsContainer); } - - final MapActivity mapActivity = requireMapActivity(); processScreenHeight(container); portrait = AndroidUiHelper.isOrientationPortrait(mapActivity); @@ -222,7 +215,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { minHalfY = viewHeight - (int) (viewHeight * .75f); mainView = view.findViewById(R.id.main_view); - nightMode = mapActivity.getMyApplication().getDaynightHelper().isNightModeForMapControls(); + nightMode = app.getDaynightHelper().isNightModeForMapControls(); // Zoom buttons zoomButtonsView = view.findViewById(R.id.map_hud_controls); @@ -267,7 +260,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { bottomScrollView.setScrollingEnabled(false); AndroidUtils.setBackground(app, bottomScrollView, nightMode, R.color.route_info_bg_light, R.color.route_info_bg_dark); - AndroidUtils.setBackground(getMapActivity(), mainView, nightMode, R.drawable.bg_map_context_menu_light, R.drawable.bg_map_context_menu_dark); + AndroidUtils.setBackground(app, mainView, nightMode, R.drawable.bg_map_context_menu_light, R.drawable.bg_map_context_menu_dark); if (!portrait) { final TypedValue typedValueAttr = new TypedValue(); @@ -281,7 +274,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { runLayoutListener(); - final GestureDetector swipeDetector = new GestureDetector(getMapActivity(), new HorizontalSwipeConfirm(true)); + final GestureDetector swipeDetector = new GestureDetector(app, new HorizontalSwipeConfirm(true)); final View.OnTouchListener slideTouchListener = new View.OnTouchListener() { private float dy; @@ -297,8 +290,8 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { private boolean slidingDown; { - scroller = new OverScroller(getMapActivity()); - final ViewConfiguration configuration = ViewConfiguration.get(getMapActivity()); + scroller = new OverScroller(app); + final ViewConfiguration configuration = ViewConfiguration.get(app); minimumVelocity = configuration.getScaledMinimumFlingVelocity(); maximumVelocity = configuration.getScaledMaximumFlingVelocity(); } @@ -473,8 +466,12 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { } private void createRouteStatisticCards(LinearLayout cardsContainer) { + MapActivity mapActivity = getMapActivity(); + if(mapActivity==null){ + return; + } if (gpx.hasAltitude) { - RouteStatisticCard statisticCard = new RouteStatisticCard(getMapActivity(), gpx, new View.OnTouchListener() { + RouteStatisticCard statisticCard = new RouteStatisticCard(mapActivity, gpx, new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mainView.requestDisallowInterceptTouchEvent(true); @@ -482,7 +479,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { } }); menuCards.add(statisticCard); - cardsContainer.addView(statisticCard.build(getMapActivity())); + cardsContainer.addView(statisticCard.build(mapActivity)); buildRowDivider(cardsContainer, false); slopeDataSet = statisticCard.getSlopeDataSet(); elevationDataSet = statisticCard.getElevationDataSet(); @@ -491,19 +488,19 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { RouteStatistics routeStatistics = RouteStatistics.newRouteStatistic(route); GPXUtilities.GPXTrackAnalysis analysis = gpx.getAnalysis(0); - RouteInfoCard routeClassCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteClassStatistic(), analysis); + RouteInfoCard routeClassCard = new RouteInfoCard(mapActivity, routeStatistics.getRouteClassStatistic(), analysis); createRouteCard(cardsContainer, routeClassCard); - RouteInfoCard routeSurfaceCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteSurfaceStatistic(), analysis); + RouteInfoCard routeSurfaceCard = new RouteInfoCard(mapActivity, routeStatistics.getRouteSurfaceStatistic(), analysis); createRouteCard(cardsContainer, routeSurfaceCard); if (slopeDataSet != null) { List inclines = createInclinesAndAdd100MetersWith0Incline(slopeDataSet.getValues()); - RouteInfoCard routeSteepnessCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteSteepnessStatistic(inclines), analysis); + RouteInfoCard routeSteepnessCard = new RouteInfoCard(mapActivity, routeStatistics.getRouteSteepnessStatistic(inclines), analysis); createRouteCard(cardsContainer, routeSteepnessCard); } - RouteInfoCard routeSmoothnessCard = new RouteInfoCard(getMapActivity(), routeStatistics.getRouteSmoothnessStatistic(), analysis); + RouteInfoCard routeSmoothnessCard = new RouteInfoCard(mapActivity, routeStatistics.getRouteSmoothnessStatistic(), analysis); createRouteCard(cardsContainer, routeSmoothnessCard); } } @@ -517,6 +514,9 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { private void updateMyLocation(RoutingHelper rh) { MapActivity mapActivity = getMapActivity(); + if (mapActivity == null) { + return; + } Location lastKnownLocation = app.getLocationProvider().getLastKnownLocation(); boolean enabled = lastKnownLocation != null; boolean tracked = mapActivity.getMapViewTrackingUtilities().isMapLinkedToLocation(); @@ -600,7 +600,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { MenuBuilder.CollapsableView collapsableView = null; if (stops.size() > 2) { - collapsableView = getCollapsableTransportStopRoutesView(getMapActivity(), transportStopRoute, stops.subList(1, stops.size() - 1)); + collapsableView = getCollapsableTransportStopRoutesView(app, transportStopRoute, stops.subList(1, stops.size() - 1)); } SpannableStringBuilder spannable = new SpannableStringBuilder("~"); int startIndex = spannable.length(); @@ -926,6 +926,10 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { public void buildStartStopRow(final View view, Drawable icon, String timeText, TransportStopRoute transportStopRoute, final Spannable title, Spannable secondaryText, View.OnClickListener onClickListener) { + MapActivity mapActivity = getMapActivity(); + if (mapActivity == null) { + return; + } FrameLayout baseItemView = new FrameLayout(view.getContext()); FrameLayout.LayoutParams baseViewLayoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); baseItemView.setLayoutParams(baseViewLayoutParams); @@ -993,7 +997,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { routeTypeView.setText(getString(R.string.layer_route) + ":"); llText.addView(routeTypeView); - View routeBadge = createRouteBadge(getMapActivity(), transportStopRoute, nightMode); + View routeBadge = createRouteBadge(mapActivity, transportStopRoute, nightMode); LinearLayout.LayoutParams routeBadgeParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); routeBadgeParams.setMargins(0, dpToPx(6), 0, dpToPx(8)); routeBadge.setLayoutParams(routeBadgeParams); @@ -1363,19 +1367,17 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { return ll; } - public static View createRouteBadge(MapActivity mapActivity, TransportStopRoute transportStopRoute, boolean nightMode) { + public View createRouteBadge(MapActivity mapActivity, TransportStopRoute transportStopRoute, boolean nightMode) { LinearLayout convertView = (LinearLayout) mapActivity.getLayoutInflater().inflate(R.layout.transport_stop_route_item_with_icon, null, false); if (transportStopRoute != null) { - String routeRef = transportStopRoute.route.getAdjustedRouteRef(); - int bgColor = transportStopRoute.getColor(mapActivity.getMyApplication(), nightMode); + int bgColor = transportStopRoute.getColor(app, nightMode); TextView transportStopRouteTextView = (TextView) convertView.findViewById(R.id.transport_stop_route_text); ImageView transportStopRouteImageView = (ImageView) convertView.findViewById(R.id.transport_stop_route_icon); int drawableResId = transportStopRoute.type == null ? R.drawable.ic_action_bus_dark : transportStopRoute.type.getResourceId(); - - transportStopRouteImageView.setImageDrawable(mapActivity.getMyApplication().getUIUtilities().getPaintedIcon(drawableResId, UiUtilities.getContrastColor(mapActivity, bgColor, true))); + transportStopRouteImageView.setImageDrawable(app.getUIUtilities().getPaintedIcon(drawableResId, UiUtilities.getContrastColor(mapActivity, bgColor, true))); transportStopRouteTextView.setText(routeRef); GradientDrawable gradientDrawableBg = (GradientDrawable) convertView.getBackground(); gradientDrawableBg.setColor(bgColor); @@ -1546,7 +1548,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { public void onClick(View v) { final String trackName = new SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(new Date()); final GPXFile gpx = routingHelper.generateGPXFileWithRoute(trackName); - final Uri fileUri = AndroidUtils.getUriForFile(getMyApplication(), new File(gpx.path)); + final Uri fileUri = AndroidUtils.getUriForFile(app, new File(gpx.path)); File dir = new File(app.getCacheDir(), "share"); if (!dir.exists()) { dir.mkdir(); @@ -1562,8 +1564,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { routingHelper.getGeneralRouteInformation()).toString())); sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_route_subject)); sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri); - sendIntent.putExtra( - Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), dst)); + sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(app, dst)); sendIntent.setType("text/plain"); sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(sendIntent); @@ -1611,7 +1612,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { if (model.distance > 0) { distanceLabel.setText(OsmAndFormatter.getFormattedDistance(model.distance, app)); timeLabel.setText(getTimeDescription(model)); - row.setContentDescription(label.getText() + " " + timeLabel.getText()); //$NON-NLS-1$ + row.setContentDescription(label.getText() + " " + timeLabel.getText()); } else { if (Algorithms.isEmpty(label.getText().toString())) { label.setText(getString((position != directionsInfo.size() - 1) ? R.string.arrived_at_intermediate_point : R.string.arrived_at_destination)); @@ -1645,7 +1646,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { void print() { File file = generateRouteInfoHtml(routingHelper.getRouteDirections(), routingHelper.getGeneralRouteInformation()); if (file.exists()) { - Uri uri = AndroidUtils.getUriForFile(getMyApplication(), file); + Uri uri = AndroidUtils.getUriForFile(app, file); Intent browserIntent; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // use Android Print Framework browserIntent = new Intent(getActivity(), PrintDialogActivity.class) @@ -1669,7 +1670,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { StringBuilder html = generateHtmlPrint(directionsInfo, title); FileOutputStream fos = null; try { - file = getMyApplication().getAppPath(fileName); + file = app.getAppPath(fileName); fos = new FileOutputStream(file); fos.write(html.toString().getBytes("UTF-8")); fos.flush(); @@ -1702,7 +1703,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { for (int i = 0; i < directionInfos.size(); i++) { RouteDirectionInfo routeDirectionInfo = directionInfos.get(i); StringBuilder sb = new StringBuilder(); - sb.append(OsmAndFormatter.getFormattedDistance(routeDirectionInfo.distance, getMyApplication())); + sb.append(OsmAndFormatter.getFormattedDistance(routeDirectionInfo.distance, app)); sb.append(", ").append(NBSP); sb.append(getTimeDescription(routeDirectionInfo)); String distance = sb.toString().replaceAll("\\s", NBSP); @@ -1743,7 +1744,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { RouteDirectionInfo routeDirectionInfo = directionsInfo.get(i); html.append("
"); StringBuilder sb = new StringBuilder(); - sb.append(OsmAndFormatter.getFormattedDistance(routeDirectionInfo.distance, getMyApplication())); + sb.append(OsmAndFormatter.getFormattedDistance(routeDirectionInfo.distance, app)); sb.append(", "); sb.append(getTimeDescription(routeDirectionInfo)); String distance = sb.toString().replaceAll("\\s", NBSP); @@ -1757,7 +1758,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { CumulativeInfo cumulativeInfo = getRouteDirectionCumulativeInfo(i, directionsInfo); html.append("
"); - html.append(String.valueOf(i + 1) + ". " + description); + html.append(String.valueOf(i + 1)).append(". ").append(description); html.append(""); sb = new StringBuilder(); sb.append(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance, getMyApplication())); sb.append(" - "); - sb.append(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance + routeDirectionInfo.distance, - getMyApplication())); + sb.append(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance + routeDirectionInfo.distance, app)); sb.append(BR); - sb.append(Algorithms.formatDuration(cumulativeInfo.time, getMyApplication().accessibilityEnabled())); + sb.append(Algorithms.formatDuration(cumulativeInfo.time, accessibilityEnabled)); sb.append(" - "); - sb.append(Algorithms.formatDuration(cumulativeInfo.time + routeDirectionInfo.getExpectedTime(), - getMyApplication().accessibilityEnabled())); + sb.append(Algorithms.formatDuration(cumulativeInfo.time + routeDirectionInfo.getExpectedTime(), accessibilityEnabled)); String cumulativeTimeAndDistance = sb.toString().replaceAll("\\s", NBSP); html.append(cumulativeTimeAndDistance); html.append("
"); sb = new StringBuilder(); - sb.append(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance, getMyApplication())); + sb.append(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance, app)); sb.append(" - "); sb.append(OsmAndFormatter.getFormattedDistance(cumulativeInfo.distance + routeDirectionInfo.distance, app)); sb.append(BR); @@ -1776,7 +1777,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { } private int getInitialMenuState() { - return MenuState.FULL_SCREEN; + return FULL_SCREEN; } public boolean slideUp() { @@ -1809,14 +1810,14 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { public int getSupportedMenuStates() { if (!portrait) { - return MenuState.FULL_SCREEN; + return FULL_SCREEN; } else { return getSupportedMenuStatesPortrait(); } } protected int getSupportedMenuStatesPortrait() { - return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN | MenuState.FULL_SCREEN; + return HEADER_ONLY | HALF_SCREEN | FULL_SCREEN; } public static boolean showInstance(final MapActivity mapActivity, int routeId) { @@ -1967,11 +1968,11 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { return topScreenPosY; } switch (menuState) { - case MenuState.HEADER_ONLY: + case HEADER_ONLY: return getHeaderOnlyTopY(); - case MenuState.HALF_SCREEN: + case HALF_SCREEN: return minHalfY; - case MenuState.FULL_SCREEN: + case FULL_SCREEN: return getFullScreenTopPosY(); default: return 0; @@ -1983,21 +1984,21 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { int currentMenuState = getCurrentMenuState(); if (portrait) { - int headerDist = Math.abs(currentY - getMenuStatePosY(MenuState.HEADER_ONLY)); - int halfDist = Math.abs(currentY - getMenuStatePosY(MenuState.HALF_SCREEN)); - int fullDist = Math.abs(currentY - getMenuStatePosY(MenuState.FULL_SCREEN)); + int headerDist = Math.abs(currentY - getMenuStatePosY(HEADER_ONLY)); + int halfDist = Math.abs(currentY - getMenuStatePosY(HALF_SCREEN)); + int fullDist = Math.abs(currentY - getMenuStatePosY(FULL_SCREEN)); int newState; if (headerDist < halfDist && headerDist < fullDist) { - newState = MenuState.HEADER_ONLY; + newState = HEADER_ONLY; } else if (halfDist < headerDist && halfDist < fullDist) { - newState = MenuState.HALF_SCREEN; + newState = HALF_SCREEN; } else { - newState = MenuState.FULL_SCREEN; + newState = FULL_SCREEN; } - if (slidingDown && currentMenuState == MenuState.FULL_SCREEN && getViewY() < getFullScreenTopPosY()) { + if (slidingDown && currentMenuState == FULL_SCREEN && getViewY() < getFullScreenTopPosY()) { slidingDown = false; - newState = MenuState.FULL_SCREEN; + newState = FULL_SCREEN; } if (menuBottomViewHeight > 0 && slidingUp) { while (getCurrentMenuState() != newState) { @@ -2006,7 +2007,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { } } } else if (slidingDown) { - if (currentMenuState == MenuState.HEADER_ONLY) { + if (currentMenuState == HEADER_ONLY) { needCloseMenu = true; } else { while (getCurrentMenuState() != newState) { @@ -2033,7 +2034,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { } } int newMenuState = getCurrentMenuState(); - boolean needMapAdjust = currentMenuState != newMenuState && newMenuState != MenuState.FULL_SCREEN; + boolean needMapAdjust = currentMenuState != newMenuState && newMenuState != FULL_SCREEN; applyPosY(currentY, needCloseMenu, needMapAdjust, currentMenuState, newMenuState, 0); } @@ -2053,20 +2054,20 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { int posY = 0; switch (destinationState) { - case MenuState.HEADER_ONLY: - posY = getMenuStatePosY(MenuState.HEADER_ONLY); + case HEADER_ONLY: + posY = getMenuStatePosY(HEADER_ONLY); break; - case MenuState.HALF_SCREEN: - posY = getMenuStatePosY(MenuState.HALF_SCREEN); + case HALF_SCREEN: + posY = getMenuStatePosY(HALF_SCREEN); break; - case MenuState.FULL_SCREEN: + case FULL_SCREEN: if (currentY != CURRENT_Y_UNDEFINED) { int maxPosY = viewHeight - menuFullHeightMax; - int minPosY = getMenuStatePosY(MenuState.FULL_SCREEN); + int minPosY = getMenuStatePosY(FULL_SCREEN); if (maxPosY > minPosY) { maxPosY = minPosY; } - if (currentY > minPosY || previousState != MenuState.FULL_SCREEN) { + if (currentY > minPosY || previousState != FULL_SCREEN) { posY = minPosY; } else if (currentY < maxPosY) { posY = maxPosY; @@ -2074,7 +2075,7 @@ public class ShowRouteInfoDialogFragment extends BaseOsmAndFragment { posY = currentY; } } else { - posY = getMenuStatePosY(MenuState.FULL_SCREEN); + posY = getMenuStatePosY(FULL_SCREEN); } break; default: