diff --git a/OsmAnd/res/drawable-hdpi/poi_parking_pos_info.png b/OsmAnd/res/drawable-hdpi/poi_parking_pos_info.png new file mode 100644 index 0000000000..3b2ffb13bf Binary files /dev/null and b/OsmAnd/res/drawable-hdpi/poi_parking_pos_info.png differ diff --git a/OsmAnd/res/drawable-hdpi/poi_parking_pos_limit_menu.png b/OsmAnd/res/drawable-hdpi/poi_parking_pos_limit_menu.png index ae9b234874..cad52bba3a 100644 Binary files a/OsmAnd/res/drawable-hdpi/poi_parking_pos_limit_menu.png and b/OsmAnd/res/drawable-hdpi/poi_parking_pos_limit_menu.png differ diff --git a/OsmAnd/res/drawable-hdpi/poi_parking_pos_no_limit_menu.png b/OsmAnd/res/drawable-hdpi/poi_parking_pos_no_limit_menu.png index 6719431465..1348f994d1 100644 Binary files a/OsmAnd/res/drawable-hdpi/poi_parking_pos_no_limit_menu.png and b/OsmAnd/res/drawable-hdpi/poi_parking_pos_no_limit_menu.png differ diff --git a/OsmAnd/res/drawable/parking_limit_button.xml b/OsmAnd/res/drawable/parking_limit_button.xml new file mode 100644 index 0000000000..d5d2a6adf5 --- /dev/null +++ b/OsmAnd/res/drawable/parking_limit_button.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/drawable/parking_no_limit_button.xml b/OsmAnd/res/drawable/parking_no_limit_button.xml new file mode 100644 index 0000000000..1cb787b27f --- /dev/null +++ b/OsmAnd/res/drawable/parking_no_limit_button.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/parking_set_time_limit.xml b/OsmAnd/res/layout/parking_set_time_limit.xml new file mode 100644 index 0000000000..3088730631 --- /dev/null +++ b/OsmAnd/res/layout/parking_set_time_limit.xml @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/parking_set_type.xml b/OsmAnd/res/layout/parking_set_type.xml new file mode 100644 index 0000000000..32f253d492 --- /dev/null +++ b/OsmAnd/res/layout/parking_set_type.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index df1bb69cf0..da23969330 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -1,4 +1,4 @@ - + + Pick up the car from parking + Warning + Notification to pick up your car was previously added to your Calendar. It will remain there until you will delete it manually. + Set the time limit of parking + Do you want to remove the location of the parked car? + Delete a parking marker + Choose the type of parking + Time-limited + Time-unlimited + Add a notification to Calendar application + Time-limited parking + Time-unlimited parking + The position of your parked car. %1$s + To pick up the car at: + PM + AM + Parking point + This plugin allows to store the location of your parked car. + Parking Position Plugin + Mark as a parking position + Delete a parking marker + Public Identifiable Trackable diff --git a/OsmAnd/src/net/osmand/plus/OptionsMenuHelper.java b/OsmAnd/src/net/osmand/plus/OptionsMenuHelper.java new file mode 100644 index 0000000000..e6276657e8 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/OptionsMenuHelper.java @@ -0,0 +1,32 @@ +package net.osmand.plus; + +import android.view.Menu; + +public class OptionsMenuHelper { + + private final Menu menu; + + public OptionsMenuHelper(Menu menu) { + this.menu = menu; + } + + public void registerOptionsMenuItem(int resItemId, int resName, int resIcon, boolean visibility) { + if (resIcon != -1) { + menu.add(Menu.CATEGORY_CONTAINER, resItemId, Menu.NONE, resName).setVisible(visibility).setIcon(resIcon); + } else { + menu.add(Menu.CATEGORY_CONTAINER, resItemId, Menu.NONE, resName).setVisible(visibility); + } + } + + public void registerOptionsMenuItem(int resItemId, int resName, int resIcon) { + registerOptionsMenuItem(resItemId, resName, resIcon, true); + } + + public void registerOptionsMenuItem(int resItemId, int resName, boolean visibility) { + registerOptionsMenuItem(resItemId, resName, -1, visibility); + } + + public void registerOptionsMenuItem(int resItemId, int resName) { + registerOptionsMenuItem(resItemId, resName, -1, true); + } +} diff --git a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java index 8c1c504cd2..4aca31e008 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java @@ -5,10 +5,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.apache.commons.logging.Log; - -import android.preference.PreferenceScreen; - import net.osmand.LogUtil; import net.osmand.access.AccessibilityPlugin; import net.osmand.plus.activities.MapActivity; @@ -18,9 +14,15 @@ import net.osmand.plus.development.OsmandDevelopmentPlugin; import net.osmand.plus.extrasettings.OsmandExtraSettings; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin; +import net.osmand.plus.parkingpoint.ParkingPositionPlugin; import net.osmand.plus.rastermaps.OsmandRasterMapsPlugin; import net.osmand.plus.views.OsmandMapTileView; +import org.apache.commons.logging.Log; + +import android.preference.PreferenceScreen; +import android.view.Menu; + public abstract class OsmandPlugin { private static List installedPlugins = new ArrayList(); @@ -56,6 +58,7 @@ public abstract class OsmandPlugin { installedPlugins.add(new AccessibilityPlugin(app)); installedPlugins.add(new OsmEditingPlugin(app)); installedPlugins.add(new OsmandDevelopmentPlugin(app)); + installedPlugins.add(new ParkingPositionPlugin(app)); Set enabledPlugins = settings.getEnabledPlugins(); for (OsmandPlugin plugin : installedPlugins) { @@ -107,6 +110,12 @@ public abstract class OsmandPlugin { public void registerMapContextMenuActions(MapActivity mapActivity, double latitude, double longitude, ContextMenuAdapter adapter, Object selectedObj) {} + public void registerOptionsMenuItems(MapActivity mapActivity, OptionsMenuHelper helper) {} + + public void prepareOptionsMenuItems(MapActivity mapActivity, Menu menu) {} + + public boolean onOptionsItemSelected(MapActivity mapActivity, int itemId) { return false; } + public static void refreshLayers(OsmandMapTileView mapView, MapActivity activity) { for (OsmandPlugin plugin : activePlugins) { plugin.updateLayers(mapView, activity); @@ -192,5 +201,26 @@ public abstract class OsmandPlugin { plugin.registerLayerContextMenuActions(mapView, adapter, mapActivity); } } + + public static void registerOptionsMenu(MapActivity map, OptionsMenuHelper helper) { + for (OsmandPlugin plugin : activePlugins) { + plugin.registerOptionsMenuItems(map, helper); + } + } + + public static void registerOnPrepareOptionsMenu(MapActivity mapActivity, Menu menu) { + for (OsmandPlugin plugin : activePlugins) { + plugin.prepareOptionsMenuItems(mapActivity, menu); + } + } + + public static boolean registerOnOptionsMenuItemSelected(MapActivity mapActivity, int itemId) { + for (OsmandPlugin plugin : activePlugins) { + if (plugin.onOptionsItemSelected(mapActivity, itemId)) { + return true; + } + } + return false; + } } diff --git a/OsmAnd/src/net/osmand/plus/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/OsmandSettings.java index 083964a46f..aa9bea02c5 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/OsmandSettings.java @@ -950,6 +950,60 @@ public class OsmandSettings { return add; } + + /** + * the location of a parked car + */ + public final static String PARKING_POINT_LAT = "parking_point_lat"; //$NON-NLS-1$ + public final static String PARKING_POINT_LON = "parking_point_lon"; //$NON-NLS-1$ + public final static String PARKING_TYPE = "parking_type"; //$NON-NLS-1$ + public final static String PARKING_TIME = "parking_limit_time"; //$//$NON-NLS-1$ + public final static String PARKING_EVENT_ADDED = "parking_event_added"; //$//$NON-NLS-1$ + + public LatLon getParkingPosition() { + float lat = globalPreferences.getFloat(PARKING_POINT_LAT, 0); + float lon = globalPreferences.getFloat(PARKING_POINT_LON, 0); + if (lat == 0 && lon == 0) { + return null; + } + return new LatLon(lat, lon); + } + + public boolean getParkingType() { + return globalPreferences.getBoolean(PARKING_TYPE, false); + } + + public boolean isParkingEventAdded() { + return globalPreferences.getBoolean(PARKING_EVENT_ADDED, false); + } + + public boolean addOrRemoveParkingEvent(boolean added) { + return globalPreferences.edit().putBoolean(PARKING_EVENT_ADDED, added).commit(); + } + + public long getParkingTime() { + return globalPreferences.getLong(PARKING_TIME, -1); + } + + public boolean clearParkingPosition() { + return globalPreferences.edit().remove(PARKING_POINT_LAT).remove(PARKING_POINT_LON).remove(PARKING_TYPE) + .remove(PARKING_TIME).remove(PARKING_EVENT_ADDED).commit(); + } + + public boolean setParkingPosition(double latitude, double longitude) { + return globalPreferences.edit().putFloat(PARKING_POINT_LAT, (float) latitude).putFloat(PARKING_POINT_LON, (float) longitude).commit(); + } + + public boolean setParkingType(boolean limited) { + if (!limited) + globalPreferences.edit().remove(PARKING_TIME).commit(); + return globalPreferences.edit().putBoolean(PARKING_TYPE, limited).commit(); + } + + public boolean setParkingTime(long timeInMillis) { + return globalPreferences.edit().putLong(PARKING_TIME, timeInMillis).commit(); + } + public static final String LAST_SEARCHED_REGION = "last_searched_region"; //$NON-NLS-1$ public static final String LAST_SEARCHED_CITY = "last_searched_city"; //$NON-NLS-1$ public static final String LAST_SEARCHED_CITY_NAME = "last_searched_city_name"; //$NON-NLS-1$ diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index cad9c302d3..61b1d7afb3 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -20,7 +20,6 @@ import net.osmand.map.IMapLocationListener; import net.osmand.osm.LatLon; import net.osmand.osm.MapUtils; import net.osmand.plus.BusyIndicator; -import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.FavouritesDbHelper; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; @@ -35,20 +34,15 @@ import net.osmand.plus.views.AnimateDraggingMapThread; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.PointLocationLayer; import android.app.Activity; -import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.ProgressDialog; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.hardware.Sensor; @@ -67,12 +61,10 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; -import android.provider.Settings.Secure; import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; -import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; @@ -84,9 +76,6 @@ import android.view.animation.Transformation; import android.widget.Toast; public class MapActivity extends AccessibleActivity implements IMapLocationListener, SensorEventListener { - - private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2.GPSStatus"; //$NON-NLS-1$ - private static final String GPS_STATUS_COMPONENT = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$ // stupid error but anyway hero 2.1 : always lost gps signal (temporarily unavailable) for timeout = 2000 private static final int GPS_TIMEOUT_REQUEST = 0; @@ -591,31 +580,6 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe } } - private void whereAmIDialog() { - final List items = new ArrayList(); - items.add(getString(R.string.show_location)); - items.add(getString(R.string.show_details)); - AlertDialog.Builder menu = new AlertDialog.Builder(this); - menu.setItems(items.toArray(new String[items.size()]), - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int item) { - dialog.dismiss(); - switch (item) { - case 0: - backToLocationImpl(); - break; - case 1: - navigationInfo.show(settings.getPointToNavigate(), mapLayers.getLocationLayer().getHeading()); - break; - default: - break; - } - } - }); - menu.show(); - } - public void setMapLocation(double lat, double lon){ mapView.setLatLon(lat, lon); locationChanged(lat, lon, this); @@ -1061,10 +1025,10 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe //return true; } else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { if (!getMyApplication().accessibilityEnabled()) { - contextMenuPoint(mapView.getLatitude(), mapView.getLongitude()); + mapActions.contextMenuPoint(mapView.getLatitude(), mapView.getLongitude()); } else if (uiHandler.hasMessages(LONG_KEYPRESS_MSG_ID)) { uiHandler.removeMessages(LONG_KEYPRESS_MSG_ID); - contextMenuPoint(mapView.getLatitude(), mapView.getLongitude()); + mapActions.contextMenuPoint(mapView.getLatitude(), mapView.getLongitude()); } return true; } else if (settings.ZOOM_BY_TRACKBALL.get()) { @@ -1151,162 +1115,22 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe } } - + @Override public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.map_menu, menu); - return true; + return mapActions.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { boolean val = super.onPrepareOptionsMenu(menu); - MenuItem navigateToPointMenu = menu.findItem(R.id.map_navigate_to_point); - if (navigateToPointMenu != null) { - if (settings.getPointToNavigate() != null) { - navigateToPointMenu.setTitle((routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || routingHelper.isRouteBeingCalculated()) ? R.string.stop_routing : R.string.stop_navigation); - navigateToPointMenu.setVisible(true); - } else { - navigateToPointMenu.setVisible(false); - } - } - MenuItem muteMenu = menu.findItem(R.id.map_mute); - if(muteMenu != null){ - if (routingHelper.getFinalLocation() != null && routingHelper.isFollowingMode()) { - muteMenu.setTitle(routingHelper.getVoiceRouter().isMute() ? R.string.menu_mute_on : R.string.menu_mute_off); - muteMenu.setVisible(true); - } else { - muteMenu.setVisible(false); - } - } - MenuItem directions = menu.findItem(R.id.map_get_directions); - if(routingHelper.isRouteCalculated()){ - directions.setTitle(R.string.show_route); - } else { - directions.setTitle(R.string.get_directions); - } - - MenuItem animateMenu = menu.findItem(R.id.map_animate_route); - - if (animateMenu != null) { - if(settings.TEST_ANIMATE_ROUTING.get()){ - animateMenu.setTitle(routeAnimation.isRouteAnimating() ? R.string.animate_route_off - : R.string.animate_route); - animateMenu.setVisible("1".equals(Secure.getString( - getContentResolver(), Secure.ALLOW_MOCK_LOCATION)) - && settings.getPointToNavigate() != null - && routingHelper.isRouteCalculated()); - animateMenu.setVisible(true); - } else { - animateMenu.setVisible(false); - } - } + mapActions.onPrepareOptionsMenu(menu); return val; } @Override public boolean onOptionsItemSelected(MenuItem item) { - final int itemId = item.getItemId(); - if (itemId == R.id.map_show_settings) { - final Intent intentSettings = new Intent(MapActivity.this, OsmandIntents.getSettingsActivity()); - startActivity(intentSettings); - return true; - } else if (itemId == R.id.map_where_am_i) { - if (getMyApplication().accessibilityEnabled()) { - whereAmIDialog(); - } else { - backToLocationImpl(); - } - return true; - } else if (itemId == R.id.map_show_gps_status) { - startGpsStatusIntent(); - return true; - } else if (itemId == R.id.map_specify_point) { - Intent newIntent = new Intent(this, OsmandIntents.getSearchActivity()); - // causes wrong position caching: newIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - LatLon loc = getMapLocation(); - newIntent.putExtra(SearchActivity.SEARCH_LAT, loc.getLatitude()); - newIntent.putExtra(SearchActivity.SEARCH_LON, loc.getLongitude()); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(newIntent); - return true; - } else if (itemId == R.id.map_get_directions) { - if (routingHelper.isRouteCalculated()) { - mapActions.aboutRoute(); - } else { - Location loc = getLastKnownLocation(); - if (loc != null) { - mapActions.getDirections(loc.getLatitude(), loc.getLongitude(), true); - } else { - mapActions.getDirections(mapView.getLatitude(), mapView.getLongitude(), true); - } - } - return true; - } else if (itemId == R.id.map_layers) { - mapLayers.openLayerSelectionDialog(mapView); - return true; - } else if (itemId == R.id.map_mute) { - routingHelper.getVoiceRouter().setMute(!routingHelper.getVoiceRouter().isMute()); - return true; - } else if (itemId == R.id.map_navigate_to_point) { - if (mapLayers.getNavigationLayer().getPointToNavigate() != null) { - if (routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || routingHelper.isRouteBeingCalculated()) { - routingHelper.setFinalAndCurrentLocation(null, routingHelper.getCurrentLocation(), routingHelper.getCurrentGPXRoute()); - // restore default mode - boolean changed = settings.APPLICATION_MODE.set(settings.PREV_APPLICATION_MODE.get()); - updateApplicationModeSettings(); - mapView.refreshMap(changed); - } else { - navigateToPoint(null); - } - } else { - navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude())); - } - mapView.refreshMap(); - return true; - } else if (itemId == R.id.map_show_point_options) { - contextMenuPoint(mapView.getLatitude(), mapView.getLongitude()); - return true; - } else if (itemId == R.id.map_animate_route) { - // animate moving on route - routeAnimation.startStopRouteAnimation(routingHelper, this); - return true; - } else { - return super.onOptionsItemSelected(item); - } - } - - private void startGpsStatusIntent() { - Intent intent = new Intent(); - intent.setComponent(new ComponentName(GPS_STATUS_COMPONENT, - GPS_STATUS_ACTIVITY)); - ResolveInfo resolved = getPackageManager().resolveActivity(intent, - PackageManager.MATCH_DEFAULT_ONLY); - if (resolved != null) { - startActivity(intent); - } else { - AlertDialog.Builder builder = new AccessibleAlertBuilder(this); - builder.setMessage(getString(R.string.gps_status_app_not_found)); - 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)); - try { - startActivity(intent); - } catch (ActivityNotFoundException e) { - } - } - }); - builder.setNegativeButton( - getString(R.string.default_buttons_no), null); - builder.show(); - } + return mapActions.onOptionsItemSelected(item) == true ? true : super.onOptionsItemSelected(item); } @@ -1338,15 +1162,6 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe return getMyApplication().getFavorites(); } - - public void contextMenuPoint(final double latitude, final double longitude){ - mapActions.contextMenuPoint(latitude, longitude, null, null); - } - - public void contextMenuPoint(final double latitude, final double longitude, ContextMenuAdapter adapter, Object selectedObj) { - mapActions.contextMenuPoint(latitude, longitude, adapter, selectedObj); - } - public MapActivityActions getMapActions() { return mapActions; } @@ -1400,4 +1215,8 @@ public class MapActivity extends AccessibleActivity implements IMapLocationListe uiHandler.sendMessageDelayed(msg, delay * 1000); } + public NavigationInfo getNavigationInfo() { + return navigationInfo; + } + } diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java index e3c5d4d091..afc8396e7b 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivityActions.java @@ -25,12 +25,14 @@ import net.osmand.plus.AmenityIndexRepositoryOdb; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick; import net.osmand.plus.FavouritesDbHelper; +import net.osmand.plus.OptionsMenuHelper; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.ResourceManager; import net.osmand.plus.activities.search.SearchActivity; +import net.osmand.plus.routing.RouteAnimation; import net.osmand.plus.routing.RouteProvider.GPXRouteParams; import net.osmand.plus.routing.RoutingHelper; import net.osmand.plus.views.BaseMapLayer; @@ -41,19 +43,27 @@ import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.ProgressDialog; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; import android.content.DialogInterface; import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Rect; import android.graphics.RectF; import android.location.Location; +import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.provider.Settings.Secure; import android.text.ClipboardManager; import android.text.Html; import android.util.FloatMath; import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -70,6 +80,9 @@ import android.widget.ToggleButton; public class MapActivityActions implements DialogProvider { + private static final String GPS_STATUS_COMPONENT = "com.eclipsim.gpsstatus2"; //$NON-NLS-1$ + private static final String GPS_STATUS_ACTIVITY = "com.eclipsim.gpsstatus2.GPSStatus"; //$NON-NLS-1$ + private static final String KEY_LONGITUDE = "longitude"; private static final String KEY_LATITUDE = "latitude"; private static final String KEY_NAME = "name"; @@ -86,10 +99,13 @@ public class MapActivityActions implements DialogProvider { private final MapActivity mapActivity; private OsmandSettings settings; + private RoutingHelper routingHelper; + private RouteAnimation routeAnimation = new RouteAnimation(); public MapActivityActions(MapActivity mapActivity){ this.mapActivity = mapActivity; settings = mapActivity.getMyApplication().getSettings(); + routingHelper = mapActivity.getMyApplication().getRoutingHelper(); } protected void addFavouritePoint(final double latitude, final double longitude){ @@ -738,6 +754,10 @@ public class MapActivityActions implements DialogProvider { builder.create().show(); } + public void contextMenuPoint(final double latitude, final double longitude){ + contextMenuPoint(latitude, longitude, null, null); + } + private Dialog createReloadTitleDialog(final Bundle args) { Builder builder = new AccessibleAlertBuilder(mapActivity); builder.setMessage(R.string.context_menu_item_update_map_confirm); @@ -825,5 +845,199 @@ public class MapActivityActions implements DialogProvider { break; } } + + public boolean onCreateOptionsMenu(Menu menu) { +// NOTE: delete not a "menu.xml" because all id-resources are generated to R-class from there + OptionsMenuHelper helper = new OptionsMenuHelper(menu); + helper.registerOptionsMenuItem(R.id.map_where_am_i, R.string.where_am_i, android.R.drawable.ic_menu_mylocation); + helper.registerOptionsMenuItem(R.id.map_layers, R.string.menu_layers, android.R.drawable.ic_menu_mapmode); + helper.registerOptionsMenuItem(R.id.map_show_settings, R.string.settings_Button, android.R.drawable.ic_menu_preferences); + helper.registerOptionsMenuItem(R.id.map_navigate_to_point, R.string.stop_navigation, android.R.drawable.ic_menu_close_clear_cancel, false); + helper.registerOptionsMenuItem(R.id.map_mute, R.string.menu_mute_off, false); + helper.registerOptionsMenuItem(R.id.map_animate_route, R.string.animate_route, false); + helper.registerOptionsMenuItem(R.id.map_get_directions, R.string.get_directions, android.R.drawable.ic_menu_directions); + helper.registerOptionsMenuItem(R.id.map_specify_point, R.string.search_button, android.R.drawable.ic_menu_search); + helper.registerOptionsMenuItem(R.id.map_show_gps_status, R.string.show_gps_status, android.R.drawable.ic_menu_compass); + helper.registerOptionsMenuItem(R.id.map_show_point_options, R.string.show_point_options); + OsmandPlugin.registerOptionsMenu(mapActivity, helper); + return true; + } + + public void onPrepareOptionsMenu(Menu menu) { + MenuItem navigateToPointMenu = menu.findItem(R.id.map_navigate_to_point); + if (navigateToPointMenu != null) { + if (settings.getPointToNavigate() != null) { + navigateToPointMenu.setTitle((routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || + routingHelper.isRouteBeingCalculated()) ? R.string.stop_routing : R.string.stop_navigation); + navigateToPointMenu.setVisible(true); + } else { + navigateToPointMenu.setVisible(false); + } + } + MenuItem muteMenu = menu.findItem(R.id.map_mute); + if(muteMenu != null){ + if (routingHelper.getFinalLocation() != null && routingHelper.isFollowingMode()) { + muteMenu.setTitle(routingHelper.getVoiceRouter().isMute() ? R.string.menu_mute_on : R.string.menu_mute_off); + muteMenu.setVisible(true); + } else { + muteMenu.setVisible(false); + } + } + MenuItem directions = menu.findItem(R.id.map_get_directions); + if(routingHelper.isRouteCalculated()){ + directions.setTitle(R.string.show_route); + } else { + directions.setTitle(R.string.get_directions); + } + + MenuItem animateMenu = menu.findItem(R.id.map_animate_route); + + if (animateMenu != null) { + if(settings.TEST_ANIMATE_ROUTING.get()){ + animateMenu.setTitle(routeAnimation.isRouteAnimating() ? R.string.animate_route_off + : R.string.animate_route); + animateMenu.setVisible("1".equals(Secure.getString( + mapActivity.getContentResolver(), Secure.ALLOW_MOCK_LOCATION)) + && settings.getPointToNavigate() != null + && routingHelper.isRouteCalculated()); + animateMenu.setVisible(true); + } else { + animateMenu.setVisible(false); + } + } + + OsmandPlugin.registerOnPrepareOptionsMenu(mapActivity, menu); + } + + public boolean onOptionsItemSelected(MenuItem item) { + final int itemId = item.getItemId(); + OsmandMapTileView mapView = mapActivity.getMapView(); + if (itemId == R.id.map_show_settings) { + final Intent intentSettings = new Intent(mapActivity, OsmandIntents.getSettingsActivity()); + mapActivity.startActivity(intentSettings); + return true; + } else if (itemId == R.id.map_where_am_i) { + if (getMyApplication().accessibilityEnabled()) { + whereAmIDialog(); + } else { + mapActivity.backToLocationImpl(); + } + return true; + } else if (itemId == R.id.map_show_gps_status) { + startGpsStatusIntent(); + return true; + } else if (itemId == R.id.map_specify_point) { + Intent newIntent = new Intent(mapActivity, OsmandIntents.getSearchActivity()); + // causes wrong position caching: newIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + LatLon loc = mapActivity.getMapLocation(); + newIntent.putExtra(SearchActivity.SEARCH_LAT, loc.getLatitude()); + newIntent.putExtra(SearchActivity.SEARCH_LON, loc.getLongitude()); + newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + mapActivity.startActivity(newIntent); + return true; + } else { + if (itemId == R.id.map_get_directions) { + if (routingHelper.isRouteCalculated()) { + aboutRoute(); + } else { + Location loc = mapActivity.getLastKnownLocation(); + if (loc != null) { + getDirections(loc.getLatitude(), loc.getLongitude(), true); + } else { + getDirections(mapView.getLatitude(), mapView.getLongitude(), true); + } + } + return true; + } else if (itemId == R.id.map_layers) { + mapActivity.getMapLayers().openLayerSelectionDialog(mapView); + return true; + } else if (itemId == R.id.map_mute) { + routingHelper.getVoiceRouter().setMute(!routingHelper.getVoiceRouter().isMute()); + return true; + } else if (itemId == R.id.map_navigate_to_point) { + if (mapActivity.getMapLayers().getNavigationLayer().getPointToNavigate() != null) { + if (routingHelper.isRouteCalculated() || routingHelper.isFollowingMode() || routingHelper.isRouteBeingCalculated()) { + routingHelper.setFinalAndCurrentLocation(null, routingHelper.getCurrentLocation(), routingHelper.getCurrentGPXRoute()); + // restore default mode + boolean changed = settings.APPLICATION_MODE.set(settings.PREV_APPLICATION_MODE.get()); + mapActivity.updateApplicationModeSettings(); + mapView.refreshMap(changed); + } else { + mapActivity.navigateToPoint(null); + } + } else { + mapActivity.navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude())); + } + mapView.refreshMap(); + return true; + } else if (itemId == R.id.map_show_point_options) { + contextMenuPoint(mapView.getLatitude(), mapView.getLongitude()); + return true; + } else if (itemId == R.id.map_animate_route) { + // animate moving on route + routeAnimation.startStopRouteAnimation(routingHelper, mapActivity); + return true; + } else { + return OsmandPlugin.registerOnOptionsMenuItemSelected(mapActivity, itemId); + } + } + } + private void startGpsStatusIntent() { + Intent intent = new Intent(); + intent.setComponent(new ComponentName(GPS_STATUS_COMPONENT, + GPS_STATUS_ACTIVITY)); + ResolveInfo resolved = mapActivity.getPackageManager().resolveActivity(intent, + PackageManager.MATCH_DEFAULT_ONLY); + if (resolved != null) { + mapActivity.startActivity(intent); + } 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() { + @Override + 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) { + } + } + }); + builder.setNegativeButton( + getString(R.string.default_buttons_no), null); + builder.show(); + } + } + + private void whereAmIDialog() { + final List items = new ArrayList(); + items.add(getString(R.string.show_location)); + items.add(getString(R.string.show_details)); + AlertDialog.Builder menu = new AlertDialog.Builder(mapActivity); + menu.setItems(items.toArray(new String[items.size()]), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int item) { + dialog.dismiss(); + switch (item) { + case 0: + mapActivity.backToLocationImpl(); + break; + case 1: + mapActivity.getNavigationInfo().show(settings.getPointToNavigate(), mapActivity.getMapLayers(). + getLocationLayer().getHeading()); + break; + default: + break; + } + } + }); + menu.show(); + } } diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java new file mode 100644 index 0000000000..3b6bf6c9c5 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionLayer.java @@ -0,0 +1,301 @@ +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; + +/** + * Class represents a layer which depicts the position of the parked car + * @author Alena Fedasenka + * @see ParkingPositionPlugin + * + */ +public class ParkingPositionLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider { + /** + * magic number so far + */ + private static final int radius = 20; + + private LatLon parkingPoint = null; + + private DisplayMetrics dm; + + private final MapActivity map; + private OsmandMapTileView view; + 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; + } + + @Override + public void initLayer(OsmandMapTileView view) { + this.view = view; + this.settings = ((OsmandApplication) map.getApplication()).getSettings(); + parkingPoint = settings.getParkingPosition(); + dm = new DisplayMetrics(); + 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); + bitmapPaint.setFilterBitmap(true); + 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 + public void onDraw(Canvas canvas, RectF latLonBounds, RectF tilesRect, DrawSettings nightMode) { +// settings.clearParkingPosition(); + parkingPoint = settings.getParkingPosition(); + if (parkingPoint == null) + return; + timeLimit = settings.getParkingType(); + Bitmap parkingIcon; + if (!timeLimit) { + parkingIcon = parkingNoLimitIcon; + } else { + parkingIcon = parkingLimitIcon; + } + double latitude = parkingPoint.getLatitude(); + double longitude = parkingPoint.getLongitude(); + if (isLocationVisible(latitude, longitude)) { + int marginX = parkingNoLimitIcon.getWidth() / 2; +// TODO tune y + int marginY = 72;//magic number! + int locationX = view.getMapXForPoint(longitude); + int locationY = view.getMapYForPoint(latitude); + canvas.rotate(-view.getRotate(), locationX, locationY); + canvas.drawBitmap(parkingIcon, locationX - marginX, locationY - marginY, bitmapPaint); + } + } + + @Override + public boolean onSingleTap(PointF point) { + List parkPos = new ArrayList(); + getParkingFromPoint(point, parkPos); + if(!parkPos.isEmpty()){ + StringBuilder res = new StringBuilder(); + res.append(view.getContext().getString(R.string.osmand_parking_position_description)); + AccessibleToast.makeText(view.getContext(), getObjectDescription(null), Toast.LENGTH_LONG).show(); + return true; + } + return false; + } + + @Override + public void destroyLayer() { + } + + @Override + public boolean drawInScreenPixels() { + return false; + } + + @Override + public void collectObjectsFromPoint(PointF point, List o) { + getParkingFromPoint(point, o); + } + + @Override + public LatLon getObjectLocation(Object o) { + return parkingPoint; + } + + @Override + public String getObjectDescription(Object o) { + StringBuilder timeLimitDesc = new StringBuilder(); + if (settings.getParkingType()) { + long parkingTime = settings.getParkingTime(); + Time time = new Time(); + time.set(parkingTime); + timeLimitDesc.append(map.getString(R.string.osmand_parking_position_description_add)); + timeLimitDesc.append(time.hour); + timeLimitDesc.append(":"); + timeLimitDesc.append(time.minute); + if (!DateFormat.is24HourFormat(map.getApplicationContext())) { + timeLimitDesc.append(time.hour >= 12 ? map.getString(R.string.osmand_parking_pm) : map.getString(R.string.osmand_parking_am)); + } + } + return map.getString(R.string.osmand_parking_position_description, timeLimitDesc.toString()); + } + + @Override + public String getObjectName(Object o) { + return view.getContext().getString(R.string.osmand_parking_position_name); + } + + public void setParkingPointOnLayer(LatLon point) { + this.parkingPoint = point; + if (view != null && view.getLayers().contains(ParkingPositionLayer.this)) { + view.refreshMap(); + } + } + + /** + * @param latitude + * @param longitude + * @return true if the parking point is located on a visible part of map + */ + private boolean isLocationVisible(double latitude, double longitude){ + if(parkingPoint == null || view == null){ + return false; + } + return view.isPointOnTheRotatedMap(latitude, longitude); + } + + /** + * @param point + * @param parkingPosition is in this case not necessarily has to be a list, + * but it's also used in method collectObjectsFromPoint(PointF point, List o) + */ + private void getParkingFromPoint(PointF point, List parkingPosition) { + if (parkingPoint != null && view != null) { + int ex = (int) point.x; + int ey = (int) point.y; + LatLon position = settings.getParkingPosition(); + int x = view.getRotatedMapXForPoint(position.getLatitude(), position.getLongitude()); + int y = view.getRotatedMapYForPoint(position.getLatitude(), position.getLongitude()); + //the width of an image is 40 px, the height is 60 px -> radius = 20, + //the position of a parking point relatively to the icon is at the center of the bottom line of the image + if (Math.abs(x - ex) <= radius && ((y - ey) <= radius*3) && ((y - ey) >= 0)) { + parkingPosition.add(parkingPoint); + } + } + } + + /** + * @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) { + int d = 0; + if (map.getRoutingHelper().isRouterEnabled()) { + d = map.getRoutingHelper().getLeftDistance(); + } + 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) { + int fZoom = view.getZoom() < 15 ? 15 : view.getZoom(); + 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; + } + +} diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java new file mode 100644 index 0000000000..1a620f5ea4 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionPlugin.java @@ -0,0 +1,305 @@ +package net.osmand.plus.parkingpoint; + +import java.util.Calendar; + +import net.osmand.osm.LatLon; +import net.osmand.plus.ContextMenuAdapter; +import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick; +import net.osmand.plus.OptionsMenuHelper; +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.MapActivity; +import net.osmand.plus.views.OsmandMapTileView; +import android.app.AlertDialog; +import android.app.AlertDialog.Builder; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.text.format.DateFormat; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.CheckBox; +import android.widget.ImageButton; +import android.widget.TimePicker; + +/** + * + * The plugin facilitates a storage of the location of a parked car. + * + * @author Alena Fedasenka + */ +public class ParkingPositionPlugin extends OsmandPlugin { + + private static final String ID = "osmand.parking.position"; + private OsmandApplication app; + + private ParkingPositionLayer parkingLayer; + private OsmandSettings settings; + + public ParkingPositionPlugin(OsmandApplication app) { + this.app = app; + } + + @Override + public boolean init(OsmandApplication app) { + settings = app.getSettings(); + return true; + } + + @Override + public String getId() { + return ID; + } + + @Override + public String getDescription() { + return app.getString(R.string.osmand_parking_plugin_description); + } + + @Override + public String getName() { + return app.getString(R.string.osmand_parking_plugin_name); + } + + @Override + public void registerLayers(MapActivity activity) { + parkingLayer = new ParkingPositionLayer(activity); + } + + @Override + public void updateLayers(OsmandMapTileView mapView, MapActivity activity) { + if ((settings.getParkingPosition() == null) + && (mapView.getLayers().contains(parkingLayer))) { + mapView.removeLayer(parkingLayer); + } else { + if (parkingLayer == null) + registerLayers(activity); + mapView.addLayer(parkingLayer, 5); + } + } + + @Override + public void registerMapContextMenuActions(final MapActivity mapActivity, + final double latitude, final double longitude, + ContextMenuAdapter adapter, Object selectedObj) { + boolean isParkingSelected = false; + LatLon parkingPosition = settings.getParkingPosition(); + if (selectedObj instanceof LatLon && parkingLayer != null && parkingPosition != null) { + LatLon point = (LatLon)selectedObj; + if ((point.getLatitude() == parkingPosition.getLatitude()) && (point.getLongitude() == parkingPosition.getLongitude())) + isParkingSelected = true; + } + if (isParkingSelected) { + OnContextMenuClick removeListener = new OnContextMenuClick() { + @Override + public void onContextMenuClick(int resId, int pos, + boolean isChecked, DialogInterface dialog) { + if ((resId == R.string.context_menu_item_delete_parking_point)) { + showDeleteDialog(mapActivity); + } + } + }; + if (parkingPosition != null) + adapter.registerItem(R.string.context_menu_item_delete_parking_point, 0, removeListener, 0); + } + + OnContextMenuClick addListener = new OnContextMenuClick() { + @Override + public void onContextMenuClick(int resId, int pos, + boolean isChecked, DialogInterface dialog) { + if (resId == R.string.context_menu_item_add_parking_point) { + showAddParkingDialog(mapActivity, latitude, longitude); + } + } + }; + adapter.registerItem(R.string.context_menu_item_add_parking_point, 0, addListener, -1); + + } + + /** + * Method dialog for adding of a parking location. + * It allows user to choose a type of parking (time-limited or time-unlimited). + */ + private void showAddParkingDialog(final MapActivity mapActivity, final double latitude, final double longitude) { + final boolean wasEventPreviouslyAdded = settings.isParkingEventAdded(); + final View addParking = mapActivity.getLayoutInflater().inflate(R.layout.parking_set_type, null); + final Dialog choose = new Dialog(mapActivity); + choose.setContentView(addParking); + choose.setCancelable(true); + choose.setTitle(mapActivity.getString(R.string.osmand_parking_choose_type)); + + ImageButton limitButton = (ImageButton) addParking.findViewById(R.id.parking_lim_button); + limitButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (wasEventPreviouslyAdded) { + showDeleteEventWarning(mapActivity); + } + setParkingPosition(mapActivity, latitude, longitude, true); + showSetTimeLimitDialog(mapActivity, choose); + mapActivity.getMapView().refreshMap(); + } + }); + + ImageButton noLimitButton = (ImageButton) addParking.findViewById(R.id.parking_no_lim_button); + noLimitButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + choose.dismiss(); + if (wasEventPreviouslyAdded) { + showDeleteEventWarning(mapActivity); + } + settings.addOrRemoveParkingEvent(false); + setParkingPosition(mapActivity, latitude, longitude, false); + mapActivity.getMapView().refreshMap(); + } + }); + + choose.show(); + + } + + /** + * Method creates confirmation dialog for deletion of a parking location. + */ + private void showDeleteDialog(final MapActivity mapActivity) { + Builder confirm = new AlertDialog.Builder(mapActivity); + confirm.setTitle(mapActivity.getString(R.string.osmand_parking_delete)); + confirm.setMessage(mapActivity.getString(R.string.osmand_parking_delete_confirm)); + confirm.setCancelable(true); + confirm.setPositiveButton(R.string.default_buttons_yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + showDeleteEventWarning(mapActivity); + settings.clearParkingPosition(); + mapActivity.getMapView().refreshMap(); + } + }); + confirm.setNegativeButton(R.string.default_buttons_cancel, null); + confirm.show(); + } + + /** + * Opens the dialog to set a time limit for time-limited parking. + * The dialog has option to add a notification to Calendar app. + * Anyway the time-limit can be seen from parking point description. + * @param mapActivity + * @param choose + */ + private void showSetTimeLimitDialog(final MapActivity mapActivity, final Dialog choose) { + final View setTimeParking = mapActivity.getLayoutInflater().inflate(R.layout.parking_set_time_limit, null); + Builder setTime = new AlertDialog.Builder(mapActivity); + setTime.setView(setTimeParking); + setTime.setTitle(mapActivity.getString(R.string.osmand_parking_time_limit_title)); + setTime.setNegativeButton(R.string.default_buttons_cancel, null); + final TimePicker timePicker = (TimePicker) setTimeParking.findViewById(R.id.parking_time_picker); + + //to set the same 24-hour or 12-hour mode as it is set in the device + timePicker.setIs24HourView(true); + timePicker.setCurrentHour(0); + timePicker.setCurrentMinute(0); + + setTime.setPositiveButton(R.string.default_buttons_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + choose.dismiss(); + Calendar cal = Calendar.getInstance(); + boolean is24HourFormat = DateFormat.is24HourFormat(app); + int hour = cal.get( is24HourFormat? Calendar.HOUR_OF_DAY : Calendar.HOUR); + int minute = cal.get(Calendar.MINUTE); + cal.set(is24HourFormat? Calendar.HOUR_OF_DAY : Calendar.HOUR, hour + timePicker.getCurrentHour()); + cal.set(Calendar.MINUTE, minute + timePicker.getCurrentMinute()); + settings.setParkingTime(cal.getTimeInMillis()); + CheckBox addCalendarEvent = (CheckBox)setTimeParking.findViewById(R.id.check_event_in_calendar); + if (addCalendarEvent.isChecked()) { + addCalendarEvent(setTimeParking); + settings.addOrRemoveParkingEvent(true); + } else { + settings.addOrRemoveParkingEvent(false); + } + } + }); + setTime.create(); + setTime.show(); + } + + /** + * Opens a Calendar app with added notification to pick up the car from time-limited parking. + * @param view + */ + private void addCalendarEvent(View view) { + Intent intent = new Intent(Intent.ACTION_EDIT); + intent.setType("vnd.android.cursor.item/event"); //$NON-NLS-1$ + intent.putExtra("calendar_id", 1); //$NON-NLS-1$ + intent.putExtra("title", view.getContext().getString(R.string.osmand_parking_event)); //$NON-NLS-1$ + intent.putExtra("beginTime", settings.getParkingTime()); //$NON-NLS-1$ + intent.putExtra("endTime", settings.getParkingTime()+60*60*1000); //$NON-NLS-1$ + view.getContext().startActivity(intent); + } + + /** + * Method shows warning, if previously the event for time-limited parking was added to Calendar app. + * @param mapActivity + */ + private void showDeleteEventWarning(final MapActivity mapActivity) { + if (settings.isParkingEventAdded()) { + Builder deleteEventWarning = new AlertDialog.Builder(mapActivity); + deleteEventWarning.setTitle(mapActivity.getString(R.string.osmand_parking_warning)); + deleteEventWarning.setMessage(mapActivity.getString(R.string.osmand_parking_warning_text)); + deleteEventWarning.setNeutralButton(R.string.default_buttons_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); + deleteEventWarning.create(); + deleteEventWarning.show(); + } + } + + /** + * Method sets a parking point on a ParkingLayer. + * @param mapActivity + * @param latitude + * @param longitude + * @param isLimited + */ + private void setParkingPosition(final MapActivity mapActivity, final double latitude, final double longitude, boolean isLimited) { + settings.setParkingPosition(latitude, longitude); + settings.setParkingType(isLimited); + if (mapActivity.getMapView().getLayers().contains(parkingLayer)) { + parkingLayer.setParkingPointOnLayer(settings.getParkingPosition()); + } + } + + @Override + public void registerOptionsMenuItems(MapActivity mapActivity, OptionsMenuHelper helper) { + if (parkingLayer != null) { + //NOTE: R.id.parking_lim_text - is used just as a stub + helper.registerOptionsMenuItem(R.id.parking_lim_text, R.string.osmand_parking_delete, android.R.drawable.ic_menu_mylocation); + } + } + + @Override + public boolean onOptionsItemSelected(MapActivity mapActivity, int itemId) { + if (itemId == R.id.parking_lim_text) { + showDeleteDialog(mapActivity); + return true; + } + return false; + } + + @Override + public void prepareOptionsMenuItems(MapActivity mapActivity, Menu menu) { + MenuItem deleteParkingItem = menu.findItem(R.id.parking_lim_text); + if (deleteParkingItem != null) { + if (settings.getParkingPosition() != null) { + deleteParkingItem.setVisible(true); + } else { + deleteParkingItem.setVisible(false); + } + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java index 3077237ce5..cd882dbfba 100644 --- a/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/ContextMenuLayer.java @@ -276,7 +276,7 @@ public class ContextMenuLayer extends OsmandMapLayer { if (!selectedObjects.isEmpty()) { showContextMenuForSelectedObjects(); } else if (nativeMode) { - activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude()); + activity.getMapActions().contextMenuPoint(latLon.getLatitude(), latLon.getLongitude()); } return true; } @@ -299,7 +299,7 @@ public class ContextMenuLayer extends OsmandMapLayer { for(OsmandMapLayer layer : view.getLayers()) { layer.populateObjectContextMenu(selectedObj, menuAdapter); } - activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), menuAdapter, selectedObj); + activity.getMapActions().contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), menuAdapter, selectedObj); } }); builder.show(); @@ -308,7 +308,7 @@ public class ContextMenuLayer extends OsmandMapLayer { for(OsmandMapLayer layer : view.getLayers()) { layer.populateObjectContextMenu(selectedObj, menuAdapter); } - activity.contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), menuAdapter, selectedObj); + activity.getMapActions().contextMenuPoint(latLon.getLatitude(), latLon.getLongitude(), menuAdapter, selectedObj); } } diff --git a/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java b/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java index 9e78bd419d..e4479e4017 100644 --- a/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/MapInfoLayer.java @@ -688,5 +688,8 @@ public class MapInfoLayer extends OsmandMapLayer { statusBar.addView(backToLocation, params); return statusBar; } - + + public void addRightStack(MapInfoControl v){ + rightStack.addStackView(v); + } }