aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/maps/CGeoMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/maps/CGeoMap.java')
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java464
1 files changed, 279 insertions, 185 deletions
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 9bbf7af..42e41b1 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -4,8 +4,10 @@ import butterknife.ButterKnife;
import cgeo.geocaching.CacheListActivity;
import cgeo.geocaching.CgeoApplication;
+import cgeo.geocaching.CompassActivity;
import cgeo.geocaching.DataStore;
import cgeo.geocaching.Geocache;
+import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Waypoint;
@@ -15,13 +17,12 @@ import cgeo.geocaching.connector.gc.GCLogin;
import cgeo.geocaching.connector.gc.MapTokens;
import cgeo.geocaching.connector.gc.Tile;
import cgeo.geocaching.enumerations.CacheType;
-import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag;
import cgeo.geocaching.enumerations.WaypointType;
-import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.list.StoredList;
+import cgeo.geocaching.location.Geopoint;
+import cgeo.geocaching.location.Viewport;
import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
import cgeo.geocaching.maps.interfaces.MapActivityImpl;
@@ -31,13 +32,15 @@ import cgeo.geocaching.maps.interfaces.MapProvider;
import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
-import cgeo.geocaching.sensors.DirectionProvider;
+import cgeo.geocaching.network.AndroidBeam;
+import cgeo.geocaching.sensors.GeoData;
import cgeo.geocaching.sensors.GeoDirHandler;
-import cgeo.geocaching.sensors.IGeoData;
+import cgeo.geocaching.sensors.Sensors;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.ui.dialog.LiveMapInfoDialogBuilder;
import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.CancellableHandler;
+import cgeo.geocaching.utils.Formatter;
import cgeo.geocaching.utils.LeastRecentlyUsedSet;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.MapUtils;
@@ -45,6 +48,7 @@ import cgeo.geocaching.utils.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import rx.Subscription;
import rx.functions.Action0;
@@ -61,11 +65,13 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.location.Location;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
@@ -123,16 +129,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
private static final int UPDATE_PROGRESS = 0;
private static final int FINISHED_LOADING_DETAILS = 1;
- //Menu
- private static final String EXTRAS_GEOCODE = "geocode";
- private static final String EXTRAS_COORDS = "coords";
- private static final String EXTRAS_WPTTYPE = "wpttype";
- private static final String EXTRAS_MAPSTATE = "mapstate";
- private static final String EXTRAS_SEARCH = "search";
- private static final String EXTRAS_MAP_TITLE = "mapTitle";
- private static final String EXTRAS_MAP_MODE = "mapMode";
- private static final String EXTRAS_LIVE_ENABLED = "liveEnabled";
-
private static final String BUNDLE_MAP_SOURCE = "mapSource";
private static final String BUNDLE_MAP_STATE = "mapState";
private static final String BUNDLE_LIVE_ENABLED = "liveEnabled";
@@ -141,15 +137,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// Those are initialized in onCreate() and will never be null afterwards
private Resources res;
private Activity activity;
- private CgeoApplication app;
private MapItemFactory mapItemFactory;
private String mapTitle;
- private LeastRecentlyUsedSet<Geocache> caches;
+ final private LeastRecentlyUsedSet<Geocache> caches = new LeastRecentlyUsedSet<>(MAX_CACHES + DataStore.getAllCachesCount());
private MapViewImpl mapView;
private CachesOverlay overlayCaches;
private PositionAndScaleOverlay overlayPositionAndScale;
- final private GeoDirHandler geoDirUpdate;
+ final private GeoDirHandler geoDirUpdate = new UpdateLoc(this);
private SearchResult searchIntent = null;
private String geocodeIntent = null;
private Geopoint coordsIntent = null;
@@ -161,7 +156,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
private MapTokens tokens = null;
private boolean noMapTokenShowed = false;
// map status data
- private boolean followMyLocation = false;
+ private static boolean followMyLocation = true;
// threads
private Subscription loadTimer;
private LoadDetails loadDetailsThread = null;
@@ -191,19 +186,20 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
private boolean centered = false; // if map is already centered
private boolean alreadyCentered = false; // -""- for setting my location
private static final Set<String> dirtyCaches = new HashSet<>();
+ // flag for honeycomb special popup menu handling
+ private boolean honeycombMenu = false;
/**
* if live map is enabled, this is the minimum zoom level, independent of the stored setting
*/
private static final int MIN_LIVEMAP_ZOOM = 12;
// Thread pooling
- private static BlockingQueue<Runnable> displayQueue = new ArrayBlockingQueue<>(1);
- private static ThreadPoolExecutor displayExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, displayQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
- private static BlockingQueue<Runnable> downloadQueue = new ArrayBlockingQueue<>(1);
- private static ThreadPoolExecutor downloadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, downloadQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
- private static BlockingQueue<Runnable> loadQueue = new ArrayBlockingQueue<>(1);
-
- private static ThreadPoolExecutor loadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, loadQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
+ private static final BlockingQueue<Runnable> displayQueue = new ArrayBlockingQueue<>(1);
+ private static final ThreadPoolExecutor displayExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, displayQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
+ private static final BlockingQueue<Runnable> downloadQueue = new ArrayBlockingQueue<>(1);
+ private static final ThreadPoolExecutor downloadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, downloadQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
+ private static final BlockingQueue<Runnable> loadQueue = new ArrayBlockingQueue<>(1);
+ private static final ThreadPoolExecutor loadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, loadQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
// handlers
/** Updates the titles */
@@ -224,29 +220,9 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
switch (what) {
case UPDATE_TITLE:
- // set title
- final StringBuilder title = new StringBuilder();
-
- if (map.mapMode == MapMode.LIVE && map.isLiveEnabled) {
- title.append(map.res.getString(R.string.map_live));
- } else {
- title.append(map.mapTitle);
- }
-
- map.countVisibleCaches();
- if (!map.caches.isEmpty() && !map.mapTitle.contains("[")) {
- title.append(" [").append(map.cachesCnt);
- if (map.cachesCnt != map.caches.size()) {
- title.append('/').append(map.caches.size());
- }
- title.append(']');
- }
+ map.setTitle();
+ map.setSubtitle();
- if (Settings.isDebug() && map.lastSearchResult != null && StringUtils.isNotBlank(map.lastSearchResult.getUrl())) {
- title.append('[').append(map.lastSearchResult.getUrl()).append(']');
- }
-
- map.setTitle(title.toString());
break;
case INVALIDATE_MAP:
map.mapView.repaintRequired(null);
@@ -261,7 +237,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
final private Handler displayHandler = new DisplayHandler(this);
- private void setTitle(final String title) {
+ private void setTitle() {
+ final String title = calculateTitle();
/* Compatibility for the old Action Bar, only used by the maps activity at the moment */
final TextView titleview = ButterKnife.findById(activity, R.id.actionbar_title);
if (titleview != null) {
@@ -273,10 +250,84 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
}
+ private String calculateTitle() {
+ if (isLiveEnabled) {
+ return res.getString(R.string.map_live);
+ }
+ if (mapMode == MapMode.SINGLE) {
+ final Geocache cache = getSingleModeCache();
+ if (cache != null) {
+ return cache.getName();
+ }
+ }
+ return StringUtils.defaultIfEmpty(mapTitle, res.getString(R.string.map_map));
+ }
+
+ @Nullable
+ private Geocache getSingleModeCache() {
+ // use a copy of the caches list to avoid concurrent modification
+ for (final Geocache geocache : new ArrayList<>(caches)) {
+ if (geocache.getGeocode().equals(geocodeIntent)) {
+ return geocache;
+ }
+ }
+ return null;
+ }
+
+ private void setSubtitle() {
+ final String subtitle = calculateSubtitle();
+ if (StringUtils.isEmpty(subtitle)) {
+ return;
+ }
+
+ /* Compatibility for the old Action Bar, only used by the maps activity at the moment */
+ final TextView titleView = ButterKnife.findById(activity, R.id.actionbar_title);
+ if (titleView != null) {
+ titleView.setText(titleView.getText().toString() + ' ' + subtitle);
+ }
+ if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)) {
+ setSubtitleIceCreamSandwich(subtitle);
+ }
+ }
+
+ private String calculateSubtitle() {
+ // count caches in the sub title
+ countVisibleCaches();
+ final StringBuilder subtitle = new StringBuilder();
+ if (!isLiveEnabled && mapMode == MapMode.SINGLE) {
+ final Geocache cache = getSingleModeCache();
+ if (cache != null) {
+ return Formatter.formatMapSubtitle(cache);
+ }
+ }
+ if (!caches.isEmpty()) {
+ final int totalCount = caches.size();
+
+ if (cachesCnt != totalCount && Settings.isDebug()) {
+ subtitle.append(cachesCnt).append('/').append(res.getQuantityString(R.plurals.cache_counts, totalCount, totalCount));
+ }
+ else {
+ subtitle.append(res.getQuantityString(R.plurals.cache_counts, cachesCnt, cachesCnt));
+ }
+ }
+
+ if (Settings.isDebug() && lastSearchResult != null && StringUtils.isNotBlank(lastSearchResult.getUrl())) {
+ subtitle.append(" [").append(lastSearchResult.getUrl()).append(']');
+ }
+
+ return subtitle.toString();
+ }
+
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void setTitleIceCreamSandwich(final String title) {
activity.getActionBar().setTitle(title);
}
+
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ private void setSubtitleIceCreamSandwich(final String subtitle) {
+ activity.getActionBar().setSubtitle(subtitle);
+ }
+
/** Updates the progress. */
private static final class ShowProgressHandler extends Handler {
private int counter = 0;
@@ -331,7 +382,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
if (msg.what == UPDATE_PROGRESS) {
if (waitDialog != null) {
final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
- int secondsRemaining;
+ final int secondsRemaining;
if (detailProgress > 0) {
secondsRemaining = (detailTotal - detailProgress) * secondsElapsed / detailProgress;
} else {
@@ -367,25 +418,10 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
public CGeoMap(final MapActivityImpl activity) {
super(activity);
- geoDirUpdate = new UpdateLoc(this);
}
protected void countVisibleCaches() {
- final List<Geocache> protectedCaches = caches.getAsList();
-
- int count = 0;
- if (!protectedCaches.isEmpty()) {
- final Viewport viewport = mapView.getViewport();
-
- for (final Geocache cache : protectedCaches) {
- if (cache != null && cache.getCoords() != null) {
- if (viewport.contains(cache)) {
- count++;
- }
- }
- }
- }
- cachesCnt = count;
+ cachesCnt = mapView.getViewport().count(caches.getAsList());
}
@Override
@@ -404,10 +440,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// class init
res = this.getResources();
activity = this.getActivity();
- app = (CgeoApplication) activity.getApplication();
-
- final int countBubbleCnt = DataStore.getAllCachesCount();
- caches = new LeastRecentlyUsedSet<>(MAX_CACHES + countBubbleCnt);
final MapProvider mapProvider = Settings.getMapProvider();
mapItemFactory = mapProvider.getMapItemFactory();
@@ -415,14 +447,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// Get parameters from the intent
final Bundle extras = activity.getIntent().getExtras();
if (extras != null) {
- mapMode = (MapMode) extras.get(EXTRAS_MAP_MODE);
- isLiveEnabled = extras.getBoolean(EXTRAS_LIVE_ENABLED, false);
- searchIntent = extras.getParcelable(EXTRAS_SEARCH);
- geocodeIntent = extras.getString(EXTRAS_GEOCODE);
- coordsIntent = extras.getParcelable(EXTRAS_COORDS);
- waypointTypeIntent = WaypointType.findById(extras.getString(EXTRAS_WPTTYPE));
- mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE);
- mapTitle = extras.getString(EXTRAS_MAP_TITLE);
+ mapMode = (MapMode) extras.get(Intents.EXTRA_MAP_MODE);
+ isLiveEnabled = extras.getBoolean(Intents.EXTRA_LIVE_ENABLED, false);
+ searchIntent = extras.getParcelable(Intents.EXTRA_SEARCH);
+ geocodeIntent = extras.getString(Intents.EXTRA_GEOCODE);
+ coordsIntent = extras.getParcelable(Intents.EXTRA_COORDS);
+ waypointTypeIntent = WaypointType.findById(extras.getString(Intents.EXTRA_WPTTYPE));
+ mapStateIntent = extras.getIntArray(Intents.EXTRA_MAPSTATE);
+ mapTitle = extras.getString(Intents.EXTRA_TITLE);
}
else {
mapMode = MapMode.LIVE;
@@ -461,7 +493,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
activity.getActionBar().setDisplayHomeAsUpEnabled(true);
}
activity.setContentView(mapProvider.getMapLayoutId());
- setTitle(res.getString(R.string.map_map));
+ setTitle();
// initialize map
mapView = (MapViewImpl) activity.findViewById(mapProvider.getMapViewId());
@@ -475,18 +507,21 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
mapView.clearOverlays();
overlayCaches = mapView.createAddMapOverlay(mapView.getContext(), getResources().getDrawable(R.drawable.marker));
- overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay();
+
+
+ overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(coordsIntent, geocodeIntent);
if (trailHistory != null) {
overlayPositionAndScale.setHistory(trailHistory);
}
+
mapView.repaintRequired(null);
- setZoom(Settings.getMapZoom());
+ setZoom(Settings.getMapZoom(mapMode));
mapView.getMapController().setCenter(Settings.getMapCenter());
if (null == mapStateIntent) {
- followMyLocation = mapMode == MapMode.LIVE;
+ followMyLocation = followMyLocation && (mapMode == MapMode.LIVE);
} else {
followMyLocation = 1 == mapStateIntent[3];
if ((overlayCaches.getCircles() ? 1 : 0) != mapStateIntent[4]) {
@@ -504,9 +539,22 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
prepareFilterBar();
- if (!app.isLiveMapHintShownInThisSession() && !Settings.getHideLiveMapHint() && Settings.getLiveMapHintShowCount() <= 3) {
+ // Check for Honeycomb fake overflow button and attach popup
+ final View overflowActionBar = ButterKnife.findById(activity, R.id.overflowActionBar);
+ if (overflowActionBar != null) {
+ honeycombMenu = true;
+ overflowActionBar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ showPopupHoneycomb(v);
+ }
+ });
+ }
+
+ if (!CgeoApplication.getInstance().isLiveMapHintShownInThisSession() && Settings.getLiveMapHintShowCount() <= 3) {
LiveMapInfoDialogBuilder.create(activity).show();
}
+ AndroidBeam.disable(activity);
}
private void initMyLocationSwitchButton(final CheckBox locSwitch) {
@@ -522,7 +570,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
/**
* Set the zoom of the map. The zoom is restricted to a certain minimum in case of live map.
*
- * @param zoom
*/
private void setZoom(final int zoom) {
mapView.getMapController().setZoom(isLiveEnabled ? Math.max(zoom, MIN_LIVEMAP_ZOOM) : zoom);
@@ -546,18 +593,28 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
resumeSubscription = Subscriptions.from(geoDirUpdate.start(GeoDirHandler.UPDATE_GEODIR), startTimer());
if (!CollectionUtils.isEmpty(dirtyCaches)) {
- for (final String geocode : dirtyCaches) {
- final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
- if (cache != null) {
- // new collection type needs to remove first
- caches.remove(cache);
- // re-add to update the freshness
- caches.add(cache);
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ public Void doInBackground(final Void... params) {
+ for (final String geocode : dirtyCaches) {
+ final Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ if (cache != null) {
+ // new collection type needs to remove first
+ caches.remove(cache);
+ // re-add to update the freshness
+ caches.add(cache);
+ }
+ }
+ return null;
}
- }
- dirtyCaches.clear();
- // Update display
- displayExecutor.execute(new DisplayRunnable(this));
+
+ @Override
+ public void onPostExecute(final Void result) {
+ dirtyCaches.clear();
+ // Update display
+ displayExecutor.execute(new DisplayRunnable(CGeoMap.this));
+ }
+ }.execute();
}
}
@@ -581,10 +638,37 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void showPopupHoneycomb(final View view) {
+ // Inflate the core menu ourselves
+ final android.widget.PopupMenu popupMenu = new android.widget.PopupMenu(getActivity(), view);
+ final MenuInflater inflater = new MenuInflater(getActivity());
+ inflater.inflate(R.menu.map_activity, popupMenu.getMenu());
+
+ // continue processing menu items as usual
+ onCreateOptionsMenu(popupMenu.getMenu());
+
+ onPrepareOptionsMenu(popupMenu.getMenu());
+
+ popupMenu.setOnMenuItemClickListener(
+ new android.widget.PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(final MenuItem item) {
+ return onOptionsItemSelected(item);
+ }
+ }
+ );
+ // display menu
+ popupMenu.show();
+ }
+
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
// menu inflation happens in Google/Mapsforge specific classes
- super.onCreateOptionsMenu(menu);
+ // skip it for honeycomb - handled specially in @see showPopupHoneycomb
+ if (!honeycombMenu) {
+ super.onCreateOptionsMenu(menu);
+ }
MapProviderFactory.addMapviewMenuItems(menu);
@@ -592,7 +676,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
subMenuStrategy.setHeaderTitle(res.getString(R.string.map_strategy_title));
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
/* if we have an Actionbar find the my position toggle */
final MenuItem item = menu.findItem(R.id.menu_toggle_mypos);
myLocSwitch = new CheckBox(activity);
@@ -640,7 +724,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
item = menu.findItem(R.id.menu_theme_mode); // show theme selection
item.setVisible(mapView.hasMapThemes());
- menu.findItem(R.id.menu_as_list).setVisible(!isLoading());
+ menu.findItem(R.id.menu_as_list).setVisible(!isLoading() && caches.size() > 1);
menu.findItem(R.id.submenu_strategy).setVisible(isLiveEnabled);
@@ -657,6 +741,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
default: // DETAILED
menu.findItem(R.id.menu_strategy_detailed).setChecked(true);
}
+ menu.findItem(R.id.menu_hint).setVisible(mapMode == MapMode.SINGLE);
+ menu.findItem(R.id.menu_compass).setVisible(mapMode == MapMode.SINGLE);
} catch (final RuntimeException e) {
Log.e("CGeoMap.onPrepareOptionsMenu", e);
}
@@ -685,6 +771,10 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
lastSearchResult = null;
searchIntent = null;
ActivityMixin.invalidateOptionsMenu(activity);
+ if (mapMode != MapMode.SINGLE) {
+ mapTitle = StringUtils.EMPTY;
+ }
+ updateMapTitle();
return true;
case R.id.menu_store_caches:
if (!isLoading()) {
@@ -714,7 +804,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
public void call(final Integer selectedListId) {
storeCaches(geocodes, selectedListId);
}
- }, true, StoredList.TEMPORARY_LIST_ID);
+ }, true, StoredList.TEMPORARY_LIST.id);
} else {
storeCaches(geocodes, StoredList.STANDARD_LIST_ID);
}
@@ -742,24 +832,30 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
case R.id.menu_strategy_fastest: {
item.setChecked(true);
- Settings.setLiveMapStrategy(Strategy.FASTEST);
+ Settings.setLiveMapStrategy(LivemapStrategy.FASTEST);
return true;
}
case R.id.menu_strategy_fast: {
item.setChecked(true);
- Settings.setLiveMapStrategy(Strategy.FAST);
+ Settings.setLiveMapStrategy(LivemapStrategy.FAST);
return true;
}
case R.id.menu_strategy_auto: {
item.setChecked(true);
- Settings.setLiveMapStrategy(Strategy.AUTO);
+ Settings.setLiveMapStrategy(LivemapStrategy.AUTO);
return true;
}
case R.id.menu_strategy_detailed: {
item.setChecked(true);
- Settings.setLiveMapStrategy(Strategy.DETAILED);
+ Settings.setLiveMapStrategy(LivemapStrategy.DETAILED);
return true;
}
+ case R.id.menu_hint:
+ menuShowHint();
+ return true;
+ case R.id.menu_compass:
+ menuCompass();
+ return true;
default:
final MapSource mapSource = MapProviderFactory.getMapSource(id);
if (mapSource != null) {
@@ -771,6 +867,20 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
return false;
}
+ private void menuCompass() {
+ final Geocache cache = getSingleModeCache();
+ if (cache != null) {
+ CompassActivity.startActivityCache(this.getActivity(), cache);
+ }
+ }
+
+ private void menuShowHint() {
+ final Geocache cache = getSingleModeCache();
+ if (cache != null) {
+ cache.showHintToast(getActivity());
+ }
+ }
+
private void selectMapTheme() {
final File[] themeFiles = Settings.getMapThemeFiles();
@@ -853,7 +963,12 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
if (restartRequired) {
mapRestart();
} else if (mapView != null) { // changeMapSource can be called by onCreate()
+ mapStateIntent = currentMapState();
mapView.setMapSource();
+ // re-center the map
+ centered = false;
+ centerMap(geocodeIntent, searchIntent, coordsIntent, mapStateIntent);
+ // re-build menues
ActivityMixin.invalidateOptionsMenu(activity);
}
@@ -864,27 +979,27 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
* Restart the current activity with the default map source.
*/
private void mapRestart() {
- // close old mapview
- activity.finish();
-
// prepare information to restart a similar view
final Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass());
- mapIntent.putExtra(EXTRAS_SEARCH, searchIntent);
- mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent);
+ mapIntent.putExtra(Intents.EXTRA_SEARCH, searchIntent);
+ mapIntent.putExtra(Intents.EXTRA_GEOCODE, geocodeIntent);
if (coordsIntent != null) {
- mapIntent.putExtra(EXTRAS_COORDS, coordsIntent);
+ mapIntent.putExtra(Intents.EXTRA_COORDS, coordsIntent);
}
- mapIntent.putExtra(EXTRAS_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null);
- mapIntent.putExtra(EXTRAS_MAP_TITLE, mapTitle);
- mapIntent.putExtra(EXTRAS_MAP_MODE, mapMode);
- mapIntent.putExtra(EXTRAS_LIVE_ENABLED, isLiveEnabled);
+ mapIntent.putExtra(Intents.EXTRA_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null);
+ mapIntent.putExtra(Intents.EXTRA_TITLE, mapTitle);
+ mapIntent.putExtra(Intents.EXTRA_MAP_MODE, mapMode);
+ mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, isLiveEnabled);
final int[] mapState = currentMapState();
if (mapState != null) {
- mapIntent.putExtra(EXTRAS_MAPSTATE, mapState);
+ mapIntent.putExtra(Intents.EXTRA_MAPSTATE, mapState);
}
+ // close old map
+ activity.finish();
+
// start the new map
activity.startActivity(mapIntent);
}
@@ -909,13 +1024,13 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
private void savePrefs() {
- Settings.setMapZoom(mapView.getMapZoomLevel());
+ Settings.setMapZoom(mapMode, mapView.getMapZoomLevel());
Settings.setMapCenter(mapView.getMapViewCenter());
}
// Set center of map to my location if appropriate.
- private void myLocationInMiddle(final IGeoData geo) {
- if (followMyLocation && !geo.isPseudoLocation()) {
+ private void myLocationInMiddle(final GeoData geo) {
+ if (followMyLocation) {
centerMap(geo.getCoords());
}
}
@@ -931,8 +1046,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// minimum change of location in fraction of map width/height (whatever is smaller) for position overlay update
private static final float MIN_LOCATION_DELTA = 0.01f;
- Location currentLocation = new Location("");
- boolean locationValid = false;
+ Location currentLocation = Sensors.getInstance().currentGeo();
float currentHeading;
private long timeLastPositionOverlayCalculation = 0;
@@ -946,16 +1060,10 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
@Override
- public void updateGeoDir(final IGeoData geo, final float dir) {
- if (geo.isPseudoLocation()) {
- locationValid = false;
- } else {
- locationValid = true;
-
- currentLocation = geo.getLocation();
- currentHeading = DirectionProvider.getDirectionNow(dir);
- repaintPositionOverlay();
- }
+ public void updateGeoDir(final GeoData geo, final float dir) {
+ currentLocation = geo;
+ currentHeading = AngleUtils.getDirectionNow(dir);
+ repaintPositionOverlay();
}
/**
@@ -969,23 +1077,24 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
try {
final CGeoMap map = mapRef.get();
if (map != null) {
- final boolean needsRepaintForDistance = needsRepaintForDistance();
+ final boolean needsRepaintForDistanceOrAccuracy = needsRepaintForDistanceOrAccuracy();
final boolean needsRepaintForHeading = needsRepaintForHeading();
- if (needsRepaintForDistance) {
- if (map.followMyLocation) {
+ if (needsRepaintForDistanceOrAccuracy) {
+ if (CGeoMap.followMyLocation) {
map.centerMap(new Geopoint(currentLocation));
}
}
- if (needsRepaintForDistance || needsRepaintForHeading) {
+ if (needsRepaintForDistanceOrAccuracy || needsRepaintForHeading) {
+
map.overlayPositionAndScale.setCoordinates(currentLocation);
map.overlayPositionAndScale.setHeading(currentHeading);
map.mapView.repaintRequired(map.overlayPositionAndScale);
}
}
} catch (final RuntimeException e) {
- Log.w("Failed to update location.");
+ Log.w("Failed to update location", e);
}
}
}
@@ -998,11 +1107,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
return Math.abs(AngleUtils.difference(currentHeading, map.overlayPositionAndScale.getHeading())) > MIN_HEADING_DELTA;
}
- boolean needsRepaintForDistance() {
- if (!locationValid) {
- return false;
- }
-
+ boolean needsRepaintForDistanceOrAccuracy() {
final CGeoMap map = mapRef.get();
if (map == null) {
return false;
@@ -1011,6 +1116,9 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
float dist = Float.MAX_VALUE;
if (lastLocation != null) {
+ if (lastLocation.getAccuracy() != currentLocation.getAccuracy()) {
+ return true;
+ }
dist = currentLocation.distanceTo(lastLocation);
}
@@ -1028,7 +1136,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
/**
- * Starts the {@link LoadTimer}.
+ * Starts the load timer.
*/
private Subscription startTimer() {
@@ -1037,7 +1145,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
displayPoint(coordsIntent);
loadTimer = Subscriptions.empty();
} else {
- loadTimer = startLoadTimer();
+ loadTimer = Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 0, 250, TimeUnit.MILLISECONDS);
}
return loadTimer;
}
@@ -1072,7 +1180,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
// update title on any change
if (moved || !viewportNow.equals(previousViewport)) {
- map.displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ map.updateMapTitle();
}
previousZoom = zoomNow;
@@ -1094,16 +1202,8 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
/**
- * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}.
- */
- private Subscription startLoadTimer() {
- return Schedulers.newThread().createWorker().schedulePeriodically(new LoadTimerAction(this), 0, 250, TimeUnit.MILLISECONDS);
- }
-
- /**
* get if map is loading something
*
- * @return
*/
public boolean isLoading() {
return !loadTimer.isUnsubscribed() &&
@@ -1114,7 +1214,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
/**
* Worker thread that loads caches and waypoints from the database and then spawns the {@link DownloadRunnable}.
- * started by {@link LoadTimer}
+ * started by the load timer.
*/
private static class LoadRunnable extends DoRunnable {
@@ -1134,7 +1234,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
loadThreadRun = System.currentTimeMillis();
- SearchResult searchResult;
+ final SearchResult searchResult;
if (mapMode == MapMode.LIVE) {
searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(mapView.getViewport(), Settings.getCacheType()));
} else {
@@ -1250,9 +1350,6 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
//render
displayExecutor.execute(new DisplayRunnable(this));
- } catch (final ThreadDeath e) {
- Log.d("DownloadThread stopped");
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
} finally {
showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
@@ -1302,19 +1399,14 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
}
itemsToDisplay.add(getCacheItem(cache));
}
-
- overlayCaches.updateItems(itemsToDisplay);
- displayHandler.sendEmptyMessage(INVALIDATE_MAP);
-
- } else {
+ }
+ // don't add other waypoints to overlayCaches if just one point should be displayed
+ if (coordsIntent == null) {
overlayCaches.updateItems(itemsToDisplay);
- displayHandler.sendEmptyMessage(INVALIDATE_MAP);
}
+ displayHandler.sendEmptyMessage(INVALIDATE_MAP);
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } catch (final ThreadDeath e) {
- Log.d("DisplayThread stopped");
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ updateMapTitle();
} finally {
showProgressHandler.sendEmptyMessage(HIDE_PROGRESS);
}
@@ -1327,11 +1419,15 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
final CachesOverlayItemImpl item = getWaypointItem(waypoint);
overlayCaches.updateItems(item);
displayHandler.sendEmptyMessage(INVALIDATE_MAP);
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ updateMapTitle();
cachesCnt = 1;
}
+ private void updateMapTitle() {
+ displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ }
+
private static abstract class DoRunnable implements Runnable {
private final WeakReference<CGeoMap> mapRef;
@@ -1538,7 +1634,7 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
if (myLocSwitch != null) {
myLocSwitch.setChecked(followMyLocation);
if (followMyLocation) {
- myLocationInMiddle(app.currentGeo());
+ myLocationInMiddle(Sensors.getInstance().currentGeo());
}
}
}
@@ -1610,42 +1706,40 @@ public class CGeoMap extends AbstractMap implements ViewFactory {
public static void startActivitySearch(final Activity fromActivity, final SearchResult search, final String title) {
final Intent mapIntent = newIntent(fromActivity);
- mapIntent.putExtra(EXTRAS_SEARCH, search);
- mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.LIST);
- mapIntent.putExtra(EXTRAS_LIVE_ENABLED, false);
+ mapIntent.putExtra(Intents.EXTRA_SEARCH, search);
+ mapIntent.putExtra(Intents.EXTRA_MAP_MODE, MapMode.LIST);
+ mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, false);
if (StringUtils.isNotBlank(title)) {
- mapIntent.putExtra(CGeoMap.EXTRAS_MAP_TITLE, title);
+ mapIntent.putExtra(Intents.EXTRA_TITLE, title);
}
fromActivity.startActivity(mapIntent);
}
- public static void startActivityLiveMap(final Activity fromActivity) {
- final Intent mapIntent = newIntent(fromActivity);
- mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.LIVE);
- mapIntent.putExtra(EXTRAS_LIVE_ENABLED, Settings.isLiveMap());
- fromActivity.startActivity(mapIntent);
+ public static Intent getLiveMapIntent(final Activity fromActivity) {
+ return newIntent(fromActivity)
+ .putExtra(Intents.EXTRA_MAP_MODE, MapMode.LIVE)
+ .putExtra(Intents.EXTRA_LIVE_ENABLED, Settings.isLiveMap());
}
public static void startActivityCoords(final Activity fromActivity, final Geopoint coords, final WaypointType type, final String title) {
final Intent mapIntent = newIntent(fromActivity);
- mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.COORDS);
- mapIntent.putExtra(EXTRAS_LIVE_ENABLED, false);
- mapIntent.putExtra(EXTRAS_COORDS, coords);
+ mapIntent.putExtra(Intents.EXTRA_MAP_MODE, MapMode.COORDS);
+ mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, false);
+ mapIntent.putExtra(Intents.EXTRA_COORDS, coords);
if (type != null) {
- mapIntent.putExtra(EXTRAS_WPTTYPE, type.id);
+ mapIntent.putExtra(Intents.EXTRA_WPTTYPE, type.id);
}
if (StringUtils.isNotBlank(title)) {
- mapIntent.putExtra(EXTRAS_MAP_TITLE, title);
+ mapIntent.putExtra(Intents.EXTRA_TITLE, title);
}
fromActivity.startActivity(mapIntent);
}
public static void startActivityGeoCode(final Activity fromActivity, final String geocode) {
final Intent mapIntent = newIntent(fromActivity);
- mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.SINGLE);
- mapIntent.putExtra(EXTRAS_LIVE_ENABLED, false);
- mapIntent.putExtra(EXTRAS_GEOCODE, geocode);
- mapIntent.putExtra(EXTRAS_MAP_TITLE, geocode);
+ mapIntent.putExtra(Intents.EXTRA_MAP_MODE, MapMode.SINGLE);
+ mapIntent.putExtra(Intents.EXTRA_LIVE_ENABLED, false);
+ mapIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
fromActivity.startActivity(mapIntent);
}