blob: 21615c55cbf80ad6e5403dcbca380cf67c967440 [file] [log] [blame]
package net.osmand.plus.views.mapwidgets;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.hardware.GeomagneticField;
import android.os.BatteryManager;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.text.format.DateFormat;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.StateChangedListener;
import net.osmand.binary.RouteDataObject;
import net.osmand.data.LatLon;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.MapMarkersHelper.MapMarker;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandSettings;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.MapViewTrackingUtilities;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.WaypointHelper;
import net.osmand.plus.routepreparationmenu.MapRouteInfoMenu;
import net.osmand.plus.routing.AlarmInfo;
import net.osmand.plus.routing.AlarmInfo.AlarmInfoType;
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
import net.osmand.plus.routing.RouteDirectionInfo;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.AnimateDraggingMapThread;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.TurnPathHelper;
import net.osmand.plus.views.mapwidgets.MapWidgetRegistry.WidgetState;
import net.osmand.router.RouteResultPreparation;
import net.osmand.router.TurnType;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RouteInfoWidgetsFactory {
public NextTurnInfoWidget createNextInfoControl(final Activity activity,
final OsmandApplication app, boolean horisontalMini) {
final OsmandSettings settings = app.getSettings();
final RoutingHelper routingHelper = app.getRoutingHelper();
final NextTurnInfoWidget nextTurnInfo = new NextTurnInfoWidget(activity, app, horisontalMini) {
NextDirectionInfo calc1 = new NextDirectionInfo();
@Override
public boolean updateInfo(DrawSettings drawSettings) {
boolean followingMode = routingHelper.isFollowingMode() || app.getLocationProvider().getLocationSimulation().isRouteAnimating();
TurnType turnType = null;
boolean deviatedFromRoute = false;
int turnImminent = 0;
int nextTurnDistance = 0;
if (routingHelper != null && routingHelper.isRouteCalculated() && followingMode) {
deviatedFromRoute = routingHelper.isDeviatedFromRoute();
if (deviatedFromRoute) {
turnImminent = 0;
turnType = TurnType.valueOf(TurnType.OFFR, settings.DRIVING_REGION.get().leftHandDriving);
setDeviatePath((int) routingHelper.getRouteDeviation());
} else {
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true);
if (r != null && r.distanceTo > 0 && r.directionInfo != null) {
turnType = r.directionInfo.getTurnType();
nextTurnDistance = r.distanceTo;
turnImminent = r.imminent;
}
}
}
setTurnType(turnType);
setTurnImminent(turnImminent, deviatedFromRoute);
setTurnDistance(nextTurnDistance);
return true;
}
};
nextTurnInfo.setOnClickListener(new View.OnClickListener() {
// int i = 0;
// boolean leftSide = false;
@Override
public void onClick(View v) {
// for test rendering purposes
// final int l = TurnType.predefinedTypes.length;
// final int exits = 5;
// i++;
// if (i % (l + exits) >= l ) {
// nextTurnInfo.turnType = TurnType.valueOf("EXIT" + (i % (l + exits) - l + 1), leftSide);
// float a = leftSide? -180 + (i % (l + exits) - l + 1) * 50: 180 - (i % (l + exits) - l + 1) * 50;
// nextTurnInfo.turnType.setTurnAngle(a < 0 ? a + 360 : a);
// nextTurnInfo.exitOut = (i % (l + exits) - l + 1)+"";
// } else {
// nextTurnInfo.turnType = TurnType.valueOf(TurnType.predefinedTypes[i % (TurnType.predefinedTypes.length + exits)], leftSide);
// nextTurnInfo.exitOut = "";
// }
// nextTurnInfo.turnImminent = (nextTurnInfo.turnImminent + 1) % 3;
// nextTurnInfo.nextTurnDirection = 580;
// TurnPathHelper.calcTurnPath(nextTurnInfo.pathForTurn, nextTurnInfo.turnType,nextTurnInfo.pathTransform);
if(routingHelper.isRouteCalculated() && !routingHelper.isDeviatedFromRoute()) {
routingHelper.getVoiceRouter().announceCurrentDirection(null);
}
}
});
// initial state
return nextTurnInfo;
}
public NextTurnInfoWidget createNextNextInfoControl(final Activity activity,
final OsmandApplication app, boolean horisontalMini) {
final RoutingHelper routingHelper = app.getRoutingHelper();
final NextTurnInfoWidget nextTurnInfo = new NextTurnInfoWidget(activity, app, horisontalMini) {
NextDirectionInfo calc1 = new NextDirectionInfo();
@Override
public boolean updateInfo(DrawSettings drawSettings) {
boolean followingMode = routingHelper.isFollowingMode() || app.getLocationProvider().getLocationSimulation().isRouteAnimating();
TurnType turnType = null;
boolean deviatedFromRoute = false;
int turnImminent = 0;
int nextTurnDistance = 0;
if (routingHelper != null && routingHelper.isRouteCalculated() && followingMode) {
deviatedFromRoute = routingHelper.isDeviatedFromRoute() ;
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true);
if (!deviatedFromRoute) {
if (r != null) {
r = routingHelper.getNextRouteDirectionInfoAfter(r, calc1, true);
}
}
if (r != null && r.distanceTo > 0 && r.directionInfo != null) {
turnType = r.directionInfo.getTurnType();
turnImminent = r.imminent;
nextTurnDistance = r.distanceTo;
}
}
setTurnType(turnType);
setTurnImminent(turnImminent, deviatedFromRoute);
setTurnDistance(nextTurnDistance);
return true;
}
};
nextTurnInfo.setOnClickListener(new View.OnClickListener() {
// int i = 0;
@Override
public void onClick(View v) {
// uncomment to test turn info rendering
// final int l = TurnType.predefinedTypes.length;
// final int exits = 5;
// i++;
// if (i % (l + exits) >= l ) {
// nextTurnInfo.turnType = TurnType.valueOf("EXIT" + (i % (l + exits) - l + 1), true);
// nextTurnInfo.exitOut = (i % (l + exits) - l + 1)+"";
// float a = 180 - (i % (l + exits) - l + 1) * 50;
// nextTurnInfo.turnType.setTurnAngle(a < 0 ? a + 360 : a);
// } else {
// nextTurnInfo.turnType = TurnType.valueOf(TurnType.predefinedTypes[i % (TurnType.predefinedTypes.length + exits)], true);
// nextTurnInfo.exitOut = "";
// }
// nextTurnInfo.turnImminent = (nextTurnInfo.turnImminent + 1) % 3;
// nextTurnInfo.nextTurnDirection = 580;
// TurnPathHelper.calcTurnPath(nextTurnInfo.pathForTurn, nexsweepAngletTurnInfo.turnType,nextTurnInfo.pathTransform);
// showMiniMap = true;
}
});
// initial state
return nextTurnInfo;
}
public static class TimeControlWidgetState extends WidgetState {
public static final int TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME = R.id.time_control_widget_state_arrival_time;
public static final int TIME_CONTROL_WIDGET_STATE_TIME_TO_GO = R.id.time_control_widget_state_time_to_go;
private final OsmandPreference<Boolean> showArrival;
private final boolean intermediate;
public TimeControlWidgetState(OsmandApplication ctx, boolean intermediate) {
super(ctx);
this.intermediate = intermediate;
if (intermediate) {
showArrival = ctx.getSettings().SHOW_INTERMEDIATE_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME;
} else {
showArrival = ctx.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME;
}
}
@Override
public int getMenuTitleId() {
if (intermediate) {
return showArrival.get() ? R.string.access_intermediate_arrival_time : R.string.map_widget_intermediate_time;
}
return showArrival.get() ? R.string.access_arrival_time : R.string.map_widget_time;
}
@Override
public int getMenuIconId() {
if (intermediate) {
return R.drawable.ic_action_intermediate_destination_time;
}
return showArrival.get() ? R.drawable.ic_action_time : R.drawable.ic_action_time_to_distance;
}
@Override
public int getMenuItemId() {
return showArrival.get() ? TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME : TIME_CONTROL_WIDGET_STATE_TIME_TO_GO;
}
@Override
public int[] getMenuTitleIds() {
if (intermediate) {
return new int[]{R.string.access_intermediate_arrival_time, R.string.map_widget_intermediate_time};
}
return new int[]{R.string.access_arrival_time, R.string.map_widget_time};
}
@Override
public int[] getMenuIconIds() {
if (intermediate) {
return new int[]{R.drawable.ic_action_intermediate_destination_time, R.drawable.ic_action_intermediate_destination_time};
}
return new int[]{R.drawable.ic_action_time, R.drawable.ic_action_time_to_distance};
}
@Override
public int[] getMenuItemIds() {
return new int[]{TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME, TIME_CONTROL_WIDGET_STATE_TIME_TO_GO};
}
@Override
public void changeState(int stateId) {
showArrival.set(stateId == TIME_CONTROL_WIDGET_STATE_ARRIVAL_TIME);
}
}
public TextInfoWidget createTimeControl(final MapActivity map, final boolean intermediate){
final RoutingHelper routingHelper = map.getRoutingHelper();
final OsmandApplication ctx = map.getMyApplication();
final OsmandPreference<Boolean> showArrival = intermediate
? ctx.getSettings().SHOW_INTERMEDIATE_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME
: ctx.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME;
final TextInfoWidget leftTimeControl = new TextInfoWidget(map) {
private long cachedLeftTime = 0;
@Override
public boolean updateInfo(DrawSettings drawSettings) {
setTimeControlIcons(this, showArrival.get(), intermediate);
int time = 0;
if (routingHelper != null && routingHelper.isRouteCalculated()) {
//boolean followingMode = routingHelper.isFollowingMode();
time = intermediate ? routingHelper.getLeftTimeNextIntermediate() : routingHelper.getLeftTime();
if (time != 0) {
if (/*followingMode && */showArrival.get()) {
long toFindTime = time * 1000 + System.currentTimeMillis();
if (Math.abs(toFindTime - cachedLeftTime) > 30000) {
cachedLeftTime = toFindTime;
setContentTitle(map.getString(R.string.access_arrival_time));
if (DateFormat.is24HourFormat(ctx)) {
setText(DateFormat.format("k:mm", toFindTime).toString(), null); //$NON-NLS-1$
} else {
setText(DateFormat.format("h:mm", toFindTime).toString(),
DateFormat.format("aa", toFindTime).toString()); //$NON-NLS-1$
}
return true;
}
} else {
if (Math.abs(time - cachedLeftTime) > 30) {
cachedLeftTime = time;
int hours = time / (60 * 60);
int minutes = (time / 60) % 60;
setContentTitle(map.getString(R.string.map_widget_time));
setText(String.format("%d:%02d", hours, minutes), null); //$NON-NLS-1$
return true;
}
}
}
}
if (time == 0 && cachedLeftTime != 0) {
cachedLeftTime = 0;
setText(null, null);
return true;
}
return false;
};
};
leftTimeControl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showArrival.set(!showArrival.get());
setTimeControlIcons(leftTimeControl, showArrival.get(), intermediate);
map.getMapView().refreshMap();
}
});
leftTimeControl.setText(null, null);
setTimeControlIcons(leftTimeControl, showArrival.get(), intermediate);
return leftTimeControl;
}
private void setTimeControlIcons(TextInfoWidget timeControl, boolean showArrival, boolean intermediate) {
int iconLight = intermediate
? R.drawable.widget_intermediate_time_day
: showArrival ? R.drawable.widget_time_day : R.drawable.widget_time_to_distance_day;
int iconDark = intermediate
? R.drawable.widget_intermediate_time_night
: showArrival ? R.drawable.widget_time_night : R.drawable.widget_time_to_distance_night;
timeControl.setIcons(iconLight, iconDark);
}
public TextInfoWidget createPlainTimeControl(final MapActivity map){
final OsmandApplication ctx = map.getMyApplication();
final TextInfoWidget plainTimeControl = new TextInfoWidget(map) {
private long cachedLeftTime = 0;
@Override
public boolean updateInfo(DrawSettings drawSettings) {
long time = System.currentTimeMillis();
if(time - cachedLeftTime > 5000) {
cachedLeftTime = time;
if (DateFormat.is24HourFormat(ctx)) {
setText(DateFormat.format("k:mm", time).toString(), null); //$NON-NLS-1$
} else {
setText(DateFormat.format("h:mm", time).toString(),
DateFormat.format("aa", time).toString()); //$NON-NLS-1$
}
}
return false;
};
};
plainTimeControl.setText(null, null);
plainTimeControl.setIcons(R.drawable.widget_time_day, R.drawable.widget_time_night);
return plainTimeControl;
}
public TextInfoWidget createBatteryControl(final MapActivity map){
final int battery = R.drawable.widget_battery_day;
final int batteryN = R.drawable.widget_battery_night;
final int batteryCharging = R.drawable.widget_battery_charging_day;
final int batteryChargingN = R.drawable.widget_battery_charging_night;
final OsmandApplication ctx = map.getMyApplication();
final TextInfoWidget batteryControl = new TextInfoWidget(map) {
private long cachedLeftTime = 0;
@Override
public boolean updateInfo(DrawSettings drawSettings) {
long time = System.currentTimeMillis();
if (time - cachedLeftTime > 1000) {
cachedLeftTime = time;
Intent batteryIntent = ctx.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int status = batteryIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
if (level == -1 || scale == -1 || status == -1) {
setText("?", null);
setIcons(battery, batteryN);
} else {
boolean charging = ((status == BatteryManager.BATTERY_STATUS_CHARGING) ||
(status == BatteryManager.BATTERY_STATUS_FULL));
setText(String.format("%d%%", (level * 100) / scale), null );
setIcons(charging ? batteryCharging : battery, charging ? batteryChargingN : batteryN);
}
}
return false;
};
};
batteryControl.setText(null, null);
batteryControl.setIcons(battery, batteryN);
return batteryControl;
}
public TextInfoWidget createMaxSpeedControl(final MapActivity map) {
final RoutingHelper rh = map.getMyApplication().getRoutingHelper();
final OsmAndLocationProvider locationProvider = map.getMyApplication().getLocationProvider();
final MapViewTrackingUtilities trackingUtilities = map.getMapViewTrackingUtilities();
final TextInfoWidget speedControl = new TextInfoWidget(map) {
private float cachedSpeed = 0;
@Override
public boolean updateInfo(DrawSettings drawSettings) {
float mx = 0;
if ((rh == null || !rh.isFollowingMode() || rh.isDeviatedFromRoute() || rh.getCurrentGPXRoute() != null)
&& trackingUtilities.isMapLinkedToLocation()) {
RouteDataObject ro = locationProvider.getLastKnownRouteSegment();
if(ro != null) {
mx = ro.getMaximumSpeed(ro.bearingVsRouteDirection(locationProvider.getLastKnownLocation()));
}
} else if (rh != null) {
mx = rh.getCurrentMaxSpeed();
} else {
mx = 0f;
}
if (cachedSpeed != mx) {
cachedSpeed = mx;
if (cachedSpeed == 0) {
setText(null, null);
} else if(cachedSpeed == RouteDataObject.NONE_MAX_SPEED) {
setText(map.getString(R.string.max_speed_none), "");
} else {
String ds = OsmAndFormatter.getFormattedSpeed(cachedSpeed, map.getMyApplication());
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setText(ds, null);
} else {
setText(ds.substring(0, ls), ds.substring(ls + 1));
}
}
return true;
}
return false;
}
};
speedControl.setIcons(R.drawable.widget_max_speed_day, R.drawable.widget_max_speed_night);
speedControl.setText(null, null);
return speedControl;
}
public TextInfoWidget createSpeedControl(final MapActivity map) {
final OsmandApplication app = map.getMyApplication();
final TextInfoWidget speedControl = new TextInfoWidget(map) {
private float cachedSpeed = 0;
@Override
public boolean updateInfo(DrawSettings drawSettings) {
Location loc = app.getLocationProvider().getLastKnownLocation();
// draw speed
if (loc != null && loc.hasSpeed()) {
// .1 mps == 0.36 kph
float minDelta = .1f;
// Update more often at walk/run speeds, since we give higher resolution
// and use .02 instead of .03 to account for rounding effects.
if (cachedSpeed < 6) {
minDelta = .015f;
}
if (Math.abs(loc.getSpeed() - cachedSpeed) > minDelta) {
cachedSpeed = loc.getSpeed();
String ds = OsmAndFormatter.getFormattedSpeed(cachedSpeed, app);
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setText(ds, null);
} else {
setText(ds.substring(0, ls), ds.substring(ls + 1));
}
return true;
}
} else if (cachedSpeed != 0) {
cachedSpeed = 0;
setText(null, null);
return true;
}
return false;
}
};
speedControl.setIcons(R.drawable.widget_speed_day, R.drawable.widget_speed_night);
speedControl.setText(null, null);
return speedControl;
}
public abstract static class DistanceToPointInfoControl extends TextInfoWidget {
private final OsmandMapTileView view;
private float[] calculations = new float[1];
private int cachedMeters;
public DistanceToPointInfoControl(MapActivity ma, int res, int resNight) {
super(ma);
this.view = ma.getMapView();
if (res != 0 && resNight != 0) {
setIcons(res, resNight);
}
setText(null, null);
setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
click(view);
}
});
}
protected void click(final OsmandMapTileView view) {
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
LatLon pointToNavigate = getPointToNavigate();
if (pointToNavigate != null) {
int fZoom = view.getZoom() < 15 ? 15 : view.getZoom();
thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true);
}
}
@Override
public boolean updateInfo(DrawSettings drawSettings) {
int d = getDistance();
if (distChanged(cachedMeters, d)) {
cachedMeters = d;
if (cachedMeters <= 20) {
cachedMeters = 0;
setText(null, null);
} else {
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, view.getApplication());
int ls = ds.lastIndexOf(' ');
if (ls == -1) {
setText(ds, null);
} else {
setText(ds.substring(0, ls), ds.substring(ls + 1));
}
}
return true;
}
return false;
}
public abstract LatLon getPointToNavigate();
public int getDistance() {
int d = 0;
LatLon l = getPointToNavigate();
if (l != null) {
Location.distanceBetween(view.getLatitude(), view.getLongitude(), l.getLatitude(), l.getLongitude(), calculations);
d = (int) calculations[0];
}
return d;
}
}
public TextInfoWidget createDistanceControl(final MapActivity map) {
DistanceToPointInfoControl distanceControl = new DistanceToPointInfoControl(map,R.drawable.widget_target_day,
R.drawable.widget_target_night) {
@Override
public LatLon getPointToNavigate() {
TargetPoint p = map.getPointToNavigate();
return p == null ? null : p.point;
}
@Override
public int getDistance() {
if (map.getRoutingHelper().isRouteCalculated()) {
return map.getRoutingHelper().getLeftDistance();
}
return super.getDistance();
}
};
return distanceControl;
}
public TextInfoWidget createIntermediateDistanceControl(final MapActivity map) {
final TargetPointsHelper targets = map.getMyApplication().getTargetPointsHelper();
DistanceToPointInfoControl distanceControl = new DistanceToPointInfoControl(map, R.drawable.widget_intermediate_day,
R.drawable.widget_intermediate_night) {
@Override
protected void click(OsmandMapTileView view) {
if(targets.getIntermediatePoints().size() > 1) {
map.getMapActions().openIntermediatePointsDialog();
} else {
super.click(view);
}
}
@Override
public LatLon getPointToNavigate() {
TargetPoint p = targets.getFirstIntermediatePoint();
return p == null ? null : p.point;
}
@Override
public int getDistance() {
if (getPointToNavigate() != null && map.getRoutingHelper().isRouteCalculated()) {
return map.getRoutingHelper().getLeftDistanceNextIntermediate();
}
return super.getDistance();
}
};
return distanceControl;
}
public static class BearingWidgetState extends WidgetState {
public static final int BEARING_WIDGET_STATE_RELATIVE_BEARING = R.id.bearing_widget_state_relative_bearing;
public static final int BEARING_WIDGET_STATE_MAGNETIC_BEARING = R.id.bearing_widget_state_magnetic_bearing;
private final OsmandPreference<Boolean> showRelativeBearing;
public BearingWidgetState(OsmandApplication ctx) {
super(ctx);
showRelativeBearing = ctx.getSettings().SHOW_RELATIVE_BEARING_OTHERWISE_REGULAR_BEARING;
}
@Override
public int getMenuTitleId() {
return showRelativeBearing.get() ? R.string.map_widget_bearing : R.string.map_widget_magnetic_bearing;
}
@Override
public int getMenuIconId() {
return showRelativeBearing.get() ? R.drawable.ic_action_relative_bearing : R.drawable.ic_action_bearing;
}
@Override
public int getMenuItemId() {
return showRelativeBearing.get() ? BEARING_WIDGET_STATE_RELATIVE_BEARING : BEARING_WIDGET_STATE_MAGNETIC_BEARING;
}
@Override
public int[] getMenuTitleIds() {
return new int[]{R.string.map_widget_magnetic_bearing, R.string.map_widget_bearing};
}
@Override
public int[] getMenuIconIds() {
return new int[]{R.drawable.ic_action_bearing, R.drawable.ic_action_relative_bearing};
}
@Override
public int[] getMenuItemIds() {
return new int[]{BEARING_WIDGET_STATE_MAGNETIC_BEARING, BEARING_WIDGET_STATE_RELATIVE_BEARING};
}
@Override
public void changeState(int stateId) {
showRelativeBearing.set(stateId == BEARING_WIDGET_STATE_RELATIVE_BEARING);
}
}
public TextInfoWidget createBearingControl(final MapActivity map) {
final int bearingResId = R.drawable.widget_bearing_day;
final int bearingNightResId = R.drawable.widget_bearing_night;
final int relativeBearingResId = R.drawable.widget_relative_bearing_day;
final int relativeBearingNightResId = R.drawable.widget_relative_bearing_night;
final OsmandApplication ctx = map.getMyApplication();
final OsmandPreference<Boolean> showRelativeBearing = ctx.getSettings().SHOW_RELATIVE_BEARING_OTHERWISE_REGULAR_BEARING;
final TextInfoWidget bearingControl = new TextInfoWidget(map) {
private int cachedDegrees;
private float MIN_SPEED_FOR_HEADING = 1f;
private boolean angularUnitTypeChanged = false;
private StateChangedListener<OsmandSettings.AngularConstants> listener = new StateChangedListener<OsmandSettings.AngularConstants>() {
@Override
public void stateChanged(OsmandSettings.AngularConstants change) {
angularUnitTypeChanged = true;
}
};
{
getOsmandApplication().getSettings().ANGULAR_UNITS.addListener(listener);
}
private LatLon getNextTargetPoint() {
List<TargetPoint> points = getOsmandApplication().getTargetPointsHelper().getIntermediatePointsWithTarget();
return points.isEmpty() ? null : points.get(0).point;
}
@Override
public boolean updateInfo(DrawSettings drawSettings) {
boolean relative = showRelativeBearing.get();
boolean modeChanged = setIcons(relative ? relativeBearingResId : bearingResId, relative ? relativeBearingNightResId : bearingNightResId);
setContentTitle(relative ? R.string.map_widget_bearing : R.string.map_widget_magnetic_bearing);
int b = getBearing(relative);
if (angularUnitTypeChanged || degreesChanged(cachedDegrees, b) || modeChanged) {
angularUnitTypeChanged = false;
cachedDegrees = b;
if (b != -1000) {
setText(OsmAndFormatter.getFormattedAzimuth(b, getOsmandApplication()) + (relative ? "" : " M"), null);
} else {
setText(null, null);
}
return true;
}
return false;
}
public int getBearing(boolean relative) {
int d = -1000;
Location myLocation = getOsmandApplication().getLocationProvider().getLastKnownLocation();
LatLon l = getNextTargetPoint();
if (l == null) {
List<MapMarker> markers = getOsmandApplication().getMapMarkersHelper().getMapMarkers();
if (markers.size() > 0) {
l = markers.get(0).point;
}
}
if (myLocation != null && l != null) {
Location dest = new Location("");
dest.setLatitude(l.getLatitude());
dest.setLongitude(l.getLongitude());
dest.setBearing(myLocation.bearingTo(dest));
GeomagneticField destGf = new GeomagneticField((float) dest.getLatitude(), (float) dest.getLongitude(), (float) dest.getAltitude(),
System.currentTimeMillis());
float bearingToDest = dest.getBearing() - destGf.getDeclination();
if (relative) {
float b = -1000;
Float heading = getOsmandApplication().getLocationProvider().getHeading();
if ((myLocation.getSpeed() < MIN_SPEED_FOR_HEADING || !myLocation.hasBearing())
&& heading != null) {
b = heading;
} else if (myLocation.hasBearing()) {
GeomagneticField myLocGf = new GeomagneticField((float) myLocation.getLatitude(), (float) myLocation.getLongitude(), (float) myLocation.getAltitude(),
System.currentTimeMillis());
b = myLocation.getBearing() - myLocGf.getDeclination();
}
if (b > -1000) {
bearingToDest -= b;
if (bearingToDest > 180f) {
bearingToDest -= 360f;
} else if (bearingToDest < -180f) {
bearingToDest += 360f;
}
d = (int) bearingToDest;
}
} else {
d = (int) bearingToDest;
}
}
return d;
}
};
bearingControl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showRelativeBearing.set(!showRelativeBearing.get());
map.refreshMap();
}
});
bearingControl.setText(null, null);
bearingControl.setIcons(!showRelativeBearing.get() ? bearingResId : relativeBearingResId,
!showRelativeBearing.get() ? bearingNightResId : relativeBearingNightResId);
return bearingControl;
}
public static class LanesControl {
private MapViewTrackingUtilities trackingUtilities;
private OsmAndLocationProvider locationProvider;
private MapRouteInfoMenu mapRouteInfoMenu;
private RoutingHelper rh;
private OsmandSettings settings;
private ImageView lanesView;
private TextView lanesText;
private TextView lanesShadowText;
private OsmandApplication app;
private int dist;
private LanesDrawable lanesDrawable;
private View centerInfo;
private int shadowRadius;
public LanesControl(final MapActivity map, final OsmandMapTileView view) {
lanesView = (ImageView) map.findViewById(R.id.map_lanes);
lanesText = (TextView) map.findViewById(R.id.map_lanes_dist_text);
lanesShadowText = (TextView) map.findViewById(R.id.map_lanes_dist_text_shadow);
centerInfo = (View) map.findViewById(R.id.map_center_info);
lanesDrawable = new LanesDrawable(map, map.getMapView().getScaleCoefficient());
lanesView.setImageDrawable(lanesDrawable);
trackingUtilities = map.getMapViewTrackingUtilities();
locationProvider = map.getMyApplication().getLocationProvider();
settings = map.getMyApplication().getSettings();
mapRouteInfoMenu = map.getMapRouteInfoMenu();
rh = map.getMyApplication().getRoutingHelper();
app = map.getMyApplication();
}
public void updateTextSize(boolean isNight, int textColor, int textShadowColor, boolean textBold, int shadowRadius) {
this.shadowRadius = shadowRadius;
TextInfoWidget.updateTextColor(lanesText, lanesShadowText, textColor, textShadowColor, textBold, shadowRadius);
}
public boolean updateInfo(DrawSettings drawSettings) {
boolean visible = false;
int locimminent = -1;
int[] loclanes = null;
int dist = 0;
// TurnType primary = null;
if ((rh == null || !rh.isFollowingMode() || rh.isDeviatedFromRoute() || rh.getCurrentGPXRoute() != null)
&& trackingUtilities.isMapLinkedToLocation() && settings.SHOW_LANES.get()) {
RouteDataObject ro = locationProvider.getLastKnownRouteSegment();
Location lp = locationProvider.getLastKnownLocation();
if(ro != null) {
float degree = lp == null || !lp.hasBearing() ? 0 : lp.getBearing();
loclanes = RouteResultPreparation.parseTurnLanes(ro, degree / 180 * Math.PI);
if(loclanes == null) {
loclanes = RouteResultPreparation.parseLanes(ro, degree / 180 * Math.PI);
}
}
} else if (rh != null && rh.isRouteCalculated() ) {
if (rh.isFollowingMode() && settings.SHOW_LANES.get()) {
NextDirectionInfo r = rh.getNextRouteDirectionInfo(new NextDirectionInfo(), false);
if(r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) {
loclanes = r.directionInfo.getTurnType().getLanes();
// primary = r.directionInfo.getTurnType();
locimminent = r.imminent;
// Do not show too far
if ((r.distanceTo > 800 && r.directionInfo.getTurnType().isSkipToSpeak()) || r.distanceTo > 1200) {
loclanes = null;
}
dist = r.distanceTo;
}
} else {
int di = MapRouteInfoMenu.getDirectionInfo();
if (di >= 0 && mapRouteInfoMenu.isVisible()
&& di < rh.getRouteDirections().size()) {
RouteDirectionInfo next = rh.getRouteDirections().get(di);
if (next != null) {
loclanes = next.getTurnType().getLanes();
// primary = next.getTurnType();
}
} else {
loclanes = null;
}
}
}
visible = loclanes != null && loclanes.length > 0 && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible;
if (visible) {
if (!Arrays.equals(lanesDrawable.lanes, loclanes) ||
(locimminent == 0) != lanesDrawable.imminent) {
lanesDrawable.imminent = locimminent == 0;
lanesDrawable.lanes = loclanes;
lanesDrawable.updateBounds();
lanesView.setImageDrawable(null);
lanesView.setImageDrawable(lanesDrawable);
lanesView.requestLayout();
lanesView.invalidate();
}
if (distChanged(dist, this.dist)) {
this.dist = dist;
if(dist == 0) {
lanesShadowText.setText("");
lanesText.setText("");
} else {
lanesShadowText.setText(OsmAndFormatter.getFormattedDistance(dist, app));
lanesText.setText(OsmAndFormatter.getFormattedDistance(dist, app));
}
lanesShadowText.invalidate();
lanesText.invalidate();
}
}
AndroidUiHelper.updateVisibility(lanesShadowText, visible && shadowRadius > 0);
AndroidUiHelper.updateVisibility(lanesText, visible);
AndroidUiHelper.updateVisibility(lanesView, visible);
AndroidUiHelper.updateVisibility(centerInfo, visible);
return true;
}
}
private static class LanesDrawable extends Drawable {
int[] lanes = null;
boolean imminent = false;
private Context ctx;
private Paint paintBlack;
private Paint paintRouteDirection;
private Paint paintSecondTurn;
private float scaleCoefficient;
private int height;
private int width;
private float delta;
private float laneHalfSize;
private static final float miniCoeff = 2f;
private final boolean leftSide;
private int imgMinDelta;
private int imgMargin;
LanesDrawable(MapActivity ctx, float scaleCoefficent) {
this.ctx = ctx;
OsmandSettings settings = ctx.getMyApplication().getSettings();
leftSide = settings.DRIVING_REGION.get().leftHandDriving;
imgMinDelta = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_min_delta);
imgMargin = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_margin);
laneHalfSize = ctx.getResources().getDimensionPixelSize(R.dimen.widget_turn_lane_size) / 2;
this.scaleCoefficient = scaleCoefficent;
paintBlack = new Paint(Paint.ANTI_ALIAS_FLAG);
paintBlack.setStyle(Style.STROKE);
paintBlack.setColor(Color.BLACK);
paintBlack.setStrokeWidth(scaleCoefficent);
paintRouteDirection = new Paint(Paint.ANTI_ALIAS_FLAG);
paintRouteDirection.setStyle(Style.FILL);
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow));
paintSecondTurn = new Paint(Paint.ANTI_ALIAS_FLAG);
paintSecondTurn.setStyle(Style.FILL);
paintSecondTurn.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
}
void updateBounds() {
float w = 0;
float h = 0;
float delta = imgMinDelta;
float coef = scaleCoefficient / miniCoeff;
if (lanes != null) {
List<RectF> boundsList = new ArrayList<>(lanes.length);
for (int i = 0; i < lanes.length; i++) {
int turnType = TurnType.getPrimaryTurn(lanes[i]);
int secondTurnType = TurnType.getSecondaryTurn(lanes[i]);
int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]);
RectF imgBounds = new RectF();
if (thirdTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
}
}
}
if (secondTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
}
}
}
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
}
}
if (imgBounds.right > 0)
{
boundsList.add(imgBounds);
float imageHeight = imgBounds.bottom;
if (imageHeight > h)
h = imageHeight;
}
}
if (boundsList.size() > 1) {
for (int i = 1; i < boundsList.size(); i++) {
RectF b1 = boundsList.get(i - 1);
RectF b2 = boundsList.get(i);
float d = b1.right + imgMargin * 2 - b2.left;
if (delta < d)
delta = d;
}
RectF b1 = boundsList.get(0);
RectF b2 = boundsList.get(boundsList.size() - 1);
w = -b1.left + (boundsList.size() - 1) * delta + b2.right;
} else if (boundsList.size() > 0) {
RectF b1 = boundsList.get(0);
w = b1.width();
}
if (w > 0) {
w += 4;
}
if (h > 0) {
h += 4;
}
}
this.width = (int) w;
this.height = (int) h;
this.delta = delta;
}
@Override
public int getIntrinsicHeight() {
return height;
}
@Override
public int getIntrinsicWidth() {
return width;
}
@Override
public void draw(@NonNull Canvas canvas) {
// setup default color
//canvas.drawColor(0, PorterDuff.Mode.CLEAR);
//to change color immediately when needed
if (lanes != null && lanes.length > 0) {
float coef = scaleCoefficient / miniCoeff;
canvas.save();
// canvas.translate((int) (16 * scaleCoefficient), 0);
for (int i = 0; i < lanes.length; i++) {
if ((lanes[i] & 1) == 1) {
paintRouteDirection.setColor(imminent ? ctx.getResources().getColor(R.color.nav_arrow_imminent) :
ctx.getResources().getColor(R.color.nav_arrow));
} else {
paintRouteDirection.setColor(ctx.getResources().getColor(R.color.nav_arrow_distant));
}
int turnType = TurnType.getPrimaryTurn(lanes[i]);
int secondTurnType = TurnType.getSecondaryTurn(lanes[i]);
int thirdTurnType = TurnType.getTertiaryTurn(lanes[i]);
RectF imgBounds = new RectF();
Path thirdTurnPath = null;
Path secondTurnPath = null;
Path firstTurnPath = null;
if (thirdTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.THIRD_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
thirdTurnPath = p;
}
}
}
if (secondTurnType > 0) {
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.SECOND_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
secondTurnPath = p;
}
}
}
Path p = TurnPathHelper.getPathFromTurnType(ctx.getResources(), turnType,
secondTurnType, thirdTurnType, TurnPathHelper.FIRST_TURN, coef, leftSide, true);
if (p != null) {
RectF b = new RectF();
p.computeBounds(b, true);
if (!b.isEmpty()) {
if (imgBounds.isEmpty()) {
imgBounds.set(b);
} else {
imgBounds.union(b);
}
firstTurnPath = p;
}
}
if (firstTurnPath != null || secondTurnPath != null || thirdTurnPath != null) {
if (i == 0) {
imgBounds.set(imgBounds.left - 2, imgBounds.top, imgBounds.right + 2, imgBounds.bottom);
canvas.translate(-imgBounds.left, 0);
} else {
canvas.translate(-laneHalfSize, 0);
}
// 1st pass
if (thirdTurnPath != null) {
//canvas.drawPath(thirdTurnPath, paintSecondTurn);
canvas.drawPath(thirdTurnPath, paintBlack);
}
if (secondTurnPath != null) {
//canvas.drawPath(secondTurnPath, paintSecondTurn);
canvas.drawPath(secondTurnPath, paintBlack);
}
if (firstTurnPath != null) {
//canvas.drawPath(firstTurnPath, paintRouteDirection);
canvas.drawPath(firstTurnPath, paintBlack);
}
// 2nd pass
if (thirdTurnPath != null) {
canvas.drawPath(thirdTurnPath, paintSecondTurn);
}
if (secondTurnPath != null) {
canvas.drawPath(secondTurnPath, paintSecondTurn);
}
if (firstTurnPath != null) {
canvas.drawPath(firstTurnPath, paintRouteDirection);
}
canvas.translate(laneHalfSize + delta, 0);
}
}
canvas.restore();
}
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return 0;
}
}
public LanesControl createLanesControl(final MapActivity map, final OsmandMapTileView view) {
return new LanesControl(map, view);
}
public static class RulerWidget {
private View layout;
private ImageView icon;
private TextView text;
private TextView textShadow;
private MapActivity ma;
private String cacheRulerText;
private int maxWidth;
private float cacheMapDensity;
private OsmandSettings.OsmandPreference<Float> mapDensity;
private int cacheRulerZoom;
private double cacheRulerTileX;
private double cacheRulerTileY;
private boolean orientationPortrait;
public RulerWidget(final OsmandApplication app, MapActivity ma) {
this.ma = ma;
layout = ma.findViewById(R.id.map_ruler_layout);
icon = (ImageView) ma.findViewById(R.id.map_ruler_image);
text = (TextView) ma.findViewById(R.id.map_ruler_text);
textShadow = (TextView) ma.findViewById(R.id.map_ruler_text_shadow);
maxWidth = ma.getResources().getDimensionPixelSize(R.dimen.map_ruler_width);
orientationPortrait = AndroidUiHelper.isOrientationPortrait(ma);
mapDensity = ma.getMyApplication().getSettings().MAP_DENSITY;
cacheMapDensity = mapDensity.get();
}
public void updateTextSize(boolean isNight, int textColor, int textShadowColor, int shadowRadius) {
TextInfoWidget.updateTextColor(text, textShadow, textColor, textShadowColor, false, shadowRadius);
icon.setBackgroundResource(isNight ? R.drawable.ruler_night : R.drawable.ruler);
}
public boolean updateInfo(RotatedTileBox tb, DrawSettings nightMode) {
boolean visible = true;
OsmandMapTileView view = ma.getMapView();
// update cache
if (view.isZooming()) {
visible = false;
} else if (!tb.isZoomAnimated() && (tb.getZoom() != cacheRulerZoom || Math.abs(tb.getCenterTileX() - cacheRulerTileX) > 1 || Math
.abs(tb.getCenterTileY() - cacheRulerTileY) > 1 || mapDensity.get() != cacheMapDensity) &&
tb.getPixWidth() > 0 && maxWidth > 0) {
cacheRulerZoom = tb.getZoom();
cacheRulerTileX = tb.getCenterTileX();
cacheRulerTileY = tb.getCenterTileY();
cacheMapDensity = mapDensity.get();
double pixDensity = tb.getPixDensity();
double roundedDist = OsmAndFormatter.calculateRoundedDist(maxWidth /
pixDensity, view.getApplication());
int cacheRulerDistPix = (int) (pixDensity * roundedDist);
cacheRulerText = OsmAndFormatter.getFormattedDistance((float) roundedDist, view.getApplication(), false);
textShadow.setText(cacheRulerText);
text.setText(cacheRulerText);
ViewGroup.LayoutParams lp = layout.getLayoutParams();
lp.width = cacheRulerDistPix;
layout.setLayoutParams(lp);
layout.requestLayout();
}
AndroidUiHelper.updateVisibility(layout, visible);
return true;
}
public void setVisibility(boolean visibility) {
layout.setVisibility(visibility ? View.VISIBLE : View.GONE);
}
}
public static class AlarmWidget {
private View layout;
private ImageView icon;
private TextView text;
private TextView bottomText;
private OsmandSettings settings;
private RoutingHelper rh;
private MapViewTrackingUtilities trackingUtilities;
private OsmAndLocationProvider locationProvider;
private WaypointHelper wh;
private int imgId;
private String textString;
private String bottomTextString;
public AlarmWidget(final OsmandApplication app, MapActivity ma) {
layout = ma.findViewById(R.id.map_alarm_warning);
icon = (ImageView) ma.findViewById(R.id.map_alarm_warning_icon);
text = (TextView) ma.findViewById(R.id.map_alarm_warning_text);
bottomText = (TextView) ma.findViewById(R.id.map_alarm_warning_text_bottom);
settings = app.getSettings();
rh = ma.getRoutingHelper();
trackingUtilities = ma.getMapViewTrackingUtilities();
locationProvider = app.getLocationProvider();
wh = app.getWaypointHelper();
}
public boolean updateInfo(DrawSettings drawSettings) {
boolean showRoutingAlarms = settings.SHOW_ROUTING_ALARMS.get();
boolean trafficWarnings = settings.SHOW_TRAFFIC_WARNINGS.get();
boolean cams = settings.SHOW_CAMERAS.get();
boolean peds = settings.SHOW_PEDESTRIAN.get();
boolean tunnels = settings.SHOW_TUNNELS.get();
boolean visible = false;
if ((rh.isFollowingMode() || trackingUtilities.isMapLinkedToLocation())
&& showRoutingAlarms && (trafficWarnings || cams)) {
AlarmInfo alarm;
if(rh.isFollowingMode() && !rh.isDeviatedFromRoute() && rh.getCurrentGPXRoute() == null) {
alarm = wh.getMostImportantAlarm(settings.SPEED_SYSTEM.get(), cams);
} else {
RouteDataObject ro = locationProvider.getLastKnownRouteSegment();
Location loc = locationProvider.getLastKnownLocation();
if(ro != null && loc != null) {
alarm = wh.calculateMostImportantAlarm(ro, loc, settings.METRIC_SYSTEM.get(),
settings.SPEED_SYSTEM.get(), cams);
} else {
alarm = null;
}
}
if(alarm != null) {
int locimgId = R.drawable.warnings_limit;
String text = "";
String bottomText = "";
if(alarm.getType() == AlarmInfoType.SPEED_LIMIT) {
if(settings.DRIVING_REGION.get().americanSigns){
locimgId = R.drawable.warnings_speed_limit_us;
//else case is done by drawing red ring
}
text = alarm.getIntValue() +"";
} else if(alarm.getType() == AlarmInfoType.SPEED_CAMERA) {
locimgId = R.drawable.warnings_speed_camera;
} else if(alarm.getType() == AlarmInfoType.BORDER_CONTROL) {
locimgId = R.drawable.warnings_border_control;
} else if(alarm.getType() == AlarmInfoType.HAZARD) {
if(settings.DRIVING_REGION.get().americanSigns){
locimgId = R.drawable.warnings_hazard_us;
} else {
locimgId = R.drawable.warnings_hazard;
}
} else if(alarm.getType() == AlarmInfoType.TOLL_BOOTH) {
//image done by drawing red ring
text = "$";
} else if(alarm.getType() == AlarmInfoType.TRAFFIC_CALMING) {
if(settings.DRIVING_REGION.get().americanSigns){
locimgId = R.drawable.warnings_traffic_calming_us;
} else {
locimgId = R.drawable.warnings_traffic_calming;
}
} else if(alarm.getType() == AlarmInfoType.STOP) {
locimgId = R.drawable.warnings_stop;
} else if(alarm.getType() == AlarmInfoType.RAILWAY) {
if(settings.DRIVING_REGION.get().americanSigns){
locimgId = R.drawable.warnings_railways_us;
} else {
locimgId = R.drawable.warnings_railways;
}
} else if(alarm.getType() == AlarmInfoType.PEDESTRIAN) {
if(settings.DRIVING_REGION.get().americanSigns){
locimgId = R.drawable.warnings_pedestrian_us;
} else {
locimgId = R.drawable.warnings_pedestrian;
}
} else if(alarm.getType() == AlarmInfoType.TUNNEL) {
if(settings.DRIVING_REGION.get().americanSigns){
locimgId = R.drawable.warnings_tunnel_us;
} else {
locimgId = R.drawable.warnings_tunnel;
}
bottomText = OsmAndFormatter.getFormattedAlarmInfoDistance(settings.getContext(), alarm.getFloatValue());
} else {
text = null;
bottomText = null;
}
visible = (text != null && text.length() > 0) || (locimgId != 0);
if (visible) {
if (alarm.getType() == AlarmInfoType.SPEED_CAMERA) {
visible = cams;
} else if (alarm.getType() == AlarmInfoType.PEDESTRIAN) {
visible = peds;
} else if (alarm.getType() == AlarmInfoType.TUNNEL) {
visible = tunnels;
} else {
visible = trafficWarnings;
}
}
if(visible) {
if(locimgId != imgId) {
imgId = locimgId;
icon.setImageResource(locimgId);
}
if (!Algorithms.objectEquals(text, this.textString)) {
textString = text;
this.text.setText(this.textString);
if (alarm.getType() == AlarmInfoType.SPEED_LIMIT && settings.DRIVING_REGION.get().americanSigns) {
this.text.setPadding(0, AndroidUtils.dpToPx(layout.getContext(), 20f), 0, 0);
} else {
this.text.setPadding(0, 0, 0, 0);
}
}
if (!Algorithms.objectEquals(bottomText, this.bottomTextString)) {
bottomTextString = bottomText;
this.bottomText.setText(this.bottomTextString);
this.bottomText.setTextColor(ContextCompat.getColor(layout.getContext(),
settings.DRIVING_REGION.get().americanSigns ? R.color.color_black : R.color.color_white));
}
}
}
}
AndroidUiHelper.updateVisibility(layout, visible);
return true;
}
public void setVisibility(boolean visibility) {
layout.setVisibility(visibility ? View.VISIBLE : View.GONE);
}
}
public static boolean distChanged(int oldDist, int dist){
if (oldDist != 0 && Math.abs(oldDist - dist) < 10) {
return false;
}
return true;
}
public static boolean degreesChanged(int oldDegrees, int degrees){
return Math.abs(oldDegrees - degrees) >= 1;
}
public AlarmWidget createAlarmInfoControl(OsmandApplication app, MapActivity map) {
return new AlarmWidget(app, map);
}
public RulerWidget createRulerControl(OsmandApplication app, MapActivity map) {
return new RulerWidget(app, map);
}
}