Implement dynamic view setup
This commit is contained in:
parent
62f877320d
commit
db09ed83f4
16 changed files with 1217 additions and 796 deletions
|
@ -14,7 +14,6 @@
|
|||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableLeft="@drawable/list_activities_poi"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/layer_poi"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
|
|
|
@ -9,6 +9,19 @@
|
|||
1. All your modified/created strings are in the top of the file (to make easier find what's translated).
|
||||
PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy
|
||||
-->
|
||||
<string name="map_widget_reset">Reset to default</string>
|
||||
<string name="map_widget_right_stack">Right side</string>
|
||||
<string name="map_widget_left_stack">Left side</string>
|
||||
<string name="map_widget_parking">Parking</string>
|
||||
<string name="map_widget_monitoring">Monitoring</string>
|
||||
<string name="map_widget_speed">Speed</string>
|
||||
<string name="map_widget_distance">Target</string>
|
||||
<string name="map_widget_altitude">Altitude</string>
|
||||
<string name="map_widget_time">Time to go</string>
|
||||
<string name="map_widget_next_turn">Next turn</string>
|
||||
<string name="map_widget_next_turn_small">Next turn (small)</string>
|
||||
<string name="map_widget_next_next_turn">Second next turn</string>
|
||||
<string name="map_widget_mini_route">Mini route map</string>
|
||||
<string name="bg_service_screen_lock">Lock/unlock screen</string>
|
||||
<string name="bg_service_screen_lock_toast">The screen is locked</string>
|
||||
<string name="bg_service_sleep_mode">Set sleep mode on/off</string>
|
||||
|
@ -39,8 +52,6 @@
|
|||
<string name="use_compass_navigation_descr">Use compass when direction is not detected</string>
|
||||
<string name="use_compass_navigation">Use compass</string>
|
||||
<string name="select_animate_speedup">Select animate route acceleration</string>
|
||||
<string name="monitoring_info_control">Show logging button</string>
|
||||
<string name="monitoring_info_control_desc">Display logging button on the map screen</string>
|
||||
|
||||
<string name="global_app_allocated_memory_descr">Allocated memory %1$s MB (Android limit %2$s MB, Dalvik %3$s MB).</string>
|
||||
<string name="global_app_allocated_memory">Allocated memory</string>
|
||||
|
@ -366,8 +377,6 @@ You can enable (online or cached) tile map sources, tracking settings, and many
|
|||
\n\t- Other small features
|
||||
</string>
|
||||
|
||||
<string name="show_altitude_info_descr">Show current altitude information on map</string>
|
||||
<string name="show_altitude_info">Show altitude</string>
|
||||
<string name="use_transparent_map_theme_descr">Use transparent map controls</string>
|
||||
<string name="use_transparent_map_theme">Transparent theme</string>
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
<ListPreference android:key="daynight_mode" android:title="@string/daynight" android:summary="@string/daynight_descr"></ListPreference>
|
||||
<CheckBoxPreference android:key="show_view_angle" android:title="@string/show_view_angle" android:summary="@string/show_view_angle_descr"></CheckBoxPreference>
|
||||
<CheckBoxPreference android:title="@string/auto_zoom_map" android:summary="@string/auto_zoom_map_descr" android:key="auto_zoom_map"></CheckBoxPreference>
|
||||
<CheckBoxPreference android:key="show_altitude_info" android:title="@string/show_altitude_info" android:summary="@string/show_altitude_info_descr"/>
|
||||
|
||||
<PreferenceCategory android:title="@string/pref_vector_map">
|
||||
<ListPreference android:key="renderer" android:title="@string/renderers" android:summary="@string/renderers_descr"></ListPreference>
|
||||
|
|
|
@ -59,6 +59,8 @@ public class OsmandSettings {
|
|||
|
||||
boolean set(T obj);
|
||||
|
||||
T getModeValue(ApplicationMode m);
|
||||
|
||||
String getId();
|
||||
}
|
||||
|
||||
|
@ -130,6 +132,11 @@ public class OsmandSettings {
|
|||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationMode getModeValue(ApplicationMode m) {
|
||||
return m;
|
||||
}
|
||||
};
|
||||
|
||||
public ApplicationMode getApplicationMode(){
|
||||
|
@ -260,6 +267,18 @@ public class OsmandSettings {
|
|||
|
||||
protected abstract boolean setValue(SharedPreferences prefs, T val);
|
||||
|
||||
@Override
|
||||
public T getModeValue(ApplicationMode mode) {
|
||||
if(global) {
|
||||
return get();
|
||||
}
|
||||
T defaultV = defaultValue;
|
||||
if(defaultValues != null && defaultValues.containsKey(currentMode)){
|
||||
defaultV = defaultValues.get(currentMode);
|
||||
}
|
||||
return getValue(getProfilePreferences(mode), defaultV);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
if(cache && cachedValue != null && cachedPreference == getPreferences()){
|
||||
|
@ -587,17 +606,12 @@ public class OsmandSettings {
|
|||
public final CommonPreference<String> LIVE_MONITORING_URL = new StringPreference("live_monitoring_url",
|
||||
"http://example.com?lat={0}&lon={1}×tamp={2}&hdop={3}&altitude={4}&speed={5}").makeGlobal();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final CommonPreference<Boolean> SHOW_MONITORING_CONTROL = new BooleanPreference("show_monitoring_control", false).makeProfile().cache();
|
||||
{
|
||||
SHOW_MONITORING_CONTROL.setModeDefaultValue(ApplicationMode.BICYCLE, true);
|
||||
SHOW_MONITORING_CONTROL.setModeDefaultValue(ApplicationMode.CAR, false);
|
||||
SHOW_MONITORING_CONTROL.setModeDefaultValue(ApplicationMode.PEDESTRIAN, true);
|
||||
}
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final OsmandPreference<Boolean> SHOW_OSM_BUGS = new BooleanPreference("show_osm_bugs", false).makeGlobal();
|
||||
|
||||
public final OsmandPreference<String> MAP_INFO_CONTROLS = new StringPreference("map_info_controls", "").makeProfile();
|
||||
|
||||
// this value string is synchronized with settings_pref.xml preference name
|
||||
public final OsmandPreference<Boolean> DEBUG_RENDERING_INFO = new BooleanPreference("debug_rendering", false).makeGlobal();
|
||||
|
||||
|
@ -1261,13 +1275,6 @@ public class OsmandSettings {
|
|||
public final CommonPreference<Boolean> FLUORESCENT_OVERLAYS =
|
||||
new BooleanPreference("fluorescent_overlays", false).makeGlobal().cache();
|
||||
|
||||
public final CommonPreference<Boolean> SHOW_ALTITUDE_INFO =
|
||||
new BooleanPreference("show_altitude_info", false).makeProfile().cache();
|
||||
{
|
||||
SHOW_ALTITUDE_INFO.setModeDefaultValue(ApplicationMode.CAR, false);
|
||||
SHOW_ALTITUDE_INFO.setModeDefaultValue(ApplicationMode.BICYCLE, true);
|
||||
SHOW_ALTITUDE_INFO.setModeDefaultValue(ApplicationMode.PEDESTRIAN, true);
|
||||
}
|
||||
|
||||
public final CommonPreference<Boolean> SHOW_RULER =
|
||||
new BooleanPreference("show_ruler", true).makeProfile().cache();
|
||||
|
|
|
@ -426,7 +426,7 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe
|
|||
|
||||
}
|
||||
|
||||
OsmandApplication getMyApplication() {
|
||||
public OsmandApplication getMyApplication() {
|
||||
return ((OsmandApplication) getApplication());
|
||||
}
|
||||
|
||||
|
|
|
@ -989,15 +989,10 @@ public class MapActivityActions implements DialogProvider {
|
|||
} else {
|
||||
AlertDialog.Builder builder = new AccessibleAlertBuilder(mapActivity);
|
||||
builder.setMessage(getString(R.string.gps_status_app_not_found));
|
||||
builder.setPositiveButton(
|
||||
getString(R.string.default_buttons_yes),
|
||||
new DialogInterface.OnClickListener() {
|
||||
builder.setPositiveButton(getString(R.string.default_buttons_yes), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse("market://search?q=pname:"
|
||||
+ GPS_STATUS_COMPONENT));
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:" + GPS_STATUS_COMPONENT));
|
||||
try {
|
||||
mapActivity.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
|
|
|
@ -269,7 +269,6 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
registerBooleanPreference(osmandSettings.SHOW_SPEED_LIMITS, screen);
|
||||
registerBooleanPreference(osmandSettings.AVOID_TOLL_ROADS, screen);
|
||||
|
||||
registerBooleanPreference(osmandSettings.SHOW_ALTITUDE_INFO, screen);
|
||||
|
||||
CheckBoxPreference nativeCheckbox = registerBooleanPreference(osmandSettings.NATIVE_RENDERING,screen);
|
||||
//disable the checkbox if the library cannot be used
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.osmand.plus.monitoring;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.OsmAndFormatter;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
|
@ -9,6 +11,7 @@ import net.osmand.plus.OsmandPlugin;
|
|||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.ProgressDialogImplementation;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.ApplicationMode;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.activities.SavingTrackHelper;
|
||||
import net.osmand.plus.activities.SettingsActivity;
|
||||
|
@ -21,11 +24,8 @@ import org.apache.commons.logging.Log;
|
|||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceCategory;
|
||||
|
@ -66,15 +66,19 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
|||
|
||||
@Override
|
||||
public void registerLayers(MapActivity activity) {
|
||||
monitoringControl = createMonitoringControl(activity);
|
||||
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
|
||||
layer.addRightStack(monitoringControl);
|
||||
monitoringControl = createMonitoringControl(activity, layer.getPaintText(), layer.getPaintSubText());
|
||||
|
||||
layer.getMapInfoControls().registerSideWidget(monitoringControl,
|
||||
R.drawable.monitoring_rec_small, R.string.map_widget_monitoring, "monitoring", false,
|
||||
EnumSet.of(ApplicationMode.BICYCLE, ApplicationMode.PEDESTRIAN), EnumSet.noneOf(ApplicationMode.class), 18);
|
||||
layer.recreateControls();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLayers(OsmandMapTileView mapView, MapActivity activity) {
|
||||
if(monitoringControl != null) {
|
||||
monitoringControl.updateInfo();
|
||||
if(monitoringControl == null) {
|
||||
registerLayers(activity);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,10 +137,6 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
|||
});
|
||||
cat.addPreference(pref);
|
||||
|
||||
CheckBoxPreference infoControlPreference = activity.createCheckBoxPreference(settings.SHOW_MONITORING_CONTROL,
|
||||
R.string.monitoring_info_control, R.string.monitoring_info_control_desc);
|
||||
cat.addPreference(infoControlPreference);
|
||||
|
||||
cat = new PreferenceCategory(activity);
|
||||
cat.setTitle(R.string.live_monitoring);
|
||||
grp.addPreference(cat);
|
||||
|
@ -174,18 +174,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
|||
/**
|
||||
* creates (if it wasn't created previously) the control to be added on a MapInfoLayer that shows a monitoring state (recorded/stopped)
|
||||
*/
|
||||
private MapInfoControl createMonitoringControl(final MapActivity map) {
|
||||
Paint paintText = new Paint();
|
||||
paintText.setStyle(Style.FILL_AND_STROKE);
|
||||
paintText.setColor(Color.BLACK);
|
||||
paintText.setTextSize(23 * MapInfoLayer.scaleCoefficient);
|
||||
paintText.setAntiAlias(true);
|
||||
paintText.setStrokeWidth(4);
|
||||
Paint paintSubText = new Paint();
|
||||
paintSubText.setStyle(Style.FILL_AND_STROKE);
|
||||
paintSubText.setColor(Color.BLACK);
|
||||
paintSubText.setTextSize(15 * MapInfoLayer.scaleCoefficient);
|
||||
paintSubText.setAntiAlias(true);
|
||||
private MapInfoControl createMonitoringControl(final MapActivity map, Paint paintText, Paint paintSubText) {
|
||||
final Drawable monitoringBig = map.getResources().getDrawable(R.drawable.monitoring_rec_big);
|
||||
final Drawable monitoringSmall = map.getResources().getDrawable(R.drawable.monitoring_rec_small);
|
||||
final Drawable monitoringInactive = map.getResources().getDrawable(R.drawable.monitoring_rec_inactive);
|
||||
|
@ -193,9 +182,7 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
|||
long lastUpdateTime;
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
if (settings.SHOW_MONITORING_CONTROL.get()) {
|
||||
visible = true;
|
||||
boolean visible = true;
|
||||
String txt = "start";
|
||||
String subtxt = null;
|
||||
Drawable d = monitoringInactive;
|
||||
|
@ -219,7 +206,6 @@ public class OsmandMonitoringPlugin extends OsmandPlugin {
|
|||
lastUpdateTime = last;
|
||||
blink();
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,33 +3,25 @@ package net.osmand.plus.parkingpoint;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.OsmAndFormatter;
|
||||
import net.osmand.access.AccessibleToast;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.views.AnimateDraggingMapThread;
|
||||
import net.osmand.plus.views.ContextMenuLayer;
|
||||
import net.osmand.plus.views.MapInfoLayer;
|
||||
import net.osmand.plus.views.OsmandMapLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.TextInfoControl;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.location.Location;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.format.Time;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -54,20 +46,20 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
|
|||
private OsmandSettings settings;
|
||||
|
||||
private Paint bitmapPaint;
|
||||
private Paint paintText;
|
||||
private Paint paintSubText;
|
||||
|
||||
private Bitmap parkingNoLimitIcon;
|
||||
private Bitmap parkingLimitIcon;
|
||||
|
||||
private TextInfoControl parkingPlaceControl;
|
||||
|
||||
private boolean timeLimit;
|
||||
|
||||
public ParkingPositionLayer(MapActivity map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public LatLon getParkingPoint() {
|
||||
return parkingPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLayer(OsmandMapTileView view) {
|
||||
this.view = view;
|
||||
|
@ -77,19 +69,6 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
|
|||
WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wmgr.getDefaultDisplay().getMetrics(dm);
|
||||
|
||||
paintText = new Paint();
|
||||
paintText.setStyle(Style.FILL_AND_STROKE);
|
||||
paintText.setColor(Color.BLACK);
|
||||
paintText.setTextSize(23 * MapInfoLayer.scaleCoefficient);
|
||||
paintText.setAntiAlias(true);
|
||||
paintText.setStrokeWidth(4);
|
||||
|
||||
paintSubText = new Paint();
|
||||
paintSubText.setStyle(Style.FILL_AND_STROKE);
|
||||
paintSubText.setColor(Color.BLACK);
|
||||
paintSubText.setTextSize(15 * MapInfoLayer.scaleCoefficient);
|
||||
paintSubText.setAntiAlias(true);
|
||||
|
||||
bitmapPaint = new Paint();
|
||||
bitmapPaint.setDither(true);
|
||||
bitmapPaint.setAntiAlias(true);
|
||||
|
@ -97,10 +76,6 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
|
|||
parkingNoLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.poi_parking_pos_no_limit);
|
||||
parkingLimitIcon = BitmapFactory.decodeResource(view.getResources(), R.drawable.poi_parking_pos_limit);
|
||||
|
||||
|
||||
MapInfoLayer mapInfoLayer = map.getMapLayers().getMapInfoLayer();
|
||||
if ((mapInfoLayer != null) && (parkingPlaceControl == null))
|
||||
mapInfoLayer.addRightStack(createParkingPlaceInfoControl());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,76 +222,6 @@ public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuL
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the control to be added on a MapInfoLayer
|
||||
* that shows a distance between
|
||||
* the current position on the map
|
||||
* and the location of the parked car
|
||||
*/
|
||||
private TextInfoControl createParkingPlaceInfoControl() {
|
||||
parkingPlaceControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private float[] calculations = new float[1];
|
||||
private int cachedMeters = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
if( parkingPoint != null && !map.getRoutingHelper().isFollowingMode()) {
|
||||
int d = 0;
|
||||
if (d == 0) {
|
||||
Location.distanceBetween(view.getLatitude(), view.getLongitude(), parkingPoint.getLatitude(), parkingPoint.getLongitude(), calculations);
|
||||
d = (int) calculations[0];
|
||||
}
|
||||
if (distChanged(cachedMeters, d)) {
|
||||
cachedMeters = d;
|
||||
if (cachedMeters <= 20) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
} else {
|
||||
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, map);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
setText(ds, null);
|
||||
} else {
|
||||
setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (cachedMeters != 0) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method.
|
||||
* @param oldDist
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
private boolean distChanged(int oldDist, int dist){
|
||||
if(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist)/oldDist) < 0.01){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
parkingPlaceControl.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
|
||||
LatLon parkingPoint = view.getSettings().getParkingPosition();
|
||||
if (parkingPoint != null) {
|
||||
float fZoom = view.getFloatZoom() < 15 ? 15 : view.getFloatZoom();
|
||||
thread.startMoving(parkingPoint.getLatitude(), parkingPoint.getLongitude(), fZoom, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
parkingPlaceControl.setText(null, null);
|
||||
parkingPlaceControl.setImageDrawable(view.getResources().getDrawable(R.drawable.poi_parking_pos_info));
|
||||
return parkingPlaceControl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package net.osmand.plus.parkingpoint;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.osmand.OsmAndFormatter;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.plus.ContextMenuAdapter;
|
||||
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
|
||||
|
@ -10,13 +12,20 @@ import net.osmand.plus.OsmandApplication;
|
|||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.ApplicationMode;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.views.AnimateDraggingMapThread;
|
||||
import net.osmand.plus.views.MapInfoControl;
|
||||
import net.osmand.plus.views.MapInfoLayer;
|
||||
import net.osmand.plus.views.OsmandMapTileView;
|
||||
import net.osmand.plus.views.TextInfoControl;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Paint;
|
||||
import android.location.Location;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
@ -39,6 +48,7 @@ public class ParkingPositionPlugin extends OsmandPlugin {
|
|||
|
||||
private ParkingPositionLayer parkingLayer;
|
||||
private OsmandSettings settings;
|
||||
private MapInfoControl parkingPlaceControl;
|
||||
|
||||
public ParkingPositionPlugin(OsmandApplication app) {
|
||||
this.app = app;
|
||||
|
@ -67,19 +77,36 @@ public class ParkingPositionPlugin extends OsmandPlugin {
|
|||
|
||||
@Override
|
||||
public void registerLayers(MapActivity activity) {
|
||||
if(parkingLayer == null) {
|
||||
parkingLayer = new ParkingPositionLayer(activity);
|
||||
}
|
||||
registerWidget(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLayers(OsmandMapTileView mapView, MapActivity activity) {
|
||||
if ((settings.getParkingPosition() == null)
|
||||
&& (mapView.getLayers().contains(parkingLayer))) {
|
||||
if ((settings.getParkingPosition() == null) && (mapView.getLayers().contains(parkingLayer))) {
|
||||
mapView.removeLayer(parkingLayer);
|
||||
} else {
|
||||
if (parkingLayer == null)
|
||||
if (parkingLayer == null) {
|
||||
registerLayers(activity);
|
||||
}
|
||||
mapView.addLayer(parkingLayer, 5);
|
||||
}
|
||||
if(parkingPlaceControl == null){
|
||||
registerWidget(activity);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerWidget(MapActivity activity) {
|
||||
MapInfoLayer mapInfoLayer = activity.getMapLayers().getMapInfoLayer();
|
||||
if (mapInfoLayer != null) {
|
||||
parkingPlaceControl = createParkingPlaceInfoControl(activity, mapInfoLayer.getPaintText(), mapInfoLayer.getPaintSubText());
|
||||
mapInfoLayer.getMapInfoControls().registerSideWidget(parkingPlaceControl,
|
||||
R.drawable.poi_parking_pos_info, R.string.map_widget_parking, "parking", false,
|
||||
EnumSet.allOf(ApplicationMode.class), EnumSet.noneOf(ApplicationMode.class), 8);
|
||||
mapInfoLayer.recreateControls();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -333,4 +360,79 @@ public class ParkingPositionPlugin extends OsmandPlugin {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the control to be added on a MapInfoLayer
|
||||
* that shows a distance between
|
||||
* the current position on the map
|
||||
* and the location of the parked car
|
||||
*/
|
||||
private TextInfoControl createParkingPlaceInfoControl(final MapActivity map, Paint paintText, Paint paintSubText) {
|
||||
TextInfoControl parkingPlaceControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private float[] calculations = new float[1];
|
||||
private int cachedMeters = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
LatLon parkingPoint = parkingLayer.getParkingPoint();
|
||||
if( parkingPoint != null && !map.getRoutingHelper().isFollowingMode()) {
|
||||
OsmandMapTileView view = map.getMapView();
|
||||
int d = 0;
|
||||
if (d == 0) {
|
||||
Location.distanceBetween(view.getLatitude(), view.getLongitude(), parkingPoint.getLatitude(), parkingPoint.getLongitude(), calculations);
|
||||
d = (int) calculations[0];
|
||||
}
|
||||
if (distChanged(cachedMeters, d)) {
|
||||
cachedMeters = d;
|
||||
if (cachedMeters <= 20) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
} else {
|
||||
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, map);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
setText(ds, null);
|
||||
} else {
|
||||
setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (cachedMeters != 0) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method.
|
||||
* @param oldDist
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
private boolean distChanged(int oldDist, int dist){
|
||||
if(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist)/oldDist) < 0.01){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
parkingPlaceControl.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
OsmandMapTileView view = map.getMapView();
|
||||
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
|
||||
LatLon parkingPoint = view.getSettings().getParkingPosition();
|
||||
if (parkingPoint != null) {
|
||||
float fZoom = view.getFloatZoom() < 15 ? 15 : view.getFloatZoom();
|
||||
thread.startMoving(parkingPoint.getLatitude(), parkingPoint.getLongitude(), fZoom, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
parkingPlaceControl.setText(null, null);
|
||||
parkingPlaceControl.setImageDrawable(map.getResources().getDrawable(R.drawable.poi_parking_pos_info));
|
||||
return parkingPlaceControl;
|
||||
}
|
||||
}
|
||||
|
|
224
OsmAnd/src/net/osmand/plus/views/MapInfoControls.java
Normal file
224
OsmAnd/src/net/osmand/plus/views/MapInfoControls.java
Normal file
|
@ -0,0 +1,224 @@
|
|||
package net.osmand.plus.views;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.activities.ApplicationMode;
|
||||
import android.graphics.Paint;
|
||||
|
||||
public class MapInfoControls {
|
||||
|
||||
private Set<MapInfoControlRegInfo> left = new TreeSet<MapInfoControls.MapInfoControlRegInfo>();
|
||||
private Set<MapInfoControlRegInfo> right = new TreeSet<MapInfoControls.MapInfoControlRegInfo>();
|
||||
private Map<ApplicationMode, Set<String>> visibleElements = new LinkedHashMap<ApplicationMode, Set<String>>();
|
||||
private final OsmandSettings settings;
|
||||
|
||||
|
||||
public interface MapInfoControlFactoryMethod {
|
||||
|
||||
/**
|
||||
* @param mapView
|
||||
* @param paints array of paints (4) 0 - normal, 1 - subtext, 2 - small, 3 - small subtext
|
||||
*/
|
||||
public MapInfoControl createControl(OsmandMapTileView mapView, Paint[] paints);
|
||||
}
|
||||
|
||||
public MapInfoControls(OsmandSettings settings) {
|
||||
this.settings = settings;
|
||||
|
||||
for(ApplicationMode ms : ApplicationMode.values() ) {
|
||||
String mpf = settings.MAP_INFO_CONTROLS.getModeValue(ms);
|
||||
if(mpf.equals("")) {
|
||||
visibleElements.put(ms, null);
|
||||
} else {
|
||||
LinkedHashSet<String> set = new LinkedHashSet<String>();
|
||||
visibleElements.put(ms, set);
|
||||
for(String s : mpf.split(";")){
|
||||
set.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void registerSideWidget(MapInfoControl m, int drawable, int messageId, String key, boolean left,
|
||||
EnumSet<ApplicationMode> appDefaultModes, EnumSet<ApplicationMode> defaultCollapsible, int priorityOrder) {
|
||||
MapInfoControlRegInfo ii = new MapInfoControlRegInfo();
|
||||
ii.defaultModes = appDefaultModes.clone();
|
||||
ii.defaultCollapsible = defaultCollapsible.clone();
|
||||
ii.key = key;
|
||||
ii.visibleModes = EnumSet.noneOf(ApplicationMode.class);
|
||||
ii.visibleCollapsible = EnumSet.noneOf(ApplicationMode.class);
|
||||
for(ApplicationMode ms : ApplicationMode.values() ) {
|
||||
boolean collapse = defaultCollapsible.contains(ms);;
|
||||
boolean def = appDefaultModes.contains(ms);
|
||||
Set<String> set = visibleElements.get(ms);
|
||||
if(set != null) {
|
||||
def = set.contains(key);
|
||||
collapse = set.contains("+"+key);
|
||||
}
|
||||
if(def){
|
||||
ii.visibleModes.add(ms);
|
||||
} else if(collapse) {
|
||||
ii.visibleCollapsible.add(ms);
|
||||
}
|
||||
}
|
||||
ii.drawable = drawable;
|
||||
ii.messageId = messageId;
|
||||
ii.m = m;
|
||||
ii.priorityOrder = priorityOrder;
|
||||
if(left) {
|
||||
this.left.add(ii);
|
||||
} else {
|
||||
this.right.add(ii);
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreModes(Set<String> set, Set<MapInfoControlRegInfo> mi, ApplicationMode mode) {
|
||||
for(MapInfoControlRegInfo m : mi){
|
||||
if(m.visibleModes.contains(mode)) {
|
||||
set.add(m.key) ;
|
||||
} else if(m.visibleCollapsible.contains(mode)) {
|
||||
set.add("+"+m.key) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void changeVisibility(MapInfoControlRegInfo m, boolean visible, boolean collapse) {
|
||||
ApplicationMode mode = settings.APPLICATION_MODE.get();
|
||||
if(this.visibleElements.get(mode) == null){
|
||||
LinkedHashSet<String> set = new LinkedHashSet<String>();
|
||||
restoreModes(set, left, mode);
|
||||
restoreModes(set, right, mode);
|
||||
this.visibleElements.put(mode, set);
|
||||
}
|
||||
this.visibleElements.get(mode).remove(m.key);
|
||||
this.visibleElements.get(mode).remove("+" + m.key);
|
||||
m.visibleModes.remove(mode);
|
||||
m.visibleCollapsible.remove(mode);
|
||||
if(visible) {
|
||||
if(collapse) {
|
||||
m.visibleCollapsible.add(mode);
|
||||
this.visibleElements.get(mode).add("+" + m.key);
|
||||
} else {
|
||||
m.visibleModes.add(mode);
|
||||
this.visibleElements.get(mode).add(m.key);
|
||||
|
||||
}
|
||||
}
|
||||
StringBuilder bs = new StringBuilder();
|
||||
for(String ks : this.visibleElements.get(mode)){
|
||||
bs.append(ks).append(";");
|
||||
}
|
||||
settings.MAP_INFO_CONTROLS.set(bs.toString());
|
||||
}
|
||||
|
||||
public Set<MapInfoControlRegInfo> getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public Set<MapInfoControlRegInfo> getRight() {
|
||||
return right;
|
||||
}
|
||||
|
||||
public void registerTopBarButton(MapInfoControlFactoryMethod m, int drawable, int messageId, boolean left,
|
||||
EnumSet<ApplicationMode> appModes, int priorityOrder) {
|
||||
|
||||
}
|
||||
|
||||
public void populateStackControl(MapStackControl stack, OsmandMapTileView v, boolean left){
|
||||
ApplicationMode appMode = settings.getApplicationMode();
|
||||
Set<MapInfoControlRegInfo> st = left ? this.left : this.right;
|
||||
for (MapInfoControlRegInfo r : st) {
|
||||
if (r.visibleCollapsible.contains(appMode)) {
|
||||
stack.addCollapsedView(r.m);
|
||||
} else if (r.visibleModes.contains(appMode)) {
|
||||
stack.addStackView(r.m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetDefault(ApplicationMode mode, Set<MapInfoControlRegInfo> set ){
|
||||
for(MapInfoControlRegInfo ri : set) {
|
||||
ri.visibleCollapsible.remove(mode);
|
||||
ri.visibleModes.remove(mode);
|
||||
if(ri.defaultCollapsible.contains(mode)) {
|
||||
ri.visibleCollapsible.add(mode);
|
||||
}
|
||||
if(ri.defaultModes.contains(mode)) {
|
||||
ri.visibleModes.add(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resetToDefault() {
|
||||
ApplicationMode appMode = settings.getApplicationMode();
|
||||
resetDefault(appMode, left);
|
||||
resetDefault(appMode, right);
|
||||
this.visibleElements.put(appMode, null);
|
||||
settings.MAP_INFO_CONTROLS.set("");
|
||||
}
|
||||
|
||||
public static boolean distChanged(int oldDist, int dist){
|
||||
if(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist)/oldDist) < 0.01){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class MapInfoControlRegInfo implements Comparable<MapInfoControlRegInfo> {
|
||||
public MapInfoControl m;
|
||||
public int drawable;
|
||||
public int messageId;
|
||||
private String key;
|
||||
private EnumSet<ApplicationMode> defaultModes;
|
||||
private EnumSet<ApplicationMode> defaultCollapsible;
|
||||
private EnumSet<ApplicationMode> visibleModes;
|
||||
private EnumSet<ApplicationMode> visibleCollapsible;
|
||||
public int priorityOrder;
|
||||
|
||||
public boolean visibleCollapsed(ApplicationMode mode){
|
||||
return visibleCollapsible.contains(mode);
|
||||
}
|
||||
|
||||
public boolean visible(ApplicationMode mode){
|
||||
return visibleModes.contains(mode);
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return messageId;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
MapInfoControlRegInfo other = (MapInfoControlRegInfo) obj;
|
||||
if (messageId != other.messageId)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int compareTo(MapInfoControlRegInfo another) {
|
||||
if (messageId == another.messageId) {
|
||||
return 0;
|
||||
}
|
||||
if(priorityOrder == another.priorityOrder) {
|
||||
return messageId - another.messageId;
|
||||
}
|
||||
return priorityOrder - another.priorityOrder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +1,32 @@
|
|||
package net.osmand.plus.views;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.OsmAndFormatter;
|
||||
import net.osmand.osm.LatLon;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.ApplicationMode;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.background.OsmandBackgroundServicePlugin;
|
||||
import net.osmand.plus.routing.AlarmInfo;
|
||||
import net.osmand.plus.routing.RouteDirectionInfo;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.router.TurnType;
|
||||
import net.osmand.plus.views.MapInfoControls.MapInfoControlRegInfo;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.Location;
|
||||
import android.text.TextPaint;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
|
@ -37,10 +34,15 @@ import android.view.View;
|
|||
import android.view.View.MeasureSpec;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.LinearLayout.LayoutParams;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MapInfoLayer extends OsmandMapLayer {
|
||||
|
@ -58,11 +60,9 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
private Paint paintImg;
|
||||
|
||||
private float cachedRotate = 0;
|
||||
private boolean showArrivalTime = true;
|
||||
private boolean showAltitude = false;
|
||||
|
||||
// layout pseudo-constants
|
||||
private int STATUS_BAR_MARGIN_X = 4;
|
||||
private int STATUS_BAR_MARGIN_X = -4;
|
||||
|
||||
private ImageView backToLocation;
|
||||
private ImageView compassView;
|
||||
|
@ -76,15 +76,13 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
private MapInfoControl alarmControl;
|
||||
private TextView topText;
|
||||
|
||||
private MapInfoControls mapInfoControls;
|
||||
|
||||
public MapInfoLayer(MapActivity map, RouteLayer layer){
|
||||
this.map = map;
|
||||
this.routeLayer = layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLayer(final OsmandMapTileView view) {
|
||||
this.view = view;
|
||||
WindowManager mgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
WindowManager mgr = (WindowManager) map.getSystemService(Context.WINDOW_SERVICE);
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
mgr.getDefaultDisplay().getMetrics(dm);
|
||||
scaleCoefficient = dm.density;
|
||||
|
@ -124,8 +122,37 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
paintImg.setFilterBitmap(true);
|
||||
paintImg.setAntiAlias(true);
|
||||
|
||||
createTopBarElements();
|
||||
|
||||
mapInfoControls = new MapInfoControls(map.getMyApplication().getSettings());
|
||||
}
|
||||
|
||||
|
||||
public Paint getPaintSmallSubText() {
|
||||
return paintSmallSubText;
|
||||
}
|
||||
|
||||
public Paint getPaintText() {
|
||||
return paintText;
|
||||
}
|
||||
|
||||
public Paint getPaintSmallText() {
|
||||
return paintSmallText;
|
||||
}
|
||||
|
||||
public Paint getPaintSubText() {
|
||||
return paintSubText;
|
||||
}
|
||||
|
||||
public MapInfoControls getMapInfoControls() {
|
||||
return mapInfoControls;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initLayer(final OsmandMapTileView view) {
|
||||
this.view = view;
|
||||
|
||||
registerAllControls();
|
||||
createControls();
|
||||
applyTheme();
|
||||
}
|
||||
|
||||
|
@ -149,29 +176,59 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
leftStack.setExpandImageDrawable(view.getResources().getDrawable(expand));
|
||||
rightStack.setExpandImageDrawable(view.getResources().getDrawable(expand));
|
||||
statusBar.setBackgroundDrawable(view.getResources().getDrawable(boxTop));
|
||||
showAltitude = view.getSettings().SHOW_ALTITUDE_INFO.get();
|
||||
}
|
||||
|
||||
public void createTopBarElements() {
|
||||
// 1. Create view groups and controls
|
||||
public void registerAllControls(){
|
||||
statusBar = createStatusBar();
|
||||
statusBar.setBackgroundDrawable(view.getResources().getDrawable(R.drawable.box_top));
|
||||
|
||||
lanesControl = createLanesControl();
|
||||
RouteInfoControls ric = new RouteInfoControls(scaleCoefficient);
|
||||
lanesControl = ric.createLanesControl(view.getApplication().getRoutingHelper(), view);
|
||||
lanesControl.setBackgroundDrawable(view.getResources().getDrawable(R.drawable.box_free));
|
||||
|
||||
alarmControl = createAlarmInfoControl();
|
||||
alarmControl = ric.createAlarmInfoControl(view.getApplication().getRoutingHelper(),
|
||||
view.getContext(), view.getSettings());
|
||||
// register right stack
|
||||
EnumSet<ApplicationMode> all = EnumSet.allOf(ApplicationMode.class);
|
||||
EnumSet<ApplicationMode> bicyclePedestrian = EnumSet.of(ApplicationMode.BICYCLE, ApplicationMode.PEDESTRIAN);
|
||||
EnumSet<ApplicationMode> none = EnumSet.noneOf(ApplicationMode.class);
|
||||
RoutingHelper routingHelper = view.getApplication().getRoutingHelper();
|
||||
NextTurnInfoControl bigInfoControl = ric.createNextInfoControl(routingHelper, view.getApplication(), view.getSettings(), paintText,
|
||||
paintSubText, false);
|
||||
mapInfoControls.registerSideWidget(bigInfoControl, 0, R.string.map_widget_next_turn,"next_turn", true, all, none, 5);
|
||||
NextTurnInfoControl smallInfoControl = ric.createNextInfoControl(routingHelper, view.getApplication(), view.getSettings(),
|
||||
paintSmallText, paintSmallSubText, true);
|
||||
mapInfoControls.registerSideWidget(smallInfoControl, 0, R.string.map_widget_next_turn_small, "next_turn_small", true, bicyclePedestrian, none, 10);
|
||||
NextTurnInfoControl nextNextInfoControl = ric.createNextNextInfoControl(routingHelper, view.getApplication(), view.getSettings(),
|
||||
paintSmallText, paintSmallSubText, true);
|
||||
mapInfoControls.registerSideWidget(nextNextInfoControl, 0, R.string.map_widget_next_next_turn, "next_next_turn",true, all, none, 15);
|
||||
MiniMapControl miniMap = ric.createMiniMapControl(routingHelper, view);
|
||||
mapInfoControls.registerSideWidget(miniMap, 0, R.string.map_widget_mini_route, "mini_route", true, none, none, 20);
|
||||
// right stack
|
||||
TextInfoControl dist = ric.createDistanceControl(map, paintText, paintSubText);
|
||||
mapInfoControls.registerSideWidget(dist, R.drawable.info_target, R.string.map_widget_distance, "distance", false, all, none, 5);
|
||||
TextInfoControl time = ric.createTimeControl(map, paintText, paintSubText);
|
||||
mapInfoControls.registerSideWidget(time, R.drawable.info_time, R.string.map_widget_time, "time",false, all, none, 10);
|
||||
TextInfoControl speed = ric.createSpeedControl(map, paintText, paintSubText);
|
||||
mapInfoControls.registerSideWidget(speed, R.drawable.info_speed, R.string.map_widget_speed, "speed", false, all, none, 15);
|
||||
TextInfoControl alt = ric.createAltitudeControl(map, paintText, paintSubText);
|
||||
mapInfoControls.registerSideWidget(alt, R.drawable.ic_altitude, R.string.map_widget_altitude, "altitude", false, EnumSet.of(ApplicationMode.PEDESTRIAN), none, 20);
|
||||
|
||||
}
|
||||
|
||||
public void recreateControls(){
|
||||
rightStack.clearAllViews();
|
||||
mapInfoControls.populateStackControl(rightStack, view, false);
|
||||
|
||||
leftStack.clearAllViews();
|
||||
mapInfoControls.populateStackControl(leftStack, view, true);
|
||||
leftStack.requestLayout();
|
||||
rightStack.requestLayout();
|
||||
}
|
||||
|
||||
public void createControls() {
|
||||
// 1. Create view groups and controls
|
||||
statusBar.setBackgroundDrawable(view.getResources().getDrawable(R.drawable.box_top));
|
||||
rightStack = new MapStackControl(view.getContext());
|
||||
rightStack.addStackView(createAltitudeControl());
|
||||
rightStack.addStackView(createDistanceControl());
|
||||
rightStack.addCollapsedView(createSpeedControl());
|
||||
rightStack.addCollapsedView(createTimeControl());
|
||||
|
||||
leftStack = new MapStackControl(view.getContext());
|
||||
leftStack.addStackView(createNextInfoControl());
|
||||
leftStack.addStackView(createMiniMapControl());
|
||||
leftStack.addStackView(createNextNextInfoControl());
|
||||
|
||||
// 2. Preparations
|
||||
Rect topRectPadding = new Rect();
|
||||
|
@ -227,16 +284,99 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
parent.addView(alarmControl);
|
||||
alarmControl.setVisibility(View.GONE);
|
||||
lanesControl.setVisibility(View.GONE);
|
||||
applyTheme();
|
||||
recreateControls();
|
||||
}
|
||||
|
||||
public void openViewConfigureDialog() {
|
||||
final OsmandSettings settings = view.getSettings();
|
||||
|
||||
public boolean distChanged(int oldDist, int dist){
|
||||
if(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist)/oldDist) < 0.01){
|
||||
return false;
|
||||
final ArrayList<Object> list = new ArrayList<Object>();
|
||||
list.add(map.getString(R.string.map_widget_reset));
|
||||
list.add(map.getString(R.string.map_widget_right_stack));
|
||||
list.addAll(mapInfoControls.getRight());
|
||||
list.add(map.getString(R.string.map_widget_left_stack));
|
||||
list.addAll(mapInfoControls.getLeft());
|
||||
|
||||
|
||||
// final LayerMenuListener listener = new LayerMenuListener(adapter, mapView, settings);
|
||||
Builder b = new AlertDialog.Builder(map);
|
||||
final ApplicationMode mode = settings.getApplicationMode();
|
||||
ListAdapter listAdapter = new ArrayAdapter<Object>(map, R.layout.layers_list_activity_item, R.id.title, list) {
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
View v = convertView;
|
||||
if (v == null) {
|
||||
v = map.getLayoutInflater().inflate(R.layout.layers_list_activity_item, null);
|
||||
}
|
||||
return true;
|
||||
TextView tv = (TextView) v.findViewById(R.id.title);
|
||||
final CheckBox ch = ((CheckBox) v.findViewById(R.id.check_item));
|
||||
Object o = list.get(position);
|
||||
if(o instanceof MapInfoControlRegInfo) {
|
||||
final MapInfoControlRegInfo mi = (MapInfoControlRegInfo) o;
|
||||
tv.setText(map.getString(mi.messageId));
|
||||
// Put the image on the TextView
|
||||
if (mi.drawable != 0) {
|
||||
tv.setPadding((int) (12 *scaleCoefficient), 0, 0, 0);
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(mi.drawable, 0, 0, 0);
|
||||
} else {
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
tv.setPadding((int) (27 *scaleCoefficient), 0, 0, 0);
|
||||
}
|
||||
|
||||
boolean check = mi.visibleCollapsed(mode) || mi.visible(mode);
|
||||
ch.setOnCheckedChangeListener(null);
|
||||
ch.setChecked(check);
|
||||
ch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if(!isChecked) {
|
||||
mapInfoControls.changeVisibility(mi, false, false);
|
||||
} else {
|
||||
mapInfoControls.changeVisibility(mi, true, false);
|
||||
}
|
||||
recreateControls();
|
||||
}
|
||||
});
|
||||
ch.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
tv.setText(o.toString());
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
tv.setPadding((int) (5 *scaleCoefficient), 0, 0, 0);
|
||||
ch.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
b.setAdapter(listAdapter, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int position) {
|
||||
Object o = list.get(position);
|
||||
if (o instanceof MapInfoControlRegInfo) {
|
||||
final MapInfoControlRegInfo mi = (MapInfoControlRegInfo) o;
|
||||
boolean check = mi.visibleCollapsed(mode) || mi.visible(mode);
|
||||
if (check) {
|
||||
mapInfoControls.changeVisibility(mi, false, false);
|
||||
} else {
|
||||
mapInfoControls.changeVisibility(mi, true, false);
|
||||
}
|
||||
recreateControls();
|
||||
} else if(o.toString().equals(map.getString(R.string.map_widget_reset))) {
|
||||
mapInfoControls.resetToDefault();
|
||||
recreateControls();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final AlertDialog dlg = b.create();
|
||||
// listener.setDialog(dlg);
|
||||
dlg.setCanceledOnTouchOutside(true);
|
||||
dlg.show();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas, RectF latlonBounds, RectF tilesRect, DrawSettings nightMode) {
|
||||
boolean bold = routeLayer.getHelper().isFollowingMode();
|
||||
|
@ -331,453 +471,6 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
return progressBar;
|
||||
}
|
||||
|
||||
private TextInfoControl createSpeedControl(){
|
||||
final TextInfoControl speedControl = new TextInfoControl(map, 3, paintText, paintSubText) {
|
||||
private float cachedSpeed = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
// draw speed
|
||||
if (map.getLastKnownLocation() != null && map.getLastKnownLocation().hasSpeed()) {
|
||||
// .3 mps == 1.08 kph
|
||||
float minDelta = .3f;
|
||||
// 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(map.getLastKnownLocation().getSpeed() - cachedSpeed) > minDelta) {
|
||||
cachedSpeed = map.getLastKnownLocation().getSpeed();
|
||||
String ds = OsmAndFormatter.getFormattedSpeed(cachedSpeed, map);
|
||||
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.setImageDrawable(view.getResources().getDrawable(R.drawable.info_speed));
|
||||
speedControl.setText(null, null);
|
||||
return speedControl;
|
||||
}
|
||||
|
||||
private TextInfoControl createAltitudeControl(){
|
||||
final TextInfoControl altitudeControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private int cachedAlt = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
// draw speed
|
||||
if (showAltitude &&
|
||||
map.getLastKnownLocation() != null && map.getLastKnownLocation().hasAltitude()) {
|
||||
if (cachedAlt != (int) map.getLastKnownLocation().getAltitude()) {
|
||||
cachedAlt = (int) map.getLastKnownLocation().getAltitude();
|
||||
String ds = OsmAndFormatter.getFormattedAlt(cachedAlt, map);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
setText(ds, null);
|
||||
} else {
|
||||
setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (cachedAlt != 0) {
|
||||
cachedAlt = 0;
|
||||
setText(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
altitudeControl.setText(null, null);
|
||||
altitudeControl.setImageDrawable(view.getResources().getDrawable(R.drawable.ic_altitude));
|
||||
return altitudeControl;
|
||||
}
|
||||
|
||||
private TextInfoControl createTimeControl(){
|
||||
final Drawable time = view.getResources().getDrawable(R.drawable.info_time);
|
||||
final Drawable timeToGo = view.getResources().getDrawable(R.drawable.info_time_to_go);
|
||||
showArrivalTime = view.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME.get();
|
||||
final TextInfoControl leftTimeControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private long cachedLeftTime = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
int time = 0;
|
||||
if (routeLayer != null && routeLayer.getHelper().isRouteCalculated()) {
|
||||
boolean followingMode = routeLayer.getHelper().isFollowingMode();
|
||||
time = routeLayer.getHelper().getLeftTime();
|
||||
if (time != 0) {
|
||||
if (followingMode && showArrivalTime) {
|
||||
long toFindTime = time * 1000 + System.currentTimeMillis();
|
||||
if (Math.abs(toFindTime - cachedLeftTime) > 30000) {
|
||||
cachedLeftTime = toFindTime;
|
||||
if (DateFormat.is24HourFormat(map)) {
|
||||
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;
|
||||
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) {
|
||||
showArrivalTime = !showArrivalTime;
|
||||
leftTimeControl.setImageDrawable(showArrivalTime? time : timeToGo);
|
||||
view.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME.set(showArrivalTime);
|
||||
view.refreshMap();
|
||||
}
|
||||
|
||||
});
|
||||
leftTimeControl.setText(null, null);
|
||||
leftTimeControl.setImageDrawable(showArrivalTime? time : timeToGo);
|
||||
return leftTimeControl;
|
||||
}
|
||||
|
||||
private TextInfoControl createDistanceControl() {
|
||||
TextInfoControl distanceControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private float[] calculations = new float[1];
|
||||
private int cachedMeters = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
if (map.getPointToNavigate() != null) {
|
||||
int d = 0;
|
||||
if (map.getRoutingHelper().isRouteCalculated()) {
|
||||
d = map.getRoutingHelper().getLeftDistance();
|
||||
}
|
||||
if (d == 0) {
|
||||
Location.distanceBetween(view.getLatitude(), view.getLongitude(), map.getPointToNavigate().getLatitude(), map
|
||||
.getPointToNavigate().getLongitude(), calculations);
|
||||
d = (int) calculations[0];
|
||||
}
|
||||
if (distChanged(cachedMeters, d)) {
|
||||
cachedMeters = d;
|
||||
if (cachedMeters <= 20) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
} else {
|
||||
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, map);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
setText(ds, null);
|
||||
} else {
|
||||
setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (cachedMeters != 0) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
distanceControl.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
|
||||
LatLon pointToNavigate = view.getSettings().getPointToNavigate();
|
||||
if (pointToNavigate != null) {
|
||||
float fZoom = view.getFloatZoom() < 15 ? 15 : view.getFloatZoom();
|
||||
thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
distanceControl.setText(null, null);
|
||||
distanceControl.setImageDrawable(view.getResources().getDrawable(R.drawable.info_target));
|
||||
return distanceControl;
|
||||
}
|
||||
|
||||
protected MiniMapControl createMiniMapControl() {
|
||||
final MiniMapControl miniMapControl = new MiniMapControl(map, view) {
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
updateVisibility(visible);
|
||||
return super.updateInfo();
|
||||
}
|
||||
};
|
||||
miniMapControl.setVisibility(View.GONE);
|
||||
miniMapControl.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// showMiniMap = false;
|
||||
miniMapControl.invalidate();
|
||||
view.refreshMap();
|
||||
}
|
||||
});
|
||||
return miniMapControl;
|
||||
}
|
||||
|
||||
private NextTurnInfoControl createNextNextInfoControl() {
|
||||
final RoutingHelper routingHelper = routeLayer.getHelper();
|
||||
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(map, paintSmallText, paintSmallSubText, true) {
|
||||
NextDirectionInfo calc1 = new NextDirectionInfo();
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
if (routeLayer != null && routingHelper.isRouteCalculated() && routingHelper.isFollowingMode()) {
|
||||
boolean uturnWhenPossible = routingHelper.makeUturnWhenPossible() ;
|
||||
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true);
|
||||
if (!uturnWhenPossible) {
|
||||
if (r != null) {
|
||||
// next turn is very close (show next next with false to speak)
|
||||
// if (r.imminent >= 0 && r.imminent < 2) {
|
||||
// r = routingHelper.getNextRouteDirectionInfoAfter(r, calc1, false);
|
||||
// } else {
|
||||
r = routingHelper.getNextRouteDirectionInfo(calc1, true);
|
||||
if (r != null) {
|
||||
r = routingHelper.getNextRouteDirectionInfoAfter(r, calc1, true);
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
if (r != null && r.distanceTo > 0) {
|
||||
visible = true;
|
||||
if (r == null || r.directionInfo == null) {
|
||||
if (turnType != null) {
|
||||
turnType = null;
|
||||
invalidate();
|
||||
}
|
||||
} else if (!Algoritms.objectEquals(turnType, r.directionInfo.getTurnType())) {
|
||||
turnType = r.directionInfo.getTurnType();
|
||||
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
|
||||
invalidate();
|
||||
requestLayout();
|
||||
}
|
||||
if (distChanged(r.distanceTo, nextTurnDirection)) {
|
||||
invalidate();
|
||||
requestLayout();
|
||||
nextTurnDirection = r.distanceTo;
|
||||
}
|
||||
int imminent = r.imminent;
|
||||
if (turnImminent != imminent) {
|
||||
turnImminent = imminent;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
|
||||
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;
|
||||
view.refreshMap();
|
||||
}
|
||||
});
|
||||
// initial state
|
||||
// nextTurnInfo.setVisibility(View.GONE);
|
||||
return nextTurnInfo;
|
||||
}
|
||||
|
||||
private MapInfoControl createAlarmInfoControl() {
|
||||
final RoutingHelper routingHelper = routeLayer.getHelper();
|
||||
final Paint paintCircle = new Paint();
|
||||
final float th = 11 * scaleCoefficient;
|
||||
paintCircle.setColor(Color.rgb(225, 15, 15));
|
||||
paintCircle.setStrokeWidth(11 * scaleCoefficient);
|
||||
paintCircle.setStyle(Style.STROKE);
|
||||
paintCircle.setAntiAlias(true);
|
||||
final Paint content = new Paint();
|
||||
content.setColor(Color.WHITE);
|
||||
content.setStyle(Style.FILL);
|
||||
final Paint ptext = new Paint();
|
||||
ptext.setTextSize(27 * scaleCoefficient);
|
||||
ptext.setFakeBoldText(true);
|
||||
ptext.setAntiAlias(true);
|
||||
ptext.setTextAlign(Align.CENTER);
|
||||
|
||||
final OsmandSettings settings = view.getSettings();
|
||||
final MapInfoControl alarm = new MapInfoControl(map) {
|
||||
private String text = "";
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean limits = settings.SHOW_SPEED_LIMITS.get();
|
||||
boolean cams = settings.SHOW_CAMERAS.get();
|
||||
boolean visible = false;
|
||||
if ((limits || cams) && routeLayer != null && routingHelper.isFollowingMode()) {
|
||||
AlarmInfo alarm = routingHelper.getMostImportantAlarm(view.getSettings().METRIC_SYSTEM.get());
|
||||
if(alarm != null) {
|
||||
if(alarm.getType() == AlarmInfo.SPEED_LIMIT) {
|
||||
text = alarm.getIntValue() +"";
|
||||
} else if(alarm.getType() == AlarmInfo.SPEED_CAMERA) {
|
||||
text = "CAM";
|
||||
} else if(alarm.getType() == AlarmInfo.BORDER_CONTROL) {
|
||||
text = "CLO";
|
||||
} else if(alarm.getType() == AlarmInfo.TOLL_BOOTH) {
|
||||
text = "$";
|
||||
} else if(alarm.getType() == AlarmInfo.TRAFFIC_CALMING) {
|
||||
// temporary omega
|
||||
text = "~^~";
|
||||
} else if(alarm.getType() == AlarmInfo.STOP) {
|
||||
// text = "STOP";
|
||||
}
|
||||
visible = text.length() > 0;
|
||||
if (visible) {
|
||||
if (alarm.getType() == AlarmInfo.SPEED_CAMERA) {
|
||||
visible = cams;
|
||||
} else {
|
||||
visible = limits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
RectF f = new RectF(th / 2, th / 2, getWidth() - th / 2, getHeight() - th / 2);
|
||||
canvas.drawOval(f, content);
|
||||
canvas.drawOval(f, paintCircle);
|
||||
canvas.drawText(text, getWidth() / 2, getHeight() / 2 + ptext.descent() + 3 * scaleCoefficient, ptext);
|
||||
}
|
||||
|
||||
};
|
||||
// initial state
|
||||
// nextTurnInfo.setVisibility(View.GONE);
|
||||
return alarm;
|
||||
}
|
||||
|
||||
private NextTurnInfoControl createNextInfoControl() {
|
||||
final RoutingHelper routingHelper = routeLayer.getHelper();
|
||||
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(map, paintText, paintSubText, false) {
|
||||
NextDirectionInfo calc1 = new NextDirectionInfo();
|
||||
TurnType straight = TurnType.valueOf(TurnType.C, true);
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
if (routeLayer != null && routingHelper.isRouteCalculated() && routingHelper.isFollowingMode()) {
|
||||
makeUturnWhenPossible = routingHelper.makeUturnWhenPossible() ;
|
||||
if (makeUturnWhenPossible) {
|
||||
visible = true;
|
||||
turnImminent = 0;
|
||||
turnType = TurnType.valueOf(TurnType.TU, view.getSettings().LEFT_SIDE_NAVIGATION.get());
|
||||
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
|
||||
invalidate();
|
||||
} else {
|
||||
boolean showStraight = false;
|
||||
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true);
|
||||
if (r != null && r.distanceTo > 0) {
|
||||
visible = true;
|
||||
if (r.directionInfo == null) {
|
||||
if (turnType != null) {
|
||||
turnType = null;
|
||||
invalidate();
|
||||
}
|
||||
} else if (!Algoritms.objectEquals(turnType, showStraight ? straight : r.directionInfo.getTurnType())) {
|
||||
turnType = showStraight ? straight : r.directionInfo.getTurnType();
|
||||
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
|
||||
if (turnType.getExitOut() > 0) {
|
||||
exitOut = turnType.getExitOut() + ""; //$NON-NLS-1$
|
||||
} else {
|
||||
exitOut = null;
|
||||
}
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
if (distChanged(r.distanceTo, nextTurnDirection)) {
|
||||
invalidate();
|
||||
requestLayout();
|
||||
nextTurnDirection = r.distanceTo;
|
||||
}
|
||||
if (turnImminent != r.imminent) {
|
||||
turnImminent = r.imminent;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
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);
|
||||
// showMiniMap = true;
|
||||
nextTurnInfo.requestLayout();
|
||||
view.refreshMap();
|
||||
}
|
||||
});
|
||||
// initial state
|
||||
nextTurnInfo.setVisibility(View.GONE);
|
||||
return nextTurnInfo;
|
||||
}
|
||||
|
||||
private ViewGroup createStatusBar() {
|
||||
LinearLayout statusBar = new LinearLayout(view.getContext());
|
||||
statusBar.setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
@ -832,7 +525,9 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
globus.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
map.getMapLayers().selectMapLayer(view);
|
||||
// TODO
|
||||
openViewConfigureDialog();
|
||||
// map.getMapLayers().selectMapLayer(view);
|
||||
}
|
||||
});
|
||||
fl.addView(globus, fparams);
|
||||
|
@ -870,109 +565,5 @@ public class MapInfoLayer extends OsmandMapLayer {
|
|||
}
|
||||
}
|
||||
|
||||
private static final float miniCoeff = 2f;
|
||||
private MapInfoControl createLanesControl() {
|
||||
final Path laneStraight = new Path();
|
||||
Matrix pathTransform = new Matrix();
|
||||
pathTransform.postScale(scaleCoefficient / miniCoeff, scaleCoefficient / miniCoeff);
|
||||
TurnPathHelper.calcTurnPath(laneStraight, TurnType.valueOf(TurnType.C, false), pathTransform);
|
||||
final Paint paintBlack = new Paint();
|
||||
paintBlack.setStyle(Style.STROKE);
|
||||
paintBlack.setColor(Color.BLACK);
|
||||
paintBlack.setAntiAlias(true);
|
||||
paintBlack.setStrokeWidth(2.5f);
|
||||
|
||||
final Paint paintRouteDirection = new Paint();
|
||||
paintRouteDirection.setStyle(Style.FILL);
|
||||
paintRouteDirection.setColor(view.getResources().getColor(R.color.nav_arrow));
|
||||
paintRouteDirection.setAntiAlias(true);
|
||||
final float w = 72 * scaleCoefficient / miniCoeff;
|
||||
|
||||
|
||||
final RoutingHelper routingHelper = routeLayer.getHelper();
|
||||
final MapInfoControl lanesControl = new MapInfoControl(map) {
|
||||
int[] lanes = null;
|
||||
|
||||
boolean imminent = false;
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int ls = (int) (lanes == null ? 0 : lanes.length * w);
|
||||
setWDimensions(ls, (int)( w + 3 * scaleCoefficient));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
//to change color immediately when needed
|
||||
if (lanes != null && lanes.length > 0) {
|
||||
canvas.save();
|
||||
// canvas.translate((int) (16 * scaleCoefficient), 0);
|
||||
for (int i = 0; i < lanes.length; i++) {
|
||||
if ((lanes[i] & 1) == 1) {
|
||||
paintRouteDirection.setColor(imminent ? getResources().getColor(R.color.nav_arrow_imminent) : getResources().getColor(R.color.nav_arrow));
|
||||
} else {
|
||||
paintRouteDirection.setColor(getResources().getColor(R.color.nav_arrow_distant));
|
||||
}
|
||||
canvas.drawPath(laneStraight, paintBlack);
|
||||
canvas.drawPath(laneStraight, paintRouteDirection);
|
||||
canvas.translate(w, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
int locimminent = -1;
|
||||
int[] loclanes = null;
|
||||
if (routeLayer != null && routingHelper.isRouteCalculated()) {
|
||||
if (routingHelper.isFollowingMode()) {
|
||||
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(new NextDirectionInfo(), false);
|
||||
if(r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) {
|
||||
loclanes = r.directionInfo.getTurnType().getLanes();
|
||||
locimminent = r.imminent;
|
||||
// Do not show too far
|
||||
if ((r.distanceTo > 700 && r.directionInfo.getTurnType().isSkipToSpeak()) || r.distanceTo > 1200) {
|
||||
loclanes = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int di = map.getMapLayers().getRouteInfoLayer().getDirectionInfo();
|
||||
if (di >= 0 && map.getMapLayers().getRouteInfoLayer().isVisible()) {
|
||||
RouteDirectionInfo next = routingHelper.getRouteDirections().get(di);
|
||||
if(next != null) {
|
||||
loclanes = next.getTurnType().getLanes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
visible = loclanes != null && loclanes.length > 0;
|
||||
if (visible) {
|
||||
if (!Arrays.equals(lanes, loclanes)) {
|
||||
lanes = loclanes;
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
if ((locimminent == 0) != imminent) {
|
||||
imminent = (locimminent == 0);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return lanesControl;
|
||||
}
|
||||
|
||||
public void addRightStack(MapInfoControl v){
|
||||
rightStack.addStackView(v);
|
||||
}
|
||||
|
||||
public MapStackControl getRightStack(){
|
||||
return rightStack;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,12 +85,20 @@ public class MapStackControl extends ViewGroup {
|
|||
|
||||
public void addStackView(MapInfoControl v) {
|
||||
stackViews.add(v);
|
||||
MapStackControl.this.addView(v, 1);
|
||||
MapStackControl.this.addView(v, getChildCount());
|
||||
}
|
||||
|
||||
public void addCollapsedView(MapInfoControl v) {
|
||||
collapsedViews.add(v);
|
||||
MapStackControl.this.addView(v, 1);
|
||||
MapStackControl.this.addView(v, getChildCount());
|
||||
}
|
||||
|
||||
public void clearAllViews(){
|
||||
stackViews.clear();
|
||||
collapsedViews.clear();
|
||||
while(getChildCount() > 1){
|
||||
removeViewAt(1);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MapInfoControl> getStackViews() {
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.graphics.Paint.Cap;
|
|||
import android.graphics.Paint.Join;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.view.View;
|
||||
|
||||
public class MiniMapControl extends MapInfoControl {
|
||||
private float scaleCoefficient = MapInfoLayer.scaleCoefficient;
|
||||
|
@ -48,7 +49,9 @@ public class MiniMapControl extends MapInfoControl {
|
|||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
if(getVisibility() == View.VISIBLE) {
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ import android.graphics.Path;
|
|||
public class NextTurnInfoControl extends MapInfoControl {
|
||||
|
||||
private float scaleCoefficient = MapInfoLayer.scaleCoefficient;
|
||||
private final float width;
|
||||
private final float height ;
|
||||
private float width;
|
||||
private float height ;
|
||||
private static final float miniCoeff = 2.5f;
|
||||
|
||||
protected Path pathForTurn = new Path();
|
||||
|
@ -27,20 +27,20 @@ public class NextTurnInfoControl extends MapInfoControl {
|
|||
protected int nextTurnDirection = 0;
|
||||
|
||||
|
||||
private final Paint textPaint;
|
||||
private final Paint subtextPaint;
|
||||
protected Paint textPaint;
|
||||
protected Paint subtextPaint;
|
||||
private Paint paintBlack;
|
||||
private Paint paintRouteDirection;
|
||||
|
||||
protected boolean makeUturnWhenPossible;
|
||||
protected int turnImminent;
|
||||
private final boolean horisontalMini;
|
||||
protected boolean horisontalMini;
|
||||
|
||||
public NextTurnInfoControl(Context ctx, Paint textPaint, Paint subtextPaint, boolean horisontalMini) {
|
||||
super(ctx);
|
||||
this.textPaint = textPaint;
|
||||
this.subtextPaint = subtextPaint;
|
||||
this.horisontalMini = horisontalMini;
|
||||
|
||||
|
||||
paintBlack = new Paint();
|
||||
paintBlack.setStyle(Style.STROKE);
|
||||
|
@ -54,6 +54,12 @@ public class NextTurnInfoControl extends MapInfoControl {
|
|||
paintRouteDirection.setAntiAlias(true);
|
||||
|
||||
pathTransform = new Matrix();
|
||||
updateHorisontalMini(horisontalMini);
|
||||
|
||||
}
|
||||
|
||||
protected void updateHorisontalMini(boolean horisontalMini) {
|
||||
this.horisontalMini = horisontalMini;
|
||||
if (horisontalMini) {
|
||||
pathTransform.postScale(scaleCoefficient / miniCoeff, scaleCoefficient / miniCoeff);
|
||||
width = 72 * scaleCoefficient / miniCoeff;
|
||||
|
@ -63,9 +69,10 @@ public class NextTurnInfoControl extends MapInfoControl {
|
|||
width = 72 * scaleCoefficient;
|
||||
height = 72 * scaleCoefficient;
|
||||
}
|
||||
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
|
||||
protected Matrix pathTransform = new Matrix();
|
||||
|
||||
@Override
|
||||
|
|
587
OsmAnd/src/net/osmand/plus/views/RouteInfoControls.java
Normal file
587
OsmAnd/src/net/osmand/plus/views/RouteInfoControls.java
Normal file
|
@ -0,0 +1,587 @@
|
|||
package net.osmand.plus.views;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.OsmAndFormatter;
|
||||
import net.osmand.osm.LatLon;
|
||||
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.activities.MapActivity;
|
||||
import net.osmand.plus.routing.AlarmInfo;
|
||||
import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo;
|
||||
import net.osmand.plus.routing.RouteDirectionInfo;
|
||||
import net.osmand.plus.routing.RoutingHelper;
|
||||
import net.osmand.router.TurnType;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.location.Location;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.View;
|
||||
|
||||
public class RouteInfoControls {
|
||||
public float scaleCoefficient = 1;
|
||||
|
||||
public RouteInfoControls(float scaleCoefficient){
|
||||
this.scaleCoefficient = scaleCoefficient;
|
||||
}
|
||||
|
||||
public NextTurnInfoControl createNextInfoControl(final RoutingHelper routingHelper, Context ctx,
|
||||
final OsmandSettings settings, Paint textPaint, Paint subtextPaint, boolean horisontalMini) {
|
||||
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(ctx, textPaint, subtextPaint, horisontalMini) {
|
||||
NextDirectionInfo calc1 = new NextDirectionInfo();
|
||||
TurnType straight = TurnType.valueOf(TurnType.C, true);
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
if (routingHelper != null && routingHelper.isRouteCalculated() && routingHelper.isFollowingMode()) {
|
||||
makeUturnWhenPossible = routingHelper.makeUturnWhenPossible() ;
|
||||
if (makeUturnWhenPossible) {
|
||||
visible = true;
|
||||
turnImminent = 0;
|
||||
turnType = TurnType.valueOf(TurnType.TU, settings.LEFT_SIDE_NAVIGATION.get());
|
||||
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
|
||||
invalidate();
|
||||
} else {
|
||||
boolean showStraight = false;
|
||||
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true);
|
||||
if (r != null && r.distanceTo > 0) {
|
||||
visible = true;
|
||||
if (r.directionInfo == null) {
|
||||
if (turnType != null) {
|
||||
turnType = null;
|
||||
invalidate();
|
||||
}
|
||||
} else if (!Algoritms.objectEquals(turnType, showStraight ? straight : r.directionInfo.getTurnType())) {
|
||||
turnType = showStraight ? straight : r.directionInfo.getTurnType();
|
||||
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
|
||||
if (turnType.getExitOut() > 0) {
|
||||
exitOut = turnType.getExitOut() + ""; //$NON-NLS-1$
|
||||
} else {
|
||||
exitOut = null;
|
||||
}
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
if (distChanged(r.distanceTo, nextTurnDirection)) {
|
||||
invalidate();
|
||||
requestLayout();
|
||||
nextTurnDirection = r.distanceTo;
|
||||
}
|
||||
if (turnImminent != r.imminent) {
|
||||
turnImminent = r.imminent;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
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);
|
||||
// showMiniMap = true;
|
||||
nextTurnInfo.requestLayout();
|
||||
nextTurnInfo.invalidate();
|
||||
}
|
||||
});
|
||||
// initial state
|
||||
nextTurnInfo.setVisibility(View.GONE);
|
||||
return nextTurnInfo;
|
||||
}
|
||||
|
||||
public NextTurnInfoControl createNextNextInfoControl(final RoutingHelper routingHelper, Context ctx,
|
||||
final OsmandSettings settings, Paint textPaint, Paint subtextPaint, boolean horisontalMini) {
|
||||
final NextTurnInfoControl nextTurnInfo = new NextTurnInfoControl(ctx, textPaint, subtextPaint, horisontalMini) {
|
||||
NextDirectionInfo calc1 = new NextDirectionInfo();
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
if (routingHelper != null && routingHelper.isRouteCalculated() && routingHelper.isFollowingMode()
|
||||
) {
|
||||
boolean uturnWhenPossible = routingHelper.makeUturnWhenPossible() ;
|
||||
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(calc1, true);
|
||||
if (!uturnWhenPossible) {
|
||||
if (r != null) {
|
||||
// next turn is very close (show next next with false to speak)
|
||||
// if (r.imminent >= 0 && r.imminent < 2) {
|
||||
// r = routingHelper.getNextRouteDirectionInfoAfter(r, calc1, false);
|
||||
// } else {
|
||||
r = routingHelper.getNextRouteDirectionInfo(calc1, true);
|
||||
if (r != null) {
|
||||
r = routingHelper.getNextRouteDirectionInfoAfter(r, calc1, true);
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
if (r != null && r.distanceTo > 0) {
|
||||
visible = true;
|
||||
if (r == null || r.directionInfo == null) {
|
||||
if (turnType != null) {
|
||||
turnType = null;
|
||||
invalidate();
|
||||
}
|
||||
} else if (!Algoritms.objectEquals(turnType, r.directionInfo.getTurnType())) {
|
||||
turnType = r.directionInfo.getTurnType();
|
||||
TurnPathHelper.calcTurnPath(pathForTurn, turnType, pathTransform);
|
||||
invalidate();
|
||||
requestLayout();
|
||||
}
|
||||
if (distChanged(r.distanceTo, nextTurnDirection)) {
|
||||
invalidate();
|
||||
requestLayout();
|
||||
nextTurnDirection = r.distanceTo;
|
||||
}
|
||||
int imminent = r.imminent;
|
||||
if (turnImminent != imminent) {
|
||||
turnImminent = imminent;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
|
||||
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
|
||||
// nextTurnInfo.setVisibility(View.GONE);
|
||||
return nextTurnInfo;
|
||||
}
|
||||
|
||||
|
||||
protected TextInfoControl createTimeControl(final MapActivity map, Paint paintText, Paint paintSubText){
|
||||
final RoutingHelper routingHelper = map.getRoutingHelper();
|
||||
final Drawable time = map.getResources().getDrawable(R.drawable.info_time);
|
||||
final Drawable timeToGo = map.getResources().getDrawable(R.drawable.info_time_to_go);
|
||||
final OsmandApplication ctx = map.getMyApplication();
|
||||
final OsmandPreference<Boolean> showArrival = ctx.getSettings().SHOW_ARRIVAL_TIME_OTHERWISE_EXPECTED_TIME;
|
||||
final TextInfoControl leftTimeControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private long cachedLeftTime = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
int time = 0;
|
||||
if (routingHelper != null && routingHelper.isRouteCalculated()) {
|
||||
boolean followingMode = routingHelper.isFollowingMode();
|
||||
time = routingHelper.getLeftTime();
|
||||
if (time != 0) {
|
||||
if (followingMode && showArrival.get()) {
|
||||
long toFindTime = time * 1000 + System.currentTimeMillis();
|
||||
if (Math.abs(toFindTime - cachedLeftTime) > 30000) {
|
||||
cachedLeftTime = toFindTime;
|
||||
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;
|
||||
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());
|
||||
leftTimeControl.setImageDrawable(showArrival.get()? time : timeToGo);
|
||||
leftTimeControl.requestLayout();
|
||||
}
|
||||
|
||||
});
|
||||
leftTimeControl.setText(null, null);
|
||||
leftTimeControl.setImageDrawable(showArrival.get()? time : timeToGo);
|
||||
return leftTimeControl;
|
||||
}
|
||||
|
||||
protected TextInfoControl createAltitudeControl(final MapActivity map, Paint paintText, Paint paintSubText) {
|
||||
final TextInfoControl altitudeControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private int cachedAlt = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
// draw speed
|
||||
if (map.getLastKnownLocation() != null && map.getLastKnownLocation().hasAltitude()) {
|
||||
if (cachedAlt != (int) map.getLastKnownLocation().getAltitude()) {
|
||||
cachedAlt = (int) map.getLastKnownLocation().getAltitude();
|
||||
String ds = OsmAndFormatter.getFormattedAlt(cachedAlt, map);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
setText(ds, null);
|
||||
} else {
|
||||
setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (cachedAlt != 0) {
|
||||
cachedAlt = 0;
|
||||
setText(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
altitudeControl.setText(null, null);
|
||||
altitudeControl.setImageDrawable(map.getResources().getDrawable(R.drawable.ic_altitude));
|
||||
return altitudeControl;
|
||||
}
|
||||
|
||||
protected TextInfoControl createSpeedControl(final MapActivity map, Paint paintText, Paint paintSubText) {
|
||||
final TextInfoControl speedControl = new TextInfoControl(map, 3, paintText, paintSubText) {
|
||||
private float cachedSpeed = 0;
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
// draw speed
|
||||
if (map.getLastKnownLocation() != null && map.getLastKnownLocation().hasSpeed()) {
|
||||
// .3 mps == 1.08 kph
|
||||
float minDelta = .3f;
|
||||
// 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(map.getLastKnownLocation().getSpeed() - cachedSpeed) > minDelta) {
|
||||
cachedSpeed = map.getLastKnownLocation().getSpeed();
|
||||
String ds = OsmAndFormatter.getFormattedSpeed(cachedSpeed, map);
|
||||
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.setImageDrawable(map.getResources().getDrawable(R.drawable.info_speed));
|
||||
speedControl.setText(null, null);
|
||||
return speedControl;
|
||||
}
|
||||
|
||||
protected TextInfoControl createDistanceControl(final MapActivity map, Paint paintText, Paint paintSubText) {
|
||||
final OsmandMapTileView view = map.getMapView();
|
||||
TextInfoControl distanceControl = new TextInfoControl(map, 0, paintText, paintSubText) {
|
||||
private float[] calculations = new float[1];
|
||||
private int cachedMeters = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
if (map.getPointToNavigate() != null) {
|
||||
int d = 0;
|
||||
if (map.getRoutingHelper().isRouteCalculated()) {
|
||||
d = map.getRoutingHelper().getLeftDistance();
|
||||
}
|
||||
if (d == 0) {
|
||||
Location.distanceBetween(view.getLatitude(), view.getLongitude(), map.getPointToNavigate().getLatitude(), map
|
||||
.getPointToNavigate().getLongitude(), calculations);
|
||||
d = (int) calculations[0];
|
||||
}
|
||||
if (distChanged(cachedMeters, d)) {
|
||||
cachedMeters = d;
|
||||
if (cachedMeters <= 20) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
} else {
|
||||
String ds = OsmAndFormatter.getFormattedDistance(cachedMeters, map);
|
||||
int ls = ds.lastIndexOf(' ');
|
||||
if (ls == -1) {
|
||||
setText(ds, null);
|
||||
} else {
|
||||
setText(ds.substring(0, ls), ds.substring(ls + 1));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else if (cachedMeters != 0) {
|
||||
cachedMeters = 0;
|
||||
setText(null, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
distanceControl.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
AnimateDraggingMapThread thread = view.getAnimatedDraggingThread();
|
||||
LatLon pointToNavigate = view.getSettings().getPointToNavigate();
|
||||
if (pointToNavigate != null) {
|
||||
float fZoom = view.getFloatZoom() < 15 ? 15 : view.getFloatZoom();
|
||||
thread.startMoving(pointToNavigate.getLatitude(), pointToNavigate.getLongitude(), fZoom, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
distanceControl.setText(null, null);
|
||||
distanceControl.setImageDrawable(view.getResources().getDrawable(R.drawable.info_target));
|
||||
return distanceControl;
|
||||
}
|
||||
|
||||
protected MiniMapControl createMiniMapControl(final RoutingHelper routingHelper, OsmandMapTileView view) {
|
||||
final MiniMapControl miniMapControl = new MiniMapControl(view.getContext(), view) {
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = routingHelper.isFollowingMode();
|
||||
updateVisibility(visible);
|
||||
return super.updateInfo();
|
||||
}
|
||||
};
|
||||
miniMapControl.setVisibility(View.GONE);
|
||||
return miniMapControl;
|
||||
}
|
||||
|
||||
private static final float miniCoeff = 2f;
|
||||
protected MapInfoControl createLanesControl(final RoutingHelper routingHelper, final OsmandMapTileView view) {
|
||||
final Path laneStraight = new Path();
|
||||
Matrix pathTransform = new Matrix();
|
||||
pathTransform.postScale(scaleCoefficient / miniCoeff, scaleCoefficient / miniCoeff);
|
||||
TurnPathHelper.calcTurnPath(laneStraight, TurnType.valueOf(TurnType.C, false), pathTransform);
|
||||
final Paint paintBlack = new Paint();
|
||||
paintBlack.setStyle(Style.STROKE);
|
||||
paintBlack.setColor(Color.BLACK);
|
||||
paintBlack.setAntiAlias(true);
|
||||
paintBlack.setStrokeWidth(2.5f);
|
||||
|
||||
final Paint paintRouteDirection = new Paint();
|
||||
paintRouteDirection.setStyle(Style.FILL);
|
||||
paintRouteDirection.setColor(view.getResources().getColor(R.color.nav_arrow));
|
||||
paintRouteDirection.setAntiAlias(true);
|
||||
final float w = 72 * scaleCoefficient / miniCoeff;
|
||||
|
||||
|
||||
final MapInfoControl lanesControl = new MapInfoControl(view.getContext()) {
|
||||
int[] lanes = null;
|
||||
|
||||
boolean imminent = false;
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int ls = (int) (lanes == null ? 0 : lanes.length * w);
|
||||
setWDimensions(ls, (int)( w + 3 * scaleCoefficient));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
//to change color immediately when needed
|
||||
if (lanes != null && lanes.length > 0) {
|
||||
canvas.save();
|
||||
// canvas.translate((int) (16 * scaleCoefficient), 0);
|
||||
for (int i = 0; i < lanes.length; i++) {
|
||||
if ((lanes[i] & 1) == 1) {
|
||||
paintRouteDirection.setColor(imminent ? getResources().getColor(R.color.nav_arrow_imminent) : getResources().getColor(R.color.nav_arrow));
|
||||
} else {
|
||||
paintRouteDirection.setColor(getResources().getColor(R.color.nav_arrow_distant));
|
||||
}
|
||||
canvas.drawPath(laneStraight, paintBlack);
|
||||
canvas.drawPath(laneStraight, paintRouteDirection);
|
||||
canvas.translate(w, 0);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean visible = false;
|
||||
int locimminent = -1;
|
||||
int[] loclanes = null;
|
||||
if (routingHelper != null && routingHelper.isRouteCalculated()) {
|
||||
if (routingHelper.isFollowingMode()) {
|
||||
NextDirectionInfo r = routingHelper.getNextRouteDirectionInfo(new NextDirectionInfo(), false);
|
||||
if(r != null && r.directionInfo != null && r.directionInfo.getTurnType() != null) {
|
||||
loclanes = r.directionInfo.getTurnType().getLanes();
|
||||
locimminent = r.imminent;
|
||||
// Do not show too far
|
||||
if ((r.distanceTo > 700 && r.directionInfo.getTurnType().isSkipToSpeak()) || r.distanceTo > 1200) {
|
||||
loclanes = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RouteInfoLayer ls = view.getLayerByClass(RouteInfoLayer.class);
|
||||
if (ls != null) {
|
||||
int di = ls.getDirectionInfo();
|
||||
if (di >= 0 && ls.isVisible()) {
|
||||
RouteDirectionInfo next = routingHelper.getRouteDirections().get(di);
|
||||
if (next != null) {
|
||||
loclanes = next.getTurnType().getLanes();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
visible = loclanes != null && loclanes.length > 0;
|
||||
if (visible) {
|
||||
if (!Arrays.equals(lanes, loclanes)) {
|
||||
lanes = loclanes;
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
if ((locimminent == 0) != imminent) {
|
||||
imminent = (locimminent == 0);
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
return lanesControl;
|
||||
}
|
||||
|
||||
|
||||
protected MapInfoControl createAlarmInfoControl(final RoutingHelper routingHelper, Context ctx,
|
||||
final OsmandSettings settings) {
|
||||
final Paint paintCircle = new Paint();
|
||||
final float th = 11 * scaleCoefficient;
|
||||
paintCircle.setColor(Color.rgb(225, 15, 15));
|
||||
paintCircle.setStrokeWidth(11 * scaleCoefficient);
|
||||
paintCircle.setStyle(Style.STROKE);
|
||||
paintCircle.setAntiAlias(true);
|
||||
final Paint content = new Paint();
|
||||
content.setColor(Color.WHITE);
|
||||
content.setStyle(Style.FILL);
|
||||
final Paint ptext = new Paint();
|
||||
ptext.setTextSize(27 * scaleCoefficient);
|
||||
ptext.setFakeBoldText(true);
|
||||
ptext.setAntiAlias(true);
|
||||
ptext.setTextAlign(Align.CENTER);
|
||||
|
||||
final MapInfoControl alarm = new MapInfoControl(ctx) {
|
||||
private String text = "";
|
||||
@Override
|
||||
public boolean updateInfo() {
|
||||
boolean limits = settings.SHOW_SPEED_LIMITS.get();
|
||||
boolean cams = settings.SHOW_CAMERAS.get();
|
||||
boolean visible = false;
|
||||
if ((limits || cams) && routingHelper != null && routingHelper.isFollowingMode()) {
|
||||
AlarmInfo alarm = routingHelper.getMostImportantAlarm(settings.METRIC_SYSTEM.get());
|
||||
if(alarm != null) {
|
||||
if(alarm.getType() == AlarmInfo.SPEED_LIMIT) {
|
||||
text = alarm.getIntValue() +"";
|
||||
} else if(alarm.getType() == AlarmInfo.SPEED_CAMERA) {
|
||||
text = "CAM";
|
||||
} else if(alarm.getType() == AlarmInfo.BORDER_CONTROL) {
|
||||
text = "CLO";
|
||||
} else if(alarm.getType() == AlarmInfo.TOLL_BOOTH) {
|
||||
text = "$";
|
||||
} else if(alarm.getType() == AlarmInfo.TRAFFIC_CALMING) {
|
||||
// temporary omega
|
||||
text = "~^~";
|
||||
} else if(alarm.getType() == AlarmInfo.STOP) {
|
||||
// text = "STOP";
|
||||
}
|
||||
visible = text.length() > 0;
|
||||
if (visible) {
|
||||
if (alarm.getType() == AlarmInfo.SPEED_CAMERA) {
|
||||
visible = cams;
|
||||
} else {
|
||||
visible = limits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateVisibility(visible);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
RectF f = new RectF(th / 2, th / 2, getWidth() - th / 2, getHeight() - th / 2);
|
||||
canvas.drawOval(f, content);
|
||||
canvas.drawOval(f, paintCircle);
|
||||
canvas.drawText(text, getWidth() / 2, getHeight() / 2 + ptext.descent() + 3 * scaleCoefficient, ptext);
|
||||
}
|
||||
|
||||
};
|
||||
// initial state
|
||||
// nextTurnInfo.setVisibility(View.GONE);
|
||||
return alarm;
|
||||
}
|
||||
|
||||
|
||||
public boolean distChanged(int oldDist, int dist){
|
||||
if(oldDist != 0 && oldDist - dist < 100 && Math.abs(((float) dist - oldDist)/oldDist) < 0.01){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue