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.java970
1 files changed, 490 insertions, 480 deletions
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index 00aee36..2ca0cfd 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -1,5 +1,7 @@
package cgeo.geocaching.maps;
+import butterknife.ButterKnife;
+
import cgeo.geocaching.CacheListActivity;
import cgeo.geocaching.CgeoApplication;
import cgeo.geocaching.DataStore;
@@ -38,19 +40,19 @@ import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.LeastRecentlyUsedSet;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.eclipse.jdt.annotation.NonNull;
-import rx.Scheduler;
import rx.Subscription;
+import rx.functions.Action0;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
-import rx.subscriptions.CompositeSubscription;
import rx.subscriptions.Subscriptions;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
@@ -61,18 +63,20 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.location.Location;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
+import android.widget.CheckBox;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
+import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.ViewSwitcher.ViewFactory;
@@ -92,11 +96,14 @@ import java.util.concurrent.TimeUnit;
/**
* Class representing the Map in c:geo
*/
-public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFactory {
+public class CGeoMap extends AbstractMap implements ViewFactory {
/** max. number of caches displayed in the Live Map */
public static final int MAX_CACHES = 500;
- private CompositeSubscription resumeSubscription;
+ /**
+ * initialization with an empty subscription to make static code analysis tools more happy
+ */
+ private Subscription resumeSubscription = Subscriptions.empty();
/** Controls the behavior of the map */
public enum MapMode {
@@ -133,11 +140,17 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static final String BUNDLE_LIVE_ENABLED = "liveEnabled";
private static final String BUNDLE_TRAIL_HISTORY = "trailHistory";
- private Resources res = null;
- private MapItemFactory mapItemFactory = null;
- private Activity activity = null;
- private MapViewImpl mapView = null;
- private CgeoApplication app = null;
+ // 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;
+ private MapViewImpl mapView;
+ private CachesOverlay overlayCaches;
+ private PositionAndScaleOverlay overlayPositionAndScale;
+
final private GeoDirHandler geoDirUpdate;
private SearchResult searchIntent = null;
private String geocodeIntent = null;
@@ -151,8 +164,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private boolean noMapTokenShowed = false;
// map status data
private boolean followMyLocation = false;
- private Viewport viewport = null;
- private int zoom = -100;
// threads
private Subscription loadTimer;
private LoadDetails loadDetailsThread = null;
@@ -160,33 +171,20 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private volatile long loadThreadRun = 0L;
//Interthread communication flag
private volatile boolean downloaded = false;
- // overlays
- private CachesOverlay overlayCaches = null;
- private PositionAndScaleOverlay overlayPositionAndScale = null;
- // data for overlays
- private static final int[][] INSET_RELIABLE = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; // center, 33x40 / 45x51 / 60x68
- private static final int[][] INSET_TYPE = { { 5, 8, 6, 10 }, { 4, 4, 5, 11 }, { 4, 4, 5, 11 } }; // center, 22x22 / 36x36
- private static final int[][] INSET_OWN = { { 21, 0, 0, 26 }, { 25, 0, 0, 35 }, { 40, 0, 0, 48 } }; // top right, 12x12 / 16x16 / 20x20
- private static final int[][] INSET_FOUND = { { 0, 0, 21, 28 }, { 0, 0, 25, 35 }, { 0, 0, 40, 48 } }; // top left, 12x12 / 16x16 / 20x20
- private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 }, { 25, 33, 0, 0 } }; // bottom right, 12x12 / 26x26 / 35x35
- private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 }, { 0, 33, 25, 0 } }; // bottom left, 12x12 / 26x26 / 35x35
-
- private SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
+
/** Count of caches currently visible */
private int cachesCnt = 0;
- /** List of caches in the viewport */
- private LeastRecentlyUsedSet<Geocache> caches = null;
/** List of waypoints in the viewport */
- private final LeastRecentlyUsedSet<Waypoint> waypoints = new LeastRecentlyUsedSet<Waypoint>(MAX_CACHES);
+ private final LeastRecentlyUsedSet<Waypoint> waypoints = new LeastRecentlyUsedSet<>(MAX_CACHES);
// storing for offline
private ProgressDialog waitDialog = null;
private int detailTotal = 0;
private int detailProgress = 0;
private long detailProgressTime = 0L;
- // views
- private ImageSwitcher myLocSwitch = null;
- /** Controls the map behaviour */
+ // views
+ private CheckBox myLocSwitch = null;
+ /** Controls the map behavior */
private MapMode mapMode = null;
/** Live mode enabled for map. **/
private boolean isLiveEnabled;
@@ -194,90 +192,147 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private boolean markersInvalidated = false; // previous state for loadTimer
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<String>();
+ private static final Set<String> dirtyCaches = new HashSet<>();
+
/**
* 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<Runnable>(1);
+ 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<Runnable>(1);
+ 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<Runnable>(1);
- private static ThreadPoolExecutor loadExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, loadQueue, 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());
// handlers
/** Updates the titles */
- final private Handler displayHandler = new Handler() {
+ private final static class DisplayHandler extends Handler {
+
+ private final WeakReference<CGeoMap> mapRef;
+
+ public DisplayHandler(@NonNull final CGeoMap map) {
+ this.mapRef = new WeakReference<>(map);
+ }
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
final int what = msg.what;
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
+ return;
+ }
switch (what) {
case UPDATE_TITLE:
// set title
final StringBuilder title = new StringBuilder();
- if (mapMode == MapMode.LIVE && isLiveEnabled) {
- title.append(res.getString(R.string.map_live));
+ if (map.mapMode == MapMode.LIVE && map.isLiveEnabled) {
+ title.append(map.res.getString(R.string.map_live));
} else {
- title.append(mapTitle);
+ title.append(map.mapTitle);
}
- countVisibleCaches();
- if (caches != null && !caches.isEmpty() && !mapTitle.contains("[")) {
- title.append(" [").append(cachesCnt);
- if (cachesCnt != caches.size()) {
- title.append('/').append(caches.size());
+ 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(']');
}
- if (Settings.isDebug() && lastSearchResult != null && StringUtils.isNotBlank(lastSearchResult.getUrl())) {
- title.append('[').append(lastSearchResult.getUrl()).append(']');
+ if (Settings.isDebug() && map.lastSearchResult != null && StringUtils.isNotBlank(map.lastSearchResult.getUrl())) {
+ title.append('[').append(map.lastSearchResult.getUrl()).append(']');
}
- ActivityMixin.setTitle(activity, title.toString());
+ map.setTitle(title.toString());
break;
case INVALIDATE_MAP:
- mapView.repaintRequired(null);
+ map.mapView.repaintRequired(null);
break;
default:
break;
}
}
- };
- /** Updates the progress. */
- final private Handler showProgressHandler = new Handler() {
+ }
+
+ final private Handler displayHandler = new DisplayHandler(this);
+
+ private void setTitle(final String title) {
+ /* 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(title);
+
+ }
+ if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)) {
+ setTitleHoneyComb(title);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private void setTitleHoneyComb(final String title) {
+ activity.getActionBar().setTitle(title);
+ }
+ /** Updates the progress. */
+ private static final class ShowProgressHandler extends Handler {
private int counter = 0;
+ @NonNull private final WeakReference<CGeoMap> mapRef;
+
+ public ShowProgressHandler(@NonNull final CGeoMap map) {
+ this.mapRef = new WeakReference<>(map);
+ }
+
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(final Message msg) {
final int what = msg.what;
if (what == HIDE_PROGRESS) {
if (--counter == 0) {
- ActivityMixin.showProgress(activity, false);
+ showProgress(false);
}
} else if (what == SHOW_PROGRESS) {
- ActivityMixin.showProgress(activity, true);
+ showProgress(true);
counter++;
}
}
- };
+ private void showProgress(final boolean show) {
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
+ return;
+ }
+
+ final ProgressBar progress = (ProgressBar) map.activity.findViewById(R.id.actionbar_progress);
+ if (progress != null) {
+ if (show) {
+ progress.setVisibility(View.VISIBLE);
+ } else {
+ progress.setVisibility(View.GONE);
+
+ }
+ }
+ if (Build.VERSION.SDK_INT >= 11) {
+ map.activity.setProgressBarIndeterminateVisibility(show);
+ }
+ }
+
+ }
+
+ final private Handler showProgressHandler = new ShowProgressHandler(this);
final private class LoadDetailsHandler extends CancellableHandler {
@Override
- public void handleRegularMessage(Message msg) {
+ public void handleRegularMessage(final Message msg) {
if (msg.what == UPDATE_PROGRESS) {
if (waitDialog != null) {
- int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
+ final int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
int secondsRemaining;
if (detailProgress > 0) {
secondsRemaining = (detailTotal - detailProgress) * secondsElapsed / detailProgress;
@@ -289,8 +344,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (secondsRemaining < 40) {
waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm));
} else {
- int minsRemaining = secondsRemaining / 60;
- waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + minsRemaining + " " + res.getQuantityString(R.plurals.caches_eta_mins, minsRemaining));
+ final int minsRemaining = secondsRemaining / 60;
+ waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getQuantityString(R.plurals.caches_eta_mins, minsRemaining, minsRemaining));
}
}
} else if (msg.what == FINISHED_LOADING_DETAILS) {
@@ -300,35 +355,19 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
}
-
@Override
public void handleCancel(final Object extra) {
if (loadDetailsThread != null) {
loadDetailsThread.stopIt();
}
}
- }
- final private Handler noMapTokenHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- if (!noMapTokenShowed) {
- ActivityMixin.showToast(activity, res.getString(R.string.map_token_err));
-
- noMapTokenShowed = true;
- }
- }
- };
- /**
- * calling activities can set the map title via extras
- */
- private String mapTitle;
+ }
/* Current source id */
private int currentSourceId;
- public CGeoMap(MapActivityImpl activity) {
+ public CGeoMap(final MapActivityImpl activity) {
super(activity);
geoDirUpdate = new UpdateLoc(this);
}
@@ -356,13 +395,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
outState.putInt(BUNDLE_MAP_SOURCE, currentSourceId);
outState.putIntArray(BUNDLE_MAP_STATE, currentMapState());
outState.putBoolean(BUNDLE_LIVE_ENABLED, isLiveEnabled);
- if (overlayPositionAndScale != null) {
- outState.putParcelableArrayList(BUNDLE_TRAIL_HISTORY, overlayPositionAndScale.getHistory());
- }
+ outState.putParcelableArrayList(BUNDLE_TRAIL_HISTORY, overlayPositionAndScale.getHistory());
}
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// class init
@@ -370,8 +408,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
activity = this.getActivity();
app = (CgeoApplication) activity.getApplication();
- int countBubbleCnt = DataStore.getAllCachesCount();
- caches = new LeastRecentlyUsedSet<Geocache>(MAX_CACHES + countBubbleCnt);
+ final int countBubbleCnt = DataStore.getAllCachesCount();
+ caches = new LeastRecentlyUsedSet<>(MAX_CACHES + countBubbleCnt);
final MapProvider mapProvider = Settings.getMapProvider();
mapItemFactory = mapProvider.getMapItemFactory();
@@ -418,10 +456,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
ActivityMixin.keepScreenOn(activity, true);
+
// set layout
ActivityMixin.setTheme(activity);
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
+ activity.getActionBar().setDisplayHomeAsUpEnabled(true);
+ }
activity.setContentView(mapProvider.getMapLayoutId());
- ActivityMixin.setTitle(activity, res.getString(R.string.map_map));
+ setTitle(res.getString(R.string.map_map));
// initialize map
mapView = (MapViewImpl) activity.findViewById(mapProvider.getMapViewId());
@@ -429,20 +471,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapView.setBuiltInZoomControls(true);
mapView.displayZoomControls(true);
mapView.preLoad();
- mapView.setOnDragListener(this);
+ mapView.setOnDragListener(new MapDragListener(this));
// initialize overlays
mapView.clearOverlays();
- if (overlayCaches == null) {
- overlayCaches = mapView.createAddMapOverlay(mapView.getContext(), getResources().getDrawable(R.drawable.marker));
- }
-
- if (overlayPositionAndScale == null) {
- overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay(activity);
- if (trailHistory != null) {
- overlayPositionAndScale.setHistory(trailHistory);
- }
+ overlayCaches = mapView.createAddMapOverlay(mapView.getContext(), getResources().getDrawable(R.drawable.marker));
+ overlayPositionAndScale = mapView.createAddPositionAndScaleOverlay();
+ if (trailHistory != null) {
+ overlayPositionAndScale.setHistory(trailHistory);
}
mapView.repaintRequired(null);
@@ -462,14 +499,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
centerMap(geocodeIntent, searchIntent, coordsIntent, mapStateIntent);
}
- // prepare my location button
- myLocSwitch = (ImageSwitcher) activity.findViewById(R.id.my_position);
- myLocSwitch.setFactory(this);
- myLocSwitch.setInAnimation(activity, android.R.anim.fade_in);
- myLocSwitch.setOutAnimation(activity, android.R.anim.fade_out);
- myLocSwitch.setOnClickListener(new MyLocationListener());
- switchMyLocationButton();
+ final CheckBox locSwitch = ButterKnife.findById(activity, R.id.my_position);
+ if (locSwitch!=null) {
+ initMyLocationSwitchButton(locSwitch);
+ }
prepareFilterBar();
if (!app.isLiveMapHintShownInThisSession() && !Settings.getHideLiveMapHint() && Settings.getLiveMapHintShowCount() <= 3) {
@@ -477,6 +511,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
+ private void initMyLocationSwitchButton(final CheckBox locSwitch) {
+ myLocSwitch = locSwitch;
+ /* TODO: Switch back to ImageSwitcher for animations?
+ myLocSwitch.setFactory(this);
+ myLocSwitch.setInAnimation(activity, android.R.anim.fade_in);
+ myLocSwitch.setOutAnimation(activity, android.R.anim.fade_out); */
+ myLocSwitch.setOnClickListener(new MyLocationListener(this));
+ switchMyLocationButton();
+ }
+
/**
* Set the zoom of the map. The zoom is restricted to a certain minimum in case of live map.
*
@@ -489,8 +533,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private void prepareFilterBar() {
// show the filter warning bar if the filter is set
if (Settings.getCacheType() != CacheType.ALL) {
- String cacheType = Settings.getCacheType().getL10n();
- ((TextView) activity.findViewById(R.id.filter_text)).setText(cacheType);
+ final String cacheType = Settings.getCacheType().getL10n();
+ final TextView filterTitleView = ButterKnife.findById(activity, R.id.filter_text);
+ filterTitleView.setText(cacheType);
activity.findViewById(R.id.filter_bar).setVisibility(View.VISIBLE);
} else {
activity.findViewById(R.id.filter_bar).setVisibility(View.GONE);
@@ -503,8 +548,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
resumeSubscription = Subscriptions.from(geoDirUpdate.start(GeoDirHandler.UPDATE_GEODIR), startTimer());
if (!CollectionUtils.isEmpty(dirtyCaches)) {
- for (String geocode : dirtyCaches) {
- Geocache cache = DataStore.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ 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);
@@ -514,7 +559,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
dirtyCaches.clear();
// Update display
- displayExecutor.execute(new DisplayRunnable(mapView.getViewport()));
+ displayExecutor.execute(new DisplayRunnable(this));
}
}
@@ -523,17 +568,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
resumeSubscription.unsubscribe();
savePrefs();
- if (mapView != null) {
- mapView.destroyDrawingCache();
- }
+ mapView.destroyDrawingCache();
- overlaysCache.clear();
+ MapUtils.clearCachedItems();
super.onPause();
}
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public boolean onCreateOptionsMenu(final Menu menu) {
// menu inflation happens in Google/Mapsforge specific classes
super.onCreateOptionsMenu(menu);
@@ -541,26 +585,35 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final SubMenu subMenuStrategy = menu.findItem(R.id.submenu_strategy).getSubMenu();
subMenuStrategy.setHeaderTitle(res.getString(R.string.map_strategy_title));
+
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
+ /* if we have an Actionbar find the my position toggle */
+ final MenuItem item = menu.findItem(R.id.menu_toggle_mypos);
+ myLocSwitch = new CheckBox(activity);
+ myLocSwitch.setButtonDrawable(R.drawable.ic_menu_myposition);
+ item.setActionView(myLocSwitch);
+ initMyLocationSwitchButton(myLocSwitch);
+ } else {
+ // Already on the fake Actionbar
+ menu.removeItem(R.id.menu_toggle_mypos);
+ }
return true;
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public boolean onPrepareOptionsMenu(final Menu menu) {
super.onPrepareOptionsMenu(menu);
- for (MapSource mapSource : MapProviderFactory.getMapSources()) {
+ for (final MapSource mapSource : MapProviderFactory.getMapSources()) {
final MenuItem menuItem = menu.findItem(mapSource.getNumericalId());
if (menuItem != null) {
- menuItem.setEnabled(mapSource.isAvailable());
+ menuItem.setVisible(mapSource.isAvailable());
}
}
try {
MenuItem item = menu.findItem(R.id.menu_trail_mode);
- if (Settings.isMapTrail()) {
- item.setTitle(res.getString(R.string.map_trail_hide));
- } else {
- item.setTitle(res.getString(R.string.map_trail_show));
- }
+ item.setChecked(Settings.isMapTrail());
item = menu.findItem(R.id.menu_map_live); // live map
if (isLiveEnabled) {
@@ -570,28 +623,20 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
item = menu.findItem(R.id.menu_mycaches_mode); // own & found caches
- if (Settings.isExcludeMyCaches()) {
- item.setTitle(res.getString(R.string.map_mycaches_show));
- } else {
- item.setTitle(res.getString(R.string.map_mycaches_hide));
- }
+ item.setChecked(Settings.isExcludeMyCaches());
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
- menu.findItem(R.id.menu_store_caches).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
+ menu.findItem(R.id.menu_store_caches).setVisible(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
item = menu.findItem(R.id.menu_circle_mode); // show circles
- if (overlayCaches != null && overlayCaches.getCircles()) {
- item.setTitle(res.getString(R.string.map_circles_hide));
- } else {
- item.setTitle(res.getString(R.string.map_circles_show));
- }
+ item.setChecked(overlayCaches.getCircles());
item = menu.findItem(R.id.menu_theme_mode); // show theme selection
item.setVisible(mapView.hasMapThemes());
- menu.findItem(R.id.menu_as_list).setEnabled(!isLoading());
+ menu.findItem(R.id.menu_as_list).setVisible(!isLoading());
- menu.findItem(R.id.submenu_strategy).setEnabled(isLiveEnabled);
+ menu.findItem(R.id.submenu_strategy).setVisible(isLiveEnabled);
switch (Settings.getLiveMapStrategy()) {
case FASTEST:
@@ -606,7 +651,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
default: // DETAILED
menu.findItem(R.id.menu_strategy_detailed).setChecked(true);
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("CGeoMap.onPrepareOptionsMenu", e);
}
@@ -614,9 +659,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
+ public boolean onOptionsItemSelected(final MenuItem item) {
final int id = item.getItemId();
switch (id) {
+ case android.R.id.home:
+ ActivityMixin.navigateUp(activity);
+ return true;
case R.id.menu_trail_mode:
Settings.setMapTrail(!Settings.isMapTrail());
mapView.repaintRequired(overlayPositionAndScale);
@@ -635,7 +683,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
case R.id.menu_store_caches:
if (!isLoading()) {
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
- final List<String> geocodes = new ArrayList<String>();
+ final List<String> geocodes = new ArrayList<>();
for (final String geocode : geocodesInViewport) {
if (!DataStore.isOffline(geocode, null)) {
@@ -667,10 +715,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
return true;
case R.id.menu_circle_mode:
- if (overlayCaches == null) {
- return false;
- }
-
overlayCaches.switchCircles();
mapView.repaintRequired(overlayCaches);
ActivityMixin.invalidateOptionsMenu(activity);
@@ -726,16 +770,16 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final File[] themeFiles = Settings.getMapThemeFiles();
String currentTheme = StringUtils.EMPTY;
- String currentThemePath = Settings.getCustomRenderThemeFilePath();
+ final String currentThemePath = Settings.getCustomRenderThemeFilePath();
if (StringUtils.isNotEmpty(currentThemePath)) {
- File currentThemeFile = new File(currentThemePath);
+ final File currentThemeFile = new File(currentThemePath);
currentTheme = currentThemeFile.getName();
}
- List<String> names = new ArrayList<String>();
+ final List<String> names = new ArrayList<>();
names.add(res.getString(R.string.map_theme_builtin));
int currentItem = 0;
- for (File file : themeFiles) {
+ for (final File file : themeFiles) {
if (currentTheme.equalsIgnoreCase(file.getName())) {
currentItem = names.size();
}
@@ -744,7 +788,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final int selectedItem = currentItem;
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.map_theme_select);
@@ -752,7 +796,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
new DialogInterface.OnClickListener() {
@Override
- public void onClick(DialogInterface dialog, int newItem) {
+ public void onClick(final DialogInterface dialog, final int newItem) {
if (newItem != selectedItem) {
// Adjust index because of <default> selection
if (newItem > 0) {
@@ -773,7 +817,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* @return a non-null Set of geocodes corresponding to the caches that are shown on screen.
*/
private Set<String> getGeocodesForCachesInViewport() {
- final Set<String> geocodes = new HashSet<String>();
+ final Set<String> geocodes = new HashSet<>();
final List<Geocache> cachesProtected = caches.getAsList();
final Viewport viewport = mapView.getViewport();
@@ -802,7 +846,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (restartRequired) {
mapRestart();
- } else if (mapView != null) {
+ } else if (mapView != null) { // changeMapSource can be called by onCreate()
mapView.setMapSource();
ActivityMixin.invalidateOptionsMenu(activity);
}
@@ -818,7 +862,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
activity.finish();
// prepare information to restart a similar view
- Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass());
+ final Intent mapIntent = new Intent(activity, Settings.getMapProvider().getMapClass());
mapIntent.putExtra(EXTRAS_SEARCH, searchIntent);
mapIntent.putExtra(EXTRAS_GEOCODE, geocodeIntent);
@@ -845,10 +889,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* @return the current map state as an array of int, or null if no map state is available
*/
private int[] currentMapState() {
- if (mapView == null) {
- return mapStateIntent;
- }
-
final GeoPointImpl mapCenter = mapView.getMapViewCenter();
return new int[] {
mapCenter.getLatitudeE6(),
@@ -860,10 +900,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
private void savePrefs() {
- if (mapView == null) {
- return;
- }
-
Settings.setMapZoom(mapView.getMapZoomLevel());
Settings.setMapCenter(mapView.getMapViewCenter());
}
@@ -894,10 +930,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
/**
* weak reference to the outer class
*/
- private final WeakReference<CGeoMap> map;
+ private final WeakReference<CGeoMap> mapRef;
- public UpdateLoc(CGeoMap map) {
- this.map = new WeakReference<CGeoMap>(map);
+ public UpdateLoc(final CGeoMap map) {
+ mapRef = new WeakReference<>(map);
}
@Override
@@ -922,41 +958,35 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
timeLastPositionOverlayCalculation = currentTimeMillis;
try {
- CGeoMap cgeoMapRef = map.get();
- if (cgeoMapRef != null) {
- if (cgeoMapRef.mapView != null) {
- if (cgeoMapRef.overlayPositionAndScale == null) {
- cgeoMapRef.overlayPositionAndScale = cgeoMapRef.mapView.createAddPositionAndScaleOverlay(cgeoMapRef.activity);
- }
-
- boolean needsRepaintForDistance = needsRepaintForDistance();
- boolean needsRepaintForHeading = needsRepaintForHeading();
-
- if (needsRepaintForDistance) {
- if (cgeoMapRef.followMyLocation) {
- cgeoMapRef.centerMap(new Geopoint(currentLocation));
- }
+ final CGeoMap map = mapRef.get();
+ if (map != null) {
+ final boolean needsRepaintForDistance = needsRepaintForDistance();
+ final boolean needsRepaintForHeading = needsRepaintForHeading();
+
+ if (needsRepaintForDistance) {
+ if (map.followMyLocation) {
+ map.centerMap(new Geopoint(currentLocation));
}
+ }
- if (needsRepaintForDistance || needsRepaintForHeading) {
- cgeoMapRef.overlayPositionAndScale.setCoordinates(currentLocation);
- cgeoMapRef.overlayPositionAndScale.setHeading(currentHeading);
- cgeoMapRef.mapView.repaintRequired(cgeoMapRef.overlayPositionAndScale);
- }
+ if (needsRepaintForDistance || needsRepaintForHeading) {
+ map.overlayPositionAndScale.setCoordinates(currentLocation);
+ map.overlayPositionAndScale.setHeading(currentHeading);
+ map.mapView.repaintRequired(map.overlayPositionAndScale);
}
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.w("Failed to update location.");
}
}
}
boolean needsRepaintForHeading() {
- final CGeoMap cgeoMapRef = map.get();
- if (cgeoMapRef == null) {
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
return false;
}
- return Math.abs(AngleUtils.difference(currentHeading, cgeoMapRef.overlayPositionAndScale.getHeading())) > MIN_HEADING_DELTA;
+ return Math.abs(AngleUtils.difference(currentHeading, map.overlayPositionAndScale.getHeading())) > MIN_HEADING_DELTA;
}
boolean needsRepaintForDistance() {
@@ -964,11 +994,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return false;
}
- final CGeoMap cgeoMapRef = map.get();
- if (cgeoMapRef == null) {
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
return false;
}
- final Location lastLocation = cgeoMapRef.overlayPositionAndScale.getCoordinates();
+ final Location lastLocation = map.overlayPositionAndScale.getCoordinates();
float dist = Float.MAX_VALUE;
if (lastLocation != null) {
@@ -976,11 +1006,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
final float[] mapDimension = new float[1];
- if (cgeoMapRef.mapView.getWidth() < cgeoMapRef.mapView.getHeight()) {
- final double span = cgeoMapRef.mapView.getLongitudeSpan() / 1e6;
+ if (map.mapView.getWidth() < map.mapView.getHeight()) {
+ final double span = map.mapView.getLongitudeSpan() / 1e6;
Location.distanceBetween(currentLocation.getLatitude(), currentLocation.getLongitude(), currentLocation.getLatitude(), currentLocation.getLongitude() + span, mapDimension);
} else {
- final double span = cgeoMapRef.mapView.getLatitudeSpan() / 1e6;
+ final double span = map.mapView.getLatitudeSpan() / 1e6;
Location.distanceBetween(currentLocation.getLatitude(), currentLocation.getLongitude(), currentLocation.getLatitude() + span, currentLocation.getLongitude(), mapDimension);
}
@@ -1003,50 +1033,62 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return loadTimer;
}
- /**
- * loading timer Triggers every 250ms and checks for viewport change and starts a {@link LoadRunnable}.
- */
- private Subscription startLoadTimer() {
- return Schedulers.newThread().schedulePeriodically(new Action1<Scheduler.Inner>() {
- @Override
- public void call(Scheduler.Inner inner) {
- try {
- if (mapView != null) {
- // get current viewport
- final Viewport viewportNow = mapView.getViewport();
- // Since zoomNow is used only for local comparison purposes,
- // it is ok to use the Google Maps compatible zoom level of OSM Maps
- final int zoomNow = mapView.getMapZoomLevel();
-
- // check if map moved or zoomed
- //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move
- final boolean moved = markersInvalidated || (isLiveEnabled && !downloaded) || (viewport == null) || zoomNow != zoom ||
- (mapMoved(viewport, viewportNow) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) || !viewport.includes(viewportNow)));
-
- // update title on any change
- if (moved || !viewportNow.equals(viewport)) {
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- }
- zoom = zoomNow;
+ private static final class LoadTimerAction implements Action0 {
- // save new values
- if (moved) {
- markersInvalidated = false;
+ @NonNull private final WeakReference<CGeoMap> mapRef;
+ private int previousZoom = -100;
+ private Viewport previousViewport;
- long currentTime = System.currentTimeMillis();
+ public LoadTimerAction(@NonNull final CGeoMap map) {
+ this.mapRef = new WeakReference<>(map);
+ }
- if (1000 < (currentTime - loadThreadRun)) {
- viewport = viewportNow;
- loadExecutor.execute(new LoadRunnable(viewport));
- }
- }
- }
+ @Override
+ public void call() {
+ final CGeoMap map = mapRef.get();
+ if (map == null) {
+ return;
+ }
+ try {
+ // get current viewport
+ final Viewport viewportNow = map.mapView.getViewport();
+ // Since zoomNow is used only for local comparison purposes,
+ // it is ok to use the Google Maps compatible zoom level of OSM Maps
+ final int zoomNow = map.mapView.getMapZoomLevel();
+
+ // check if map moved or zoomed
+ //TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move
+ final boolean moved = map.markersInvalidated || (map.isLiveEnabled && !map.downloaded) || (previousViewport == null) || zoomNow != previousZoom ||
+ (mapMoved(previousViewport, viewportNow) && (map.cachesCnt <= 0 || CollectionUtils.isEmpty(map.caches) || !previousViewport.includes(viewportNow)));
+
+ // update title on any change
+ if (moved || !viewportNow.equals(previousViewport)) {
+ map.displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ }
+ previousZoom = zoomNow;
- } catch (Exception e) {
- Log.w("CGeoMap.startLoadtimer.start", e);
+ // save new values
+ if (moved) {
+ map.markersInvalidated = false;
+
+ final long currentTime = System.currentTimeMillis();
+
+ if (1000 < (currentTime - map.loadThreadRun)) {
+ previousViewport = viewportNow;
+ loadExecutor.execute(new LoadRunnable(map));
+ }
}
+ } catch (final Exception e) {
+ Log.w("CGeoMap.startLoadtimer.start", e);
}
- }, 250, 250, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ /**
+ * 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);
}
/**
@@ -1066,79 +1108,84 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* started by {@link LoadTimer}
*/
- private class LoadRunnable extends DoRunnable {
+ private static class LoadRunnable extends DoRunnable {
- public LoadRunnable(final Viewport viewport) {
- super(viewport);
+ public LoadRunnable(@NonNull final CGeoMap map) {
+ super(map);
}
@Override
- public void run() {
- try {
- showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
- loadThreadRun = System.currentTimeMillis();
-
- SearchResult searchResult;
- if (mapMode == MapMode.LIVE) {
- searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(viewport, Settings.getCacheType()));
- } else {
- // map started from another activity
- searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult();
- if (geocodeIntent != null) {
- searchResult.addGeocode(geocodeIntent);
- }
- }
- // live mode search result
- if (isLiveEnabled) {
- searchResult.addSearchResult(DataStore.loadCachedInViewport(viewport, Settings.getCacheType()));
- }
+ public void runWithMap(final CGeoMap map) {
+ map.doLoadRun();
+ }
+ }
- downloaded = true;
- Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
- // update the caches
- // new collection type needs to remove first
- caches.removeAll(cachesFromSearchResult);
- caches.addAll(cachesFromSearchResult);
+ private void doLoadRun() {
+ try {
+ showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
+ loadThreadRun = System.currentTimeMillis();
- final boolean excludeMine = Settings.isExcludeMyCaches();
- final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
- if (mapMode == MapMode.LIVE) {
- CGeoMap.filter(caches);
+ SearchResult searchResult;
+ if (mapMode == MapMode.LIVE) {
+ searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(DataStore.loadStoredInViewport(mapView.getViewport(), Settings.getCacheType()));
+ } else {
+ // map started from another activity
+ searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult();
+ if (geocodeIntent != null) {
+ searchResult.addGeocode(geocodeIntent);
}
- countVisibleCaches();
- if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) {
- // we don't want to see any stale waypoints
- waypoints.clear();
- if (isLiveEnabled || mapMode == MapMode.LIVE
- || mapMode == MapMode.COORDS) {
- //All visible waypoints
- CacheType type = Settings.getCacheType();
- Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(viewport, excludeMine, excludeDisabled, type);
- waypoints.addAll(waypointsInViewport);
- }
- else {
- //All waypoints from the viewed caches
- for (Geocache c : caches.getAsList()) {
- waypoints.addAll(c.getWaypoints());
- }
- }
+ }
+ // live mode search result
+ if (isLiveEnabled) {
+ searchResult.addSearchResult(DataStore.loadCachedInViewport(mapView.getViewport(), Settings.getCacheType()));
+ }
+
+ downloaded = true;
+ final Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
+ // update the caches
+ // new collection type needs to remove first
+ caches.removeAll(cachesFromSearchResult);
+ caches.addAll(cachesFromSearchResult);
+
+ final boolean excludeMine = Settings.isExcludeMyCaches();
+ final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
+ if (mapMode == MapMode.LIVE) {
+ CGeoMap.filter(caches);
+ }
+ countVisibleCaches();
+ if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) {
+ // we don't want to see any stale waypoints
+ waypoints.clear();
+ if (isLiveEnabled || mapMode == MapMode.LIVE
+ || mapMode == MapMode.COORDS) {
+ //All visible waypoints
+ final CacheType type = Settings.getCacheType();
+ final Set<Waypoint> waypointsInViewport = DataStore.loadWaypoints(mapView.getViewport(), excludeMine, excludeDisabled, type);
+ waypoints.addAll(waypointsInViewport);
}
else {
- // we don't want to see any stale waypoints when above threshold
- waypoints.clear();
+ //All waypoints from the viewed caches
+ for (final Geocache c : caches.getAsList()) {
+ waypoints.addAll(c.getWaypoints());
+ }
}
+ }
+ else {
+ // we don't want to see any stale waypoints when above threshold
+ waypoints.clear();
+ }
- //render
- displayExecutor.execute(new DisplayRunnable(viewport));
+ //render
+ displayExecutor.execute(new DisplayRunnable(this));
- if (isLiveEnabled) {
- downloadExecutor.execute(new DownloadRunnable(viewport));
- }
- lastSearchResult = searchResult;
- } finally {
- showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
+ if (isLiveEnabled) {
+ downloadExecutor.execute(new DownloadRunnable(this));
}
+ lastSearchResult = searchResult;
+ } finally {
+ showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
+
}
/**
@@ -1146,111 +1193,119 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* Started by {@link LoadRunnable}.
*/
- private class DownloadRunnable extends DoRunnable {
+ private static class DownloadRunnable extends DoRunnable {
- public DownloadRunnable(final Viewport viewport) {
- super(viewport);
+ public DownloadRunnable(final CGeoMap map) {
+ super(map);
}
@Override
- public void run() {
- try {
- showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress
- if (Settings.isGCConnectorActive()) {
- if (tokens == null) {
- tokens = GCLogin.getInstance().getMapTokens();
- if (noMapTokenHandler != null && (StringUtils.isEmpty(tokens.getUserSession()) || StringUtils.isEmpty(tokens.getSessionToken()))) {
- tokens = null;
- noMapTokenHandler.sendEmptyMessage(0);
+ public void runWithMap(final CGeoMap map) {
+ map.doDownloadRun();
+ }
+ }
+
+ private void doDownloadRun() {
+ try {
+ showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress
+ if (Settings.isGCConnectorActive()) {
+ if (tokens == null) {
+ tokens = GCLogin.getInstance().getMapTokens();
+ if (StringUtils.isEmpty(tokens.getUserSession()) || StringUtils.isEmpty(tokens.getSessionToken())) {
+ tokens = null;
+ if (!noMapTokenShowed) {
+ ActivityMixin.showToast(activity, res.getString(R.string.map_token_err));
+ noMapTokenShowed = true;
}
}
}
- final SearchResult searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
- downloaded = true;
-
- Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- CGeoMap.filter(result);
- // update the caches
- // first remove filtered out
- final Set<String> filteredCodes = searchResult.getFilteredGeocodes();
- Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString());
- caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY));
- DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.REMOVE_CACHE));
- // new collection type needs to remove first to refresh
- caches.removeAll(result);
- caches.addAll(result);
- lastSearchResult = searchResult;
-
- //render
- displayExecutor.execute(new DisplayRunnable(viewport));
-
- } catch (ThreadDeath e) {
- Log.d("DownloadThread stopped");
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } finally {
- showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
+ final SearchResult searchResult = ConnectorFactory.searchByViewport(mapView.getViewport().resize(0.8), tokens);
+ downloaded = true;
+
+ final Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ CGeoMap.filter(result);
+ // update the caches
+ // first remove filtered out
+ final Set<String> filteredCodes = searchResult.getFilteredGeocodes();
+ Log.d("Filtering out " + filteredCodes.size() + " caches: " + filteredCodes.toString());
+ caches.removeAll(DataStore.loadCaches(filteredCodes, LoadFlags.LOAD_CACHE_ONLY));
+ DataStore.removeCaches(filteredCodes, EnumSet.of(RemoveFlag.CACHE));
+ // new collection type needs to remove first to refresh
+ caches.removeAll(result);
+ caches.addAll(result);
+ lastSearchResult = searchResult;
+
+ //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
}
}
/**
* Thread to Display (down)loaded caches. Started by {@link LoadRunnable} and {@link DownloadRunnable}
*/
- private class DisplayRunnable extends DoRunnable {
+ private static class DisplayRunnable extends DoRunnable {
- public DisplayRunnable(final Viewport viewport) {
- super(viewport);
+ public DisplayRunnable(@NonNull final CGeoMap map) {
+ super(map);
}
@Override
- public void run() {
- try {
- showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
- if (mapView == null || caches == null) {
- throw new ThreadDeath();
- }
+ public void runWithMap(final CGeoMap map) {
+ map.doDisplayRun();
+ }
+ }
- // display caches
- final List<Geocache> cachesToDisplay = caches.getAsList();
- final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints);
- final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>();
+ private void doDisplayRun() {
+ try {
+ showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
- if (!cachesToDisplay.isEmpty()) {
- // Only show waypoints for single view or setting
- // when less than showWaypointsthreshold Caches shown
- if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) {
- for (Waypoint waypoint : waypointsToDisplay) {
+ // display caches
+ final List<Geocache> cachesToDisplay = caches.getAsList();
+ final List<Waypoint> waypointsToDisplay = new ArrayList<>(waypoints);
+ final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<>();
- if (waypoint == null || waypoint.getCoords() == null) {
- continue;
- }
+ if (!cachesToDisplay.isEmpty()) {
+ // Only show waypoints for single view or setting
+ // when less than showWaypointsthreshold Caches shown
+ if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) {
+ for (final Waypoint waypoint : waypointsToDisplay) {
- itemsToDisplay.add(getWaypointItem(waypoint));
- }
- }
- for (Geocache cache : cachesToDisplay) {
-
- if (cache == null || cache.getCoords() == null) {
+ if (waypoint == null || waypoint.getCoords() == null) {
continue;
}
- itemsToDisplay.add(getCacheItem(cache));
- }
- overlayCaches.updateItems(itemsToDisplay);
- displayHandler.sendEmptyMessage(INVALIDATE_MAP);
+ itemsToDisplay.add(getWaypointItem(waypoint));
+ }
+ }
+ for (final Geocache cache : cachesToDisplay) {
- } else {
- overlayCaches.updateItems(itemsToDisplay);
- displayHandler.sendEmptyMessage(INVALIDATE_MAP);
+ if (cache == null || cache.getCoords() == null) {
+ continue;
+ }
+ itemsToDisplay.add(getCacheItem(cache));
}
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } catch (ThreadDeath e) {
- Log.d("DisplayThread stopped");
- displayHandler.sendEmptyMessage(UPDATE_TITLE);
- } finally {
- showProgressHandler.sendEmptyMessage(HIDE_PROGRESS);
+ overlayCaches.updateItems(itemsToDisplay);
+ displayHandler.sendEmptyMessage(INVALIDATE_MAP);
+
+ } else {
+ overlayCaches.updateItems(itemsToDisplay);
+ displayHandler.sendEmptyMessage(INVALIDATE_MAP);
}
+
+ displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ } catch (final ThreadDeath e) {
+ Log.d("DisplayThread stopped");
+ displayHandler.sendEmptyMessage(UPDATE_TITLE);
+ } finally {
+ showProgressHandler.sendEmptyMessage(HIDE_PROGRESS);
}
}
@@ -1268,11 +1323,21 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static abstract class DoRunnable implements Runnable {
- final protected Viewport viewport;
+ private final WeakReference<CGeoMap> mapRef;
- protected DoRunnable(final Viewport viewport) {
- this.viewport = viewport;
+ protected DoRunnable(@NonNull final CGeoMap map) {
+ mapRef = new WeakReference<>(map);
}
+
+ @Override
+ final public void run() {
+ final CGeoMap map = mapRef.get();
+ if (map != null) {
+ runWithMap(map);
+ }
+ }
+
+ abstract protected void runWithMap(final CGeoMap map);
}
/**
@@ -1281,7 +1346,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
* @param listId
* the list to store the caches in
*/
- private void storeCaches(List<String> geocodes, int listId) {
+ private void storeCaches(final List<String> geocodes, final int listId) {
final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler();
waitDialog = new ProgressDialog(activity);
@@ -1292,23 +1357,23 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
waitDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
- public void onCancel(DialogInterface arg0) {
+ public void onCancel(final DialogInterface arg0) {
try {
if (loadDetailsThread != null) {
loadDetailsThread.stopIt();
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("CGeoMap.storeCaches.onCancel", e);
}
}
});
- float etaTime = detailTotal * 7.0f / 60.0f;
- int roundedEta = Math.round(etaTime);
+ final float etaTime = detailTotal * 7.0f / 60.0f;
+ final int roundedEta = Math.round(etaTime);
if (etaTime < 0.4) {
waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm));
} else {
- waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + roundedEta + " " + res.getQuantityString(R.plurals.caches_eta_mins, roundedEta));
+ waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getQuantityString(R.plurals.caches_eta_mins, roundedEta, roundedEta));
}
waitDialog.show();
@@ -1353,7 +1418,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (!DataStore.isOffline(geocode, null)) {
Geocache.storeCache(null, geocode, listId, false, handler);
}
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("CGeoMap.LoadDetails.run", e);
} finally {
// one more cache over
@@ -1367,13 +1432,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
- private static synchronized void filter(Collection<Geocache> caches) {
- boolean excludeMine = Settings.isExcludeMyCaches();
- boolean excludeDisabled = Settings.isExcludeDisabledCaches();
+ private static synchronized void filter(final Collection<Geocache> caches) {
+ final boolean excludeMine = Settings.isExcludeMyCaches();
+ final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
- List<Geocache> removeList = new ArrayList<Geocache>();
- for (Geocache cache : caches) {
- if ((excludeMine && cache.isFound()) || (excludeMine && cache.isOwner()) || (excludeDisabled && cache.isDisabled())) {
+ final List<Geocache> removeList = new ArrayList<>();
+ for (final Geocache cache : caches) {
+ if ((excludeMine && cache.isFound()) || (excludeMine && cache.isOwner()) || (excludeDisabled && cache.isDisabled()) || (excludeDisabled && cache.isArchived())) {
removeList.add(cache);
}
}
@@ -1392,9 +1457,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (coords == null) {
return;
}
- if (mapView == null) {
- return;
- }
final MapControllerImpl mapController = mapView.getMapController();
final GeoPointImpl target = makeGeoPoint(coords);
@@ -1410,14 +1472,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
// move map to view results of searchIntent
- private void centerMap(String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, int[] mapState) {
+ private void centerMap(final String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, final int[] mapState) {
final MapControllerImpl mapController = mapView.getMapController();
if (!centered && mapState != null) {
try {
mapController.setCenter(mapItemFactory.getGeoPointBase(new Geopoint(mapState[0] / 1.0e6, mapState[1] / 1.0e6)));
setZoom(mapState[2]);
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("centermap", e);
}
@@ -1441,7 +1503,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (viewport.getLatitudeSpan() != 0 && viewport.getLongitudeSpan() != 0) {
mapController.zoomToSpan((int) (viewport.getLatitudeSpan() * 1e6), (int) (viewport.getLongitudeSpan() * 1e6));
}
- } catch (RuntimeException e) {
+ } catch (final RuntimeException e) {
Log.e("centermap", e);
}
@@ -1450,7 +1512,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
} else if (!centered && coordsCenter != null) {
try {
mapController.setCenter(makeGeoPoint(coordsCenter));
- } catch (Exception e) {
+ } catch (final Exception e) {
Log.e("centermap", e);
}
@@ -1461,25 +1523,54 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// switch My Location button image
private void switchMyLocationButton() {
+ myLocSwitch.setChecked(followMyLocation);
if (followMyLocation) {
- myLocSwitch.setImageResource(R.drawable.actionbar_mylocation_on);
myLocationInMiddle(app.currentGeo());
- } else {
- myLocSwitch.setImageResource(R.drawable.actionbar_mylocation_off);
}
}
// set my location listener
- private class MyLocationListener implements View.OnClickListener {
+ private static class MyLocationListener implements View.OnClickListener {
+
+ private final WeakReference<CGeoMap> mapRef;
+
+ public MyLocationListener(@NonNull final CGeoMap map) {
+ mapRef = new WeakReference<>(map);
+ }
+
@Override
- public void onClick(View view) {
- followMyLocation = !followMyLocation;
- switchMyLocationButton();
+ public void onClick(final View view) {
+ final CGeoMap map = mapRef.get();
+ if (map != null) {
+ map.onFollowMyLocationClicked();
+ }
}
}
- @Override
- public void onDrag() {
+ private void onFollowMyLocationClicked() {
+ followMyLocation = !followMyLocation;
+ switchMyLocationButton();
+ }
+
+ public static class MapDragListener implements OnMapDragListener {
+
+ private final WeakReference<CGeoMap> mapRef;
+
+ public MapDragListener(@NonNull final CGeoMap map) {
+ mapRef = new WeakReference<>(map);
+ }
+
+ @Override
+ public void onDrag() {
+ final CGeoMap map = mapRef.get();
+ if (map != null) {
+ map.onDrag();
+ }
+ }
+
+ }
+
+ private void onDrag() {
if (followMyLocation) {
followMyLocation = false;
switchMyLocationButton();
@@ -1491,15 +1582,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return mapItemFactory.getGeoPointBase(coords);
}
- // close activity and open homescreen
- @Override
- public void goHome(View view) {
- ActivityMixin.goHome(activity);
- }
-
@Override
public View makeView() {
- ImageView imageView = new ImageView(activity);
+ final ImageView imageView = new ImageView(activity);
imageView.setScaleType(ScaleType.CENTER);
imageView.setLayoutParams(new ImageSwitcher.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
return imageView;
@@ -1556,88 +1641,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private CachesOverlayItemImpl getCacheItem(final Geocache cache) {
final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(cache, cache.applyDistanceRule());
-
- final int hashcode = new HashCodeBuilder()
- .append(cache.isReliableLatLon())
- .append(cache.getType().id)
- .append(cache.isDisabled() || cache.isArchived())
- .append(cache.getMapMarkerId())
- .append(cache.isOwner())
- .append(cache.isFound())
- .append(cache.hasUserModifiedCoords())
- .append(cache.getPersonalNote())
- .append(cache.isLogOffline())
- .append(cache.getListId() > 0)
- .toHashCode();
-
- LayerDrawable drawable = overlaysCache.get(hashcode);
- if (drawable == null) {
- drawable = createCacheItem(cache, hashcode);
- }
- item.setMarker(drawable);
+ item.setMarker(MapUtils.getCacheItem(getResources(), cache));
return item;
}
- private LayerDrawable createCacheItem(final Geocache cache, final int hashcode) {
- // Set initial capacities to the maximum of layers and insets to avoid dynamic reallocation
- final ArrayList<Drawable> layers = new ArrayList<Drawable>(9);
- final ArrayList<int[]> insets = new ArrayList<int[]>(8);
-
- // background: disabled or not
- final Drawable marker = getResources().getDrawable(cache.getMapMarkerId());
- layers.add(marker);
- final int resolution = marker.getIntrinsicWidth() > 40 ? (marker.getIntrinsicWidth() > 50 ? 2 : 1) : 0;
- // reliable or not
- if (!cache.isReliableLatLon()) {
- insets.add(INSET_RELIABLE[resolution]);
- layers.add(getResources().getDrawable(R.drawable.marker_notreliable));
- }
- // cache type
- layers.add(getResources().getDrawable(cache.getType().markerId));
- insets.add(INSET_TYPE[resolution]);
- // own
- if (cache.isOwner()) {
- layers.add(getResources().getDrawable(R.drawable.marker_own));
- insets.add(INSET_OWN[resolution]);
- // if not, checked if stored
- } else if (cache.getListId() > 0) {
- layers.add(getResources().getDrawable(R.drawable.marker_stored));
- insets.add(INSET_OWN[resolution]);
- }
- // found
- if (cache.isFound()) {
- layers.add(getResources().getDrawable(R.drawable.marker_found));
- insets.add(INSET_FOUND[resolution]);
- // if not, perhaps logged offline
- } else if (cache.isLogOffline()) {
- layers.add(getResources().getDrawable(R.drawable.marker_found_offline));
- insets.add(INSET_FOUND[resolution]);
- }
- // user modified coords
- if (cache.hasUserModifiedCoords()) {
- layers.add(getResources().getDrawable(R.drawable.marker_usermodifiedcoords));
- insets.add(INSET_USERMODIFIEDCOORDS[resolution]);
- }
- // personal note
- if (cache.getPersonalNote() != null) {
- layers.add(getResources().getDrawable(R.drawable.marker_personalnote));
- insets.add(INSET_PERSONALNOTE[resolution]);
- }
-
- final LayerDrawable ld = new LayerDrawable(layers.toArray(new Drawable[layers.size()]));
-
- int index = 1;
- for (final int[] inset : insets) {
- ld.setLayerInset(index++, inset[0], inset[1], inset[2], inset[3]);
- }
-
- overlaysCache.put(hashcode, ld);
- return ld;
- }
-
private CachesOverlayItemImpl getWaypointItem(final Waypoint waypoint) {
final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(waypoint, waypoint.getWaypointType().applyDistanceRule());
- Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent);
+ final Drawable marker = getResources().getDrawable(!waypoint.isVisited() ? R.drawable.marker : R.drawable.marker_transparent);
final Drawable[] layers = new Drawable[] {
marker,
getResources().getDrawable(waypoint.getWaypointType().markerId)