diff --git a/OsmAnd/res/drawable/warnings_speed_camera_dist.xml b/OsmAnd/res/drawable/warnings_speed_camera_dist.xml new file mode 100644 index 00000000000..538eb86c1b5 --- /dev/null +++ b/OsmAnd/res/drawable/warnings_speed_camera_dist.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + diff --git a/OsmAnd/res/drawable/warnings_speed_camera_dist_lim.xml b/OsmAnd/res/drawable/warnings_speed_camera_dist_lim.xml new file mode 100644 index 00000000000..ddf47415627 --- /dev/null +++ b/OsmAnd/res/drawable/warnings_speed_camera_dist_lim.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/drawable/warnings_speed_camera_dist_lim_us.xml b/OsmAnd/res/drawable/warnings_speed_camera_dist_lim_us.xml new file mode 100644 index 00000000000..d5abb8d80c7 --- /dev/null +++ b/OsmAnd/res/drawable/warnings_speed_camera_dist_lim_us.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + diff --git a/OsmAnd/res/drawable/warnings_speed_camera_dist_us.xml b/OsmAnd/res/drawable/warnings_speed_camera_dist_us.xml new file mode 100644 index 00000000000..d5e7086417e --- /dev/null +++ b/OsmAnd/res/drawable/warnings_speed_camera_dist_us.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/OsmAnd/res/layout-land/map_hud_bottom.xml b/OsmAnd/res/layout-land/map_hud_bottom.xml index e76b20c7ce5..e11b63a7a02 100644 --- a/OsmAnd/res/layout-land/map_hud_bottom.xml +++ b/OsmAnd/res/layout-land/map_hud_bottom.xml @@ -31,8 +31,8 @@ diff --git a/OsmAnd/res/layout/map_hud_bottom.xml b/OsmAnd/res/layout/map_hud_bottom.xml index cf2311d473a..368e02a6d80 100644 --- a/OsmAnd/res/layout/map_hud_bottom.xml +++ b/OsmAnd/res/layout/map_hud_bottom.xml @@ -23,8 +23,8 @@ diff --git a/OsmAnd/res/values-large/sizes.xml b/OsmAnd/res/values-large/sizes.xml index 64275349747..faa276ce2eb 100644 --- a/OsmAnd/res/values-large/sizes.xml +++ b/OsmAnd/res/values-large/sizes.xml @@ -23,13 +23,15 @@ 6dp 84dp 138dp - 12dp + 15dp 35sp 30dp 22sp 18sp 131dp 81dp + 54dp + 22sp 36dp 48dp diff --git a/OsmAnd/res/values/sizes.xml b/OsmAnd/res/values/sizes.xml index 4ff0f503942..af2378be663 100644 --- a/OsmAnd/res/values/sizes.xml +++ b/OsmAnd/res/values/sizes.xml @@ -123,7 +123,7 @@ 120dp 9dp 92dp - 8dp + 10dp 87dp @@ -157,6 +157,8 @@ 20dp 16sp 12sp + 36dp + 16sp 1sp 3sp 2dp diff --git a/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java b/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java index 4cf45bcfb41..24eda7fa18f 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/WaypointHelper.java @@ -225,9 +225,9 @@ public AlarmInfo getMostImportantAlarm(SpeedConstants sc, boolean showCameras) { Location lastProjection = app.getRoutingHelper().getLastProjection(); float mxspeed = route.getCurrentMaxSpeed(); float delta = app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f; - AlarmInfo speedAlarm = createSpeedAlarm(sc, mxspeed, lastProjection, delta); + AlarmInfo speedAlarm = createSpeedAlarm(mxspeed, lastProjection, delta); if (speedAlarm != null) { - getVoiceRouter().announceSpeedAlarm(speedAlarm.getIntValue(), lastProjection.getSpeed()); + getVoiceRouter().announceSpeedAlarm(speedAlarm.getMaxSpeed(sc), lastProjection.getSpeed()); } AlarmInfo mostImportant = speedAlarm; int value = speedAlarm != null ? speedAlarm.updateDistanceAndGetPriority(0, 0) : Integer.MAX_VALUE; @@ -252,6 +252,12 @@ public AlarmInfo getMostImportantAlarm(SpeedConstants sc, boolean showCameras) { if (!atd.isTurnStateActive(0, d, STATE_LONG_PNT_APPROACH)) { break; } + + // Set actual distance to speed camera + if (inf.getType() == AlarmInfoType.SPEED_CAMERA) { + inf.setFloatValue(d); + } + float time = speed > 0 ? d / speed : Integer.MAX_VALUE; int vl = inf.updateDistanceAndGetPriority(time, d); if (vl < value && (showCameras || inf.getType() != AlarmInfoType.SPEED_CAMERA)) { @@ -323,9 +329,9 @@ public AlarmInfo calculateMostImportantAlarm(RouteDataObject ro, Location loc, M SpeedConstants sc, boolean showCameras) { float mxspeed = ro.getMaximumSpeed(ro.bearingVsRouteDirection(loc)); float delta = app.getSettings().SPEED_LIMIT_EXCEED_KMH.get() / 3.6f; - AlarmInfo speedAlarm = createSpeedAlarm(sc, mxspeed, loc, delta); + AlarmInfo speedAlarm = createSpeedAlarm(mxspeed, loc, delta); if (speedAlarm != null) { - getVoiceRouter().announceSpeedAlarm(speedAlarm.getIntValue(), loc.getSpeed()); + getVoiceRouter().announceSpeedAlarm(speedAlarm.getMaxSpeed(sc), loc.getSpeed()); return speedAlarm; } for (int i = 0; i < ro.getPointsLength(); i++) { @@ -360,17 +366,11 @@ public AlarmInfo calculateMostImportantAlarm(RouteDataObject ro, Location loc, M return null; } - private static AlarmInfo createSpeedAlarm(SpeedConstants sc, float mxspeed, Location loc, float delta) { + private static AlarmInfo createSpeedAlarm(float mxspeed, Location loc, float delta) { AlarmInfo speedAlarm = null; if (mxspeed != 0 && loc != null && loc.hasSpeed() && mxspeed != RouteDataObject.NONE_MAX_SPEED) { if (loc.getSpeed() > mxspeed + delta) { - int speed; - if (sc.imperial) { - speed = Math.round(mxspeed * 3.6f / 1.6f); - } else { - speed = Math.round(mxspeed * 3.6f); - } - speedAlarm = AlarmInfo.createSpeedLimit(speed, loc); + speedAlarm = AlarmInfo.createSpeedLimit(mxspeed, loc); } } return speedAlarm; @@ -482,7 +482,15 @@ public void announceVisibleLocations() { } else if (type == ALARMS) { for (LocationPointWrapper pw : approachPoints) { AlarmInfo alarm = (AlarmInfo) pw.point; - voiceRouter.announceAlarm(new AlarmInfo(alarm.getType(), -1), lastKnownLocation.getSpeed()); + AlarmInfo alarmCopy = new AlarmInfo(alarm.getType(), -1); + + // Set actual distance and copy max speed to speed camera + if (alarmCopy.getType() == AlarmInfoType.SPEED_CAMERA) { + alarmCopy.setFloatValue(route.getDistanceToPoint(alarm.getLocationIndex())); + alarmCopy.setMaxSpeed(alarm.getMaxSpeed()); + } + + voiceRouter.announceAlarm(alarmCopy, lastKnownLocation.getSpeed()); lastAnnouncedAlarms.put(alarm.getType(), alarm); } } else if (type == FAVORITES) { diff --git a/OsmAnd/src/net/osmand/plus/plugins/development/TestVoiceActivity.java b/OsmAnd/src/net/osmand/plus/plugins/development/TestVoiceActivity.java index 36dd2616cf7..3ac2cd9c7a6 100644 --- a/OsmAnd/src/net/osmand/plus/plugins/development/TestVoiceActivity.java +++ b/OsmAnd/src/net/osmand/plus/plugins/development/TestVoiceActivity.java @@ -214,14 +214,15 @@ private void addButtons(final LinearLayout ll, CommandPlayer p) { addButton(ll, "Attention prompts:", builder(p)); addButton(ll, "\u25BA (9.1) You are exceeding the speed limit '50' (18 m/s)", builder(p).speedAlarm(50, 18f)); - addButton(ll, "\u25BA (9.2) Attention, speed camera", builder(p).attention("SPEED_CAMERA")); - addButton(ll, "\u25BA (9.3) Attention, border control", builder(p).attention("BORDER_CONTROL")); - addButton(ll, "\u25BA (9.4) Attention, railroad crossing", builder(p).attention("RAILWAY")); - addButton(ll, "\u25BA (9.5) Attention, traffic calming", builder(p).attention("TRAFFIC_CALMING")); - addButton(ll, "\u25BA (9.6) Attention, toll booth", builder(p).attention("TOLL_BOOTH")); - addButton(ll, "\u25BA (9.7) Attention, stop sign", builder(p).attention("STOP")); - addButton(ll, "\u25BA (9.8) Attention, pedestrian crosswalk", builder(p).attention("PEDESTRIAN")); - addButton(ll, "\u25BA (9.9) Attention, tunnel", builder(p).attention("TUNNEL")); + addButton(ll, "\u25BA (9.2) Attention, speed camera, distance 650m, speed limit '50' (18 m/s)", builder(p).speedCameraAlarm(650f, 50, "SPEED_CAMERA")); + addButton(ll, "\u25BA (9.3) Attention, speed camera", builder(p).attention("SPEED_CAMERA")); + addButton(ll, "\u25BA (9.4) Attention, border control", builder(p).attention("BORDER_CONTROL")); + addButton(ll, "\u25BA (9.5) Attention, railroad crossing", builder(p).attention("RAILWAY")); + addButton(ll, "\u25BA (9.6) Attention, traffic calming", builder(p).attention("TRAFFIC_CALMING")); + addButton(ll, "\u25BA (9.7) Attention, toll booth", builder(p).attention("TOLL_BOOTH")); + addButton(ll, "\u25BA (9.8) Attention, stop sign", builder(p).attention("STOP")); + addButton(ll, "\u25BA (9.9) Attention, pedestrian crosswalk", builder(p).attention("PEDESTRIAN")); + addButton(ll, "\u25BA (9.10) Attention, tunnel", builder(p).attention("TUNNEL")); addButton(ll, "Other prompts:", builder(p)); addButton(ll, "\u25BA (10.1) GPS signal lost", builder(p).gpsLocationLost()); diff --git a/OsmAnd/src/net/osmand/plus/routing/AlarmInfo.java b/OsmAnd/src/net/osmand/plus/routing/AlarmInfo.java index 5740edd1a4e..1fa1cf5a756 100644 --- a/OsmAnd/src/net/osmand/plus/routing/AlarmInfo.java +++ b/OsmAnd/src/net/osmand/plus/routing/AlarmInfo.java @@ -6,6 +6,7 @@ import net.osmand.data.LocationPoint; import net.osmand.data.PointDescription; import net.osmand.plus.R; +import net.osmand.plus.settings.enums.SpeedConstants; public class AlarmInfo implements LocationPoint { public enum AlarmInfoType { @@ -42,7 +43,7 @@ public String getVisualName(Context ctx) { private final AlarmInfoType type; protected final int locationIndex; private int lastLocationIndex = -1; - private int intValue; + private float maxSpeed; private float floatValue; private double latitude; private double longitude; @@ -64,7 +65,17 @@ public float getFloatValue() { public void setFloatValue(float floatValue) { this.floatValue = floatValue; } - + + public int getMaxSpeed(SpeedConstants sc) { + return sc.imperial + ? Math.round(getMaxSpeed() * 3.6f / 1.6f) + : Math.round(getMaxSpeed() * 3.6f); + } + + public float getMaxSpeed() { return maxSpeed; } + + public void setMaxSpeed(float maxSpeed) { this.maxSpeed = maxSpeed; } + @Override public double getLatitude() { return latitude; @@ -75,10 +86,6 @@ public double getLongitude() { return longitude; } - public int getIntValue() { - return intValue; - } - public int getLocationIndex() { return locationIndex; } @@ -91,14 +98,10 @@ public void setLastLocationIndex(int lastLocationIndex) { this.lastLocationIndex = lastLocationIndex; } - public void setIntValue(int intValue) { - this.intValue = intValue; - } - - public static AlarmInfo createSpeedLimit(int speed, Location loc){ + public static AlarmInfo createSpeedLimit(float maxSpeed, Location loc){ AlarmInfo info = new AlarmInfo(AlarmInfoType.SPEED_LIMIT, 0); info.setLatLon(loc.getLatitude(), loc.getLongitude()); - info.setIntValue(speed); + info.setMaxSpeed(maxSpeed); return info; } diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java index 14d036b0d94..9b1b455aa79 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteCalculationResult.java @@ -20,6 +20,7 @@ import net.osmand.plus.R; import net.osmand.plus.routing.AlarmInfo.AlarmInfoType; import net.osmand.plus.settings.backend.ApplicationMode; +import net.osmand.plus.settings.enums.SpeedConstants; import net.osmand.router.ExitInfo; import net.osmand.router.RouteSegmentResult; import net.osmand.router.RoutingContext; @@ -276,6 +277,8 @@ private static void attachAlarmInfo(List alarms, RouteSegmentResult r int[] pointTypes = res.getObject().getPointTypes(intId); if (pointTypes != null) { RouteRegion reg = res.getObject().region; + float maxSpeed = -1; + AlarmInfo speedCameraAlarmInfo = null; for (int r = 0; r < pointTypes.length; r++) { RouteTypeRule typeRule = reg.quickGetEncodingRule(pointTypes[r]); int x31 = res.getObject().getPoint31XTile(intId); @@ -284,9 +287,28 @@ private static void attachAlarmInfo(List alarms, RouteSegmentResult r loc.setLatitude(MapUtils.get31LatitudeY(y31)); loc.setLongitude(MapUtils.get31LongitudeX(x31)); AlarmInfo info = AlarmInfo.createAlarmInfo(typeRule, locInd, loc); + // For STOP first check if it has directional info if ((info != null) && !((info.getType() == AlarmInfoType.STOP) && !res.getObject().isStopApplicable(res.isForwardDirection(), intId, res.getStartPointIndex(), res.getEndPointIndex()))) { alarms.add(info); + + if (info.getType() == AlarmInfoType.SPEED_CAMERA) { + speedCameraAlarmInfo = info; + } + } + + if (maxSpeed <= 0 || maxSpeed == RouteDataObject.NONE_MAX_SPEED) { + maxSpeed = typeRule.maxSpeed(); + } + } + + if (speedCameraAlarmInfo != null) { + if (maxSpeed <= 0 || maxSpeed == RouteDataObject.NONE_MAX_SPEED) { + maxSpeed = res.getObject().getMaximumSpeed(res.isForwardDirection()); + } + + if (maxSpeed > 0 && maxSpeed != RouteDataObject.NONE_MAX_SPEED) { + speedCameraAlarmInfo.setMaxSpeed(maxSpeed); } } } diff --git a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java index 892a0bc5dc3..b2bf92be91b 100644 --- a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java +++ b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java @@ -319,17 +319,21 @@ protected String getText(Location location, List points, d public void announceAlarm(AlarmInfo info, float speed) { AlarmInfoType type = info.getType(); + OsmandSettings settings = router.getSettings(); + if (type == AlarmInfoType.SPEED_LIMIT) { - announceSpeedAlarm(info.getIntValue(), speed); + announceSpeedAlarm(info.getMaxSpeed(settings.SPEED_SYSTEM.get()), speed); + } else if (type == AlarmInfoType.SPEED_CAMERA) { + if (settings.SPEAK_SPEED_CAMERA.get()) { + announceSpeedCameraAlarm(info.getFloatValue(), info.getMaxSpeed(settings.SPEED_SYSTEM.get())); + } } else { - OsmandSettings settings = router.getSettings(); boolean speakTrafficWarnings = settings.SPEAK_TRAFFIC_WARNINGS.get(); boolean speakTunnels = type == AlarmInfoType.TUNNEL && settings.SPEAK_TUNNELS.get(); boolean speakPedestrian = type == AlarmInfoType.PEDESTRIAN && settings.SPEAK_PEDESTRIAN.get(); - boolean speakSpeedCamera = type == AlarmInfoType.SPEED_CAMERA && settings.SPEAK_SPEED_CAMERA.get(); - boolean speakPrefType = type == AlarmInfoType.TUNNEL || type == AlarmInfoType.PEDESTRIAN || type == AlarmInfoType.SPEED_CAMERA; + boolean speakPrefType = type == AlarmInfoType.TUNNEL || type == AlarmInfoType.PEDESTRIAN; - if (speakSpeedCamera || speakPedestrian || speakTunnels || speakTrafficWarnings && !speakPrefType) { + if (speakPedestrian || speakTunnels || speakTrafficWarnings && !speakPrefType) { CommandBuilder p = getNewCommandPlayerToPlay(); if (p != null) { p.attention(String.valueOf(type)); @@ -365,7 +369,19 @@ public void announceSpeedAlarm(int maxSpeed, float speed) { } } } - + + private void announceSpeedCameraAlarm(double dist, int maxSpeed) { + CommandBuilder p = getNewCommandPlayerToPlay(); + if (p != null) { + if (dist > 0 && maxSpeed > 0) { + p.speedCameraAlarm(dist, maxSpeed, String.valueOf(AlarmInfoType.SPEED_CAMERA)); + } else { + p.attention(String.valueOf(AlarmInfoType.SPEED_CAMERA)); + } + } + play(p); + } + private boolean isTargetPoint(NextDirectionInfo info) { boolean in = info != null && info.intermediatePoint; boolean target = info == null || info.directionInfo == null diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java index 1cac61d0bc3..214c93091c4 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/widgets/AlarmWidget.java @@ -10,7 +10,9 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.text.TextPaint; +import android.view.Gravity; import android.view.View; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -43,6 +45,8 @@ public class AlarmWidget { private static final float WIDGET_BITMAP_TEXT_AMERICAN_SPEED_LIMIT_SHIFT_DP = 12f; private static final float WIDGET_BITMAP_BOTTOM_TEXT_SIZE = 16f; private static final float WIDGET_BITMAP_BOTTOM_TEXT_SIZE_SMALL = 12f; + private static final float WIDGET_BITMAP_SPEED_CAMERA_SPEED_INFO_SIZE_DP = 36f; + private static final float WIDGET_BITMAP_SPEED_CAMERA_SPEED_INFO_TEXT_SIZE = 16f; @Nullable private final View layout; @@ -67,6 +71,7 @@ public class AlarmWidget { private String cachedText; private String cachedBottomText; private DrivingRegion cachedRegion; + private AlarmInfo.AlarmInfoType cachedAlarmType; public static class AlarmWidgetInfo { public AlarmInfo alarm; @@ -138,39 +143,18 @@ public boolean updateInfo(DrawSettings drawSettings, boolean drawBitmap) { icon.setImageResource(info.locImgId); } } - if (!Algorithms.objectEquals(info.text, cachedText) || cachedRegion != info.region) { + + if (!Algorithms.objectEquals(info.text, cachedText) || + !Algorithms.objectEquals(info.bottomText, cachedBottomText) || + cachedRegion != info.region || cachedAlarmType != alarm.getType()) { changed = true; cachedText = info.text; - cachedRegion = info.region; - if (layout != null && widgetText != null) { - widgetText.setText(cachedText); - Resources res = layout.getContext().getResources(); - if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && info.americanType && !info.isCanadianRegion) { - int topPadding = res.getDimensionPixelSize(R.dimen.map_alarm_text_top_padding); - widgetText.setPadding(0, topPadding, 0, 0); - } else { - widgetText.setPadding(0, 0, 0, 0); - } - } - } - if (!Algorithms.objectEquals(info.bottomText, cachedBottomText) || cachedRegion != info.region) { - changed = true; cachedBottomText = info.bottomText; cachedRegion = info.region; - if (layout != null && widgetBottomText != null) { - widgetBottomText.setText(cachedBottomText); - Resources res = layout.getContext().getResources(); - if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && info.isCanadianRegion) { - int bottomPadding = res.getDimensionPixelSize(R.dimen.map_button_margin); - widgetBottomText.setPadding(0, 0, 0, bottomPadding); - widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_si_text_size)); - } else { - widgetBottomText.setPadding(0, 0, 0, 0); - widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_text_size)); - } - widgetBottomText.setTextColor(ContextCompat.getColor(layout.getContext(), - info.americanType ? R.color.color_black : R.color.color_white)); - } + cachedAlarmType = alarm.getType(); + + updateTextWidget(info); + updateBottomTextWidget(info); } } } @@ -198,6 +182,64 @@ public boolean updateInfo(DrawSettings drawSettings, boolean drawBitmap) { return true; } + private void updateTextWidget(@NonNull AlarmWidgetInfo info) { + if (layout == null || widgetText == null) { + return; + } + + widgetText.setText(info.text); + Resources res = layout.getContext().getResources(); + + if (info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && info.americanType && !info.isCanadianRegion) { + int topPadding = res.getDimensionPixelSize(R.dimen.map_alarm_text_top_padding); + widgetText.setPadding(0, topPadding, 0, 0); + } else { + widgetText.setPadding(0, 0, 0, 0); + } + + if (info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA) { + FrameLayout.LayoutParams widgetTextLayoutParams = new FrameLayout.LayoutParams( + res.getDimensionPixelSize(R.dimen.map_alarm_speed_camera_speed_info_size), + res.getDimensionPixelSize(R.dimen.map_alarm_speed_camera_speed_info_size)); + + widgetTextLayoutParams.gravity = Gravity.RIGHT | Gravity.TOP; + + widgetText.setLayoutParams(widgetTextLayoutParams); + widgetText.setGravity(Gravity.CENTER); + widgetText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_speed_camera_speed_info_text_size)); + } else { + FrameLayout.LayoutParams widgetTextLayoutParams = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT); + + widgetTextLayoutParams.gravity = Gravity.CENTER; + + widgetText.setLayoutParams(widgetTextLayoutParams); + widgetText.setGravity(Gravity.NO_GRAVITY); + widgetText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_text_size)); + } + } + + private void updateBottomTextWidget(@NonNull AlarmWidgetInfo info) { + if (layout == null || widgetBottomText == null) { + return; + } + + widgetBottomText.setText(info.bottomText); + Resources res = layout.getContext().getResources(); + + if (info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && info.isCanadianRegion) { + int bottomPadding = res.getDimensionPixelSize(R.dimen.map_button_margin); + widgetBottomText.setPadding(0, 0, 0, bottomPadding); + widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_si_text_size)); + } else { + widgetBottomText.setPadding(0, 0, 0, 0); + widgetBottomText.setTextSize(COMPLEX_UNIT_PX, res.getDimensionPixelSize(R.dimen.map_alarm_bottom_text_size)); + } + widgetBottomText.setTextColor(ContextCompat.getColor(layout.getContext(), + info.americanType ? R.color.color_black : R.color.color_white)); + } + @NonNull private Bitmap createWidgetBitmap(@NonNull AlarmWidgetInfo info, float density) { Bitmap bitmap = Bitmap.createBitmap((int) (WIDGET_BITMAP_SIZE_DP * density), @@ -208,17 +250,28 @@ private Bitmap createWidgetBitmap(@NonNull AlarmWidgetInfo info, float density) locImg.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); locImg.draw(canvas); + boolean isSpeedLimit = info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT; + boolean isSpeedCamera = info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA; + if (!Algorithms.isEmpty(info.text)) { TextPaint textPaint = new TextPaint(); textPaint.setAntiAlias(true); textPaint.setColor(Color.BLACK); - textPaint.setTextSize(WIDGET_BITMAP_TEXT_SIZE * density); + textPaint.setTextSize((!isSpeedCamera ? WIDGET_BITMAP_TEXT_SIZE : WIDGET_BITMAP_SPEED_CAMERA_SPEED_INFO_TEXT_SIZE) * density); textPaint.setTextAlign(Paint.Align.CENTER); textPaint.setTypeface(Typeface.DEFAULT_BOLD); textPaint.setTextAlign(Paint.Align.CENTER); - float x = canvas.getWidth() / 2f; - float y = canvas.getHeight() / 2f - ((textPaint.descent() + textPaint.ascent()) / 2); - if (info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && info.americanType && !info.isCanadianRegion) { + + float x = !isSpeedCamera + ? canvas.getWidth() / 2f + : canvas.getWidth() - WIDGET_BITMAP_SPEED_CAMERA_SPEED_INFO_SIZE_DP * density / 2f; + + float y = (!isSpeedCamera + ? canvas.getHeight() / 2f + : WIDGET_BITMAP_SPEED_CAMERA_SPEED_INFO_SIZE_DP * density / 2f) - + ((textPaint.descent() + textPaint.ascent()) / 2); + + if (isSpeedLimit && info.americanType && !info.isCanadianRegion) { y += WIDGET_BITMAP_TEXT_AMERICAN_SPEED_LIMIT_SHIFT_DP * density; } canvas.drawText(info.text, x, y, textPaint); @@ -235,7 +288,7 @@ private Bitmap createWidgetBitmap(@NonNull AlarmWidgetInfo info, float density) textPaint.setTextAlign(Paint.Align.CENTER); float x = canvas.getWidth() / 2f; float y = canvas.getHeight() - (textPaint.descent() - textPaint.ascent()); - if (info.alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_LIMIT && info.isCanadianRegion) { + if (isSpeedLimit && info.isCanadianRegion) { textPaint.setTextSize(WIDGET_BITMAP_BOTTOM_TEXT_SIZE_SMALL * density); } canvas.drawText(info.bottomText, x, y, textPaint); @@ -263,9 +316,24 @@ public AlarmWidgetInfo createWidgetInfo(@NonNull AlarmInfo alarm) { locImgId = R.drawable.warnings_speed_limit_us; //else case is done by drawing red ring } - text = alarm.getIntValue() + ""; + text = alarm.getMaxSpeed(settings.SPEED_SYSTEM.get()) + ""; } else if (alarm.getType() == AlarmInfo.AlarmInfoType.SPEED_CAMERA) { - locImgId = R.drawable.warnings_speed_camera; + int maxSpeed = alarm.getMaxSpeed(settings.SPEED_SYSTEM.get()); + if (maxSpeed > 0) { + if (americanType) { + locImgId = R.drawable.warnings_speed_camera_dist_lim_us; + } else { + locImgId = R.drawable.warnings_speed_camera_dist_lim; + } + text = maxSpeed + ""; + } + else if (americanType) { + locImgId = R.drawable.warnings_speed_camera_dist_us; + } + else { + locImgId = R.drawable.warnings_speed_camera_dist; + } + bottomText = OsmAndFormatter.getFormattedAlarmInfoDistance(settings.getContext(), alarm.getFloatValue()); } else if (alarm.getType() == AlarmInfo.AlarmInfoType.BORDER_CONTROL) { locImgId = R.drawable.warnings_border_control; } else if (alarm.getType() == AlarmInfo.AlarmInfoType.HAZARD) { diff --git a/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java b/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java index 7750c2db880..dc2f33fe50a 100644 --- a/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java +++ b/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java @@ -30,6 +30,7 @@ public abstract class CommandBuilder { protected static final String C_REACHED_POI = "reached_poi"; protected static final String C_THEN = "then"; protected static final String C_SPEAD_ALARM = "speed_alarm"; + protected static final String C_SPEED_CAMERA_ALARM = "speed_camera_alarm"; protected static final String C_ATTENTION = "attention"; protected static final String C_OFF_ROUTE = "off_route"; protected static final String C_BACK_ON_ROUTE = "back_on_route"; @@ -69,6 +70,8 @@ public List getCommandsList() { public abstract CommandBuilder speedAlarm(int maxSpeed, float speed); + public abstract CommandBuilder speedCameraAlarm(double dist, int maxSpeed, String fallbackAttentionType); + public abstract CommandBuilder attention(String type); public abstract CommandBuilder offRoute(double dist); diff --git a/OsmAnd/src/net/osmand/plus/voice/JsCommandBuilder.java b/OsmAnd/src/net/osmand/plus/voice/JsCommandBuilder.java index 0e971cb64c1..02f08c35270 100644 --- a/OsmAnd/src/net/osmand/plus/voice/JsCommandBuilder.java +++ b/OsmAnd/src/net/osmand/plus/voice/JsCommandBuilder.java @@ -79,6 +79,13 @@ public CommandBuilder speedAlarm(int maxSpeed, float speed) { return addCommand(C_SPEAD_ALARM, maxSpeed, speed); } + @Override + public CommandBuilder speedCameraAlarm(double dist, int maxSpeed, String fallbackAttentionType) { + return isJsCommandExists(C_SPEED_CAMERA_ALARM) + ? addCommand(C_SPEED_CAMERA_ALARM, dist, maxSpeed) + : attention(fallbackAttentionType); + } + @Override public CommandBuilder attention(String type) { return addCommand(C_ATTENTION, type);