diff options
Diffstat (limited to 'main/src')
31 files changed, 420 insertions, 577 deletions
diff --git a/main/src/cgeo/geocaching/CacheCache.java b/main/src/cgeo/geocaching/CacheCache.java index a84f1bd..1ebb47f 100644 --- a/main/src/cgeo/geocaching/CacheCache.java +++ b/main/src/cgeo/geocaching/CacheCache.java @@ -1,10 +1,18 @@ package cgeo.geocaching; import cgeo.geocaching.cgData.StorageLocation; +import cgeo.geocaching.connector.gc.GCBase; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.utils.LeastRecentlyUsedMap; +import cgeo.geocaching.utils.LeastRecentlyUsedMap.RemoveHandler; +import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; +import java.util.HashSet; +import java.util.Set; + /** * Cache for Caches. Every cache is stored in memory while c:geo is active to * speed up the app and to minimize network request - which are slow. @@ -15,11 +23,14 @@ public class CacheCache { private static final int MAX_CACHED_CACHES = 1000; final private LeastRecentlyUsedMap<String, cgCache> cachesCache; + final private RemoveHandler<cgCache> removeHandler; private static CacheCache instance = null; private CacheCache() { cachesCache = new LeastRecentlyUsedMap.LruCache<String, cgCache>(MAX_CACHED_CACHES); + removeHandler = new CacheRemoveHandler(); + cachesCache.setRemoveHandler(removeHandler); } public static CacheCache getInstance() { @@ -74,9 +85,34 @@ public class CacheCache { return cachesCache.get(geocode); } + public Set<String> getInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { + final Set<String> geocodes = new HashSet<String>(); + for (final cgCache cache : cachesCache.values()) { + if (cache.getCoords() == null) { + // FIXME: this kludge must be removed, it is only present to help us debug the cases where + // caches contain null coordinates. + Log.e(Settings.tag, "CacheCache.getInViewport: got cache with null coordinates: " + cache.getGeocode()); + continue; + } + if ((CacheType.ALL == cacheType || cache.getType() == cacheType) && + Viewport.isCacheInViewPort(centerLat.intValue(), centerLon.intValue(), spanLat.intValue(), spanLon.intValue(), cache.getCoords())) { + geocodes.add(cache.getGeocode()); + } + } + return geocodes; + } + @Override public String toString() { return StringUtils.join(cachesCache.keySet(), ' '); } + private class CacheRemoveHandler implements RemoveHandler<cgCache> { + + @Override + public void onRemove(cgCache removed) { + GCBase.removeFromTileCache(removed.getCoords()); + } + } + } diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index dfd8dde..755115a 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -832,25 +832,6 @@ public class CacheDetailActivity extends AbstractActivity { } /** - * Creates a {@link List} of all coordinates (cache and waypoints) for the current cache. - * - * @return A {@link List} of all coordinates - */ - public List<IWaypoint> getCoordinates() { - List<IWaypoint> coordinates = new ArrayList<IWaypoint>(); - - // cache - coordinates.add(cache); - - // waypoints - if (cache.hasWaypoints()) { - coordinates.addAll(cache.getWaypoints()); - } - - return coordinates; - } - - /** * Tries to navigate to the {@link cgCache} of this activity. */ private void startDefaultNavigation() { diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java index e7c9a88..f7458fe 100644 --- a/main/src/cgeo/geocaching/SearchResult.java +++ b/main/src/cgeo/geocaching/SearchResult.java @@ -7,7 +7,6 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.gcvote.GCVote; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.os.Parcel; @@ -201,14 +200,4 @@ public class SearchResult implements Parcelable { return cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE)); } - /** Add the cache geocodes to the search and store them in the CacheCache */ - public void addCaches(final Set<cgCache> caches) { - if (CollectionUtils.isEmpty(caches)) { - return; - } - - for (final cgCache cache : caches) { - addCache(cache); - } - } } diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 9080b3f..b52571a 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -110,7 +110,7 @@ public final class Settings { } } - // usable values + // FIXME: tag should be private member of our log class public static final String tag = "cgeo"; private static String username = null; @@ -201,10 +201,6 @@ public final class Settings { e.commit(); cachedDebug = sharedPrefs.getBoolean(KEY_DEBUG, false); } - final SharedPreferences old = cgeoapplication.getInstance().getSharedPreferences("cgeo.pref", Context.MODE_PRIVATE); - System.out.println("old prefs " + old.getString(KEY_USERNAME, "not set")); - System.out.println("shared prefs " + sharedPrefs.getString(KEY_USERNAME, "no set")); - } public static void setLanguage(boolean useEnglish) { diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 9c17a34..17601af 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -1,7 +1,6 @@ package cgeo.geocaching; import cgeo.geocaching.concurrent.BlockingThreadPool; -import cgeo.geocaching.concurrent.Task; import cgeo.geocaching.files.LocalStorage; import cgeo.geocaching.geopoint.GeopointFormatter.Format; import cgeo.geocaching.network.Network; @@ -146,7 +145,7 @@ public class StaticMapsProvider { downloadDifferentZooms(cache, markerUrl, prefix, latlonMap, edge, waypoints); } else { - Task currentTask = new Task("getting static map") { + final Runnable currentTask = new Runnable() { @Override public void run() { downloadDifferentZooms(cache, markerUrl, prefix, latlonMap, edge, waypoints); diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java index dd22cff..2503b99 100644 --- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java +++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java @@ -1,8 +1,5 @@ package cgeo.geocaching.activity; -import cgeo.geocaching.cgCache; - -import android.view.Menu; import android.view.View; public interface IAbstractActivity { @@ -13,19 +10,11 @@ public interface IAbstractActivity { public void goManual(View view); - public void showProgress(final boolean show); - - public void setTheme(); - public void showToast(String text); public void showShortToast(String text); public void helpDialog(String title, String message); - public void setTitle(final String title); - - void addVisitMenu(Menu menu, cgCache cache); - public void invalidateOptionsMenuCompatible(); } diff --git a/main/src/cgeo/geocaching/cgBase.java b/main/src/cgeo/geocaching/cgBase.java index 090bffc..a1bb980 100644 --- a/main/src/cgeo/geocaching/cgBase.java +++ b/main/src/cgeo/geocaching/cgBase.java @@ -1,7 +1,6 @@ // $codepro.audit.disable logExceptions package cgeo.geocaching; -import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.ConnectorFactory; import cgeo.geocaching.connector.gc.GCConnector; import cgeo.geocaching.connector.gc.GCConstants; @@ -1866,54 +1865,6 @@ public class cgBase { } } - public static boolean runNavigation(Activity activity, Resources res, Settings settings, final Geopoint coords) { - return runNavigation(activity, res, settings, coords, null); - } - - public static boolean runNavigation(Activity activity, Resources res, Settings settings, final Geopoint coords, final Geopoint coordsNow) { - if (activity == null) { - return false; - } - if (settings == null) { - return false; - } - - // Google Navigation - if (Settings.isUseGoogleNavigation()) { - try { - activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:ll=" + coords.getLatitude() + "," + coords.getLongitude()))); - - return true; - } catch (Exception e) { - // nothing - } - } - - // Google Maps Directions - try { - if (coordsNow != null) { - activity.startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("http://maps.google.com/maps?f=d&saddr=" + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + - "&daddr=" + coords.getLatitude() + "," + coords.getLongitude()))); - } else { - activity.startActivity(new Intent(Intent.ACTION_VIEW, - Uri.parse("http://maps.google.com/maps?f=d&daddr=" + coords.getLatitude() + "," + coords.getLongitude()))); - } - - return true; - } catch (Exception e) { - // nothing - } - - Log.i(Settings.tag, "cgBase.runNavigation: No navigation application available."); - - if (res != null) { - ActivityMixin.showToast(activity, res.getString(R.string.err_navigation_no)); - } - - return false; - } - /** * Generate a time string according to system-wide settings (locale, 12/24 hour) * such as "13:24". diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java index 36fd064..f2a773d 100644 --- a/main/src/cgeo/geocaching/cgCache.java +++ b/main/src/cgeo/geocaching/cgCache.java @@ -99,7 +99,7 @@ public class cgCache implements ICache, IWaypoint { private String nameForSorting; private final EnumSet<StorageLocation> storageLocation = EnumSet.of(StorageLocation.HEAP); private boolean finalDefined = false; - private int zoomlevel = Tile.ZOOMLEVEL_MAX; + private int zoomlevel = Tile.ZOOMLEVEL_MAX + 1; private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+"); @@ -401,8 +401,7 @@ public class cgCache implements ICache, IWaypoint { } public boolean isEventCache() { - return CacheType.EVENT == cacheType || CacheType.MEGA_EVENT == cacheType - || CacheType.CITO == cacheType || CacheType.LOSTANDFOUND == cacheType; + return cacheType.isEvent(); } public boolean logVisit(IAbstractActivity fromActivity) { @@ -1401,10 +1400,6 @@ public class cgCache implements ICache, IWaypoint { cgBase.storeCache(activity, this, null, listId, false, handler); } - public int getZoomlevel() { - return this.zoomlevel; - } - public void setZoomlevel(int zoomlevel) { this.zoomlevel = zoomlevel; } diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index d1b9e07..281d098 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -2722,23 +2722,36 @@ public class cgData { } /** Retrieve all stored caches from DB */ - public Set<String> loadCachedInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { + public Set<String> loadCachedInViewport(final long centerLat, final long centerLon, final long spanLat, final long spanLon, final CacheType cacheType) { return loadInViewport(false, centerLat, centerLon, spanLat, spanLon, cacheType); } /** Retrieve stored caches from DB with listId >= 1 */ - public Set<String> loadStoredInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { + public Set<String> loadStoredInViewport(final long centerLat, final long centerLon, final long spanLat, final long spanLon, final CacheType cacheType) { return loadInViewport(true, centerLat, centerLon, spanLat, spanLon, cacheType); } - public Set<String> loadInViewport(final boolean stored, final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { - if (centerLat == null || centerLon == null || spanLat == null || spanLon == null) { - return null; - } - + /** + * Loads the geocodes of caches in a viewport from CacheCache and/or Database + * + * @param stored + * True - query only stored caches, False - query cached ones as well + * @param centerLat + * @param centerLon + * @param spanLat + * @param spanLon + * @param cacheType + * @return Set with geocodes + */ + private Set<String> loadInViewport(final boolean stored, final long centerLat, final long centerLon, final long spanLat, final long spanLon, final CacheType cacheType) { init(); - Set<String> geocodes = new HashSet<String>(); + final Set<String> geocodes = new HashSet<String>(); + + // if not stored only, get codes from CacheCache as well + if (!stored) { + geocodes.addAll(CacheCache.getInstance().getInViewport(centerLat, centerLon, spanLat, spanLon, cacheType)); + } // viewport limitation StringBuilder where = buildCoordinateWhere(centerLat, centerLon, spanLat, spanLon); @@ -2756,7 +2769,7 @@ public class cgData { } try { - Cursor cursor = databaseRO.query( + final Cursor cursor = databaseRO.query( dbTableCaches, new String[] { "geocode" }, where.toString(), @@ -2766,21 +2779,14 @@ public class cgData { null, "500"); - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("geocode"); + if (cursor.moveToFirst()) { + final int index = cursor.getColumnIndex("geocode"); - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } else { - cursor.close(); - return null; - } - - cursor.close(); + do { + geocodes.add(cursor.getString(index)); + } while (cursor.moveToNext()); } + cursor.close(); } catch (Exception e) { Log.e(Settings.tag, "cgData.loadInViewport: " + e.toString()); } @@ -2788,58 +2794,6 @@ public class cgData { return geocodes; } - public List<String> getOfflineAll(CacheType cacheType) { - init(); - - List<String> geocodes = new ArrayList<String>(); - - StringBuilder where = new StringBuilder(); - - // cacheType limitation - if (cacheType != CacheType.ALL) { - where.append(cacheType); - where.append('"'); - } - - // offline caches only - if (where.length() > 0) { - where.append(" and "); - } - where.append("reason >= 1"); - - try { - Cursor cursor = databaseRO.query( - dbTableCaches, - new String[] { "geocode" }, - where.toString(), - null, - null, - null, - null, - "5000"); - - if (cursor != null) { - if (cursor.getCount() > 0) { - cursor.moveToFirst(); - int index = cursor.getColumnIndex("geocode"); - - do { - geocodes.add(cursor.getString(index)); - } while (cursor.moveToNext()); - } else { - cursor.close(); - return null; - } - - cursor.close(); - } - } catch (Exception e) { - Log.e(Settings.tag, "cgData.getOfflineAll: " + e.toString()); - } - - return geocodes; - } - public boolean markFound(String geocode) { if (StringUtils.isBlank(geocode)) { return false; diff --git a/main/src/cgeo/geocaching/cgWaypoint.java b/main/src/cgeo/geocaching/cgWaypoint.java index 8f9ec85..ee865ee 100644 --- a/main/src/cgeo/geocaching/cgWaypoint.java +++ b/main/src/cgeo/geocaching/cgWaypoint.java @@ -179,10 +179,6 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> { return waypointType; } - public void setWaypointType(WaypointType type) { - this.waypointType = type; - } - public String getLookup() { return lookup; } diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java index 07d33ec..7d01093 100644 --- a/main/src/cgeo/geocaching/cgeo.java +++ b/main/src/cgeo/geocaching/cgeo.java @@ -151,9 +151,9 @@ public class cgeo extends AbstractActivity { final int satellitesFixed = msg.arg1; final int satellitesVisible = msg.arg2; if (satellitesFixed > 0) { - satellites = res.getString(R.string.loc_sat) + ": " + satellitesFixed + "/" + satellitesVisible; + satellites = res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible; } else if (satellitesVisible >= 0) { - satellites = res.getString(R.string.loc_sat) + ": 0/" + geo.satellitesVisible; + satellites = res.getString(R.string.loc_sat) + ": 0/" + satellitesVisible; } break; } diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java index 92c0005..b43cf05 100644 --- a/main/src/cgeo/geocaching/cgeoapplication.java +++ b/main/src/cgeo/geocaching/cgeoapplication.java @@ -308,14 +308,14 @@ public class cgeoapplication extends Application { return new SearchResult(geocodes, getAllHistoricCachesCount()); } - /** {@link cgData#loadCachedInViewport(Long, Long, Long, Long, CacheType)} */ - public SearchResult getCachedInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { + /** {@link cgData#loadCachedInViewport(long, long, long, long, CacheType)} */ + public SearchResult getCachedInViewport(final long centerLat, final long centerLon, final long spanLat, final long spanLon, final CacheType cacheType) { final Set<String> geocodes = storage.loadCachedInViewport(centerLat, centerLon, spanLat, spanLon, cacheType); return new SearchResult(geocodes); } - /** {@link cgData#loadStoredInViewport(Long, Long, Long, Long, CacheType)} */ - public SearchResult getStoredInViewport(final Long centerLat, final Long centerLon, final Long spanLat, final Long spanLon, final CacheType cacheType) { + /** {@link cgData#loadStoredInViewport(long, long, long, long, CacheType)} */ + public SearchResult getStoredInViewport(final long centerLat, final long centerLon, final long spanLat, final long spanLon, final CacheType cacheType) { final Set<String> geocodes = storage.loadStoredInViewport(centerLat, centerLon, spanLat, spanLon, cacheType); return new SearchResult(geocodes); } diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 09c0f5a..7d165b3 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -505,7 +505,7 @@ public class cgeocaches extends AbstractListActivity { if (Intent.ACTION_VIEW.equals(getIntent().getAction())) { type = CacheListType.OFFLINE; if (coords == null) { - coords = new Geopoint(0, 0); + coords = new Geopoint(0.0, 0.0); } } diff --git a/main/src/cgeo/geocaching/cgeocoords.java b/main/src/cgeo/geocaching/cgeocoords.java index b4868ce..fdedfda 100644 --- a/main/src/cgeo/geocaching/cgeocoords.java +++ b/main/src/cgeo/geocaching/cgeocoords.java @@ -419,7 +419,7 @@ public class cgeocoords extends Dialog { if (geo != null && geo.coordsNow != null) { gp = geo.coordsNow; } else { - gp = new Geopoint(0, 0); + gp = new Geopoint(0.0, 0.0); } } } diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java index f5da2a1..0cbd30f 100644 --- a/main/src/cgeo/geocaching/cgeonavigate.java +++ b/main/src/cgeo/geocaching/cgeonavigate.java @@ -294,23 +294,6 @@ public class cgeonavigate extends AbstractActivity { ((TextView) findViewById(R.id.destination)).setText(dstCoords.toString()); } - public void setDest(final Geopoint coords) { - if (coords == null) { - return; - } - - title = "some place"; - setTitle(); - setDestCoords(); - - dstCoords = coords; - updateDistanceInfo(); - } - - public Geopoint getCoordinatesNow() { - return geo.coordsNow; - } - private void updateDistanceInfo() { if (geo == null || geo.coordsNow == null || dstCoords == null) { return; diff --git a/main/src/cgeo/geocaching/cgeowaypointadd.java b/main/src/cgeo/geocaching/cgeowaypointadd.java index 4bc5be0..28d9934 100644 --- a/main/src/cgeo/geocaching/cgeowaypointadd.java +++ b/main/src/cgeo/geocaching/cgeowaypointadd.java @@ -9,6 +9,7 @@ import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.GeopointFormatter; import cgeo.geocaching.geopoint.GeopointParser; +import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -72,7 +73,12 @@ public class cgeowaypointadd extends AbstractActivity { ((Button) findViewById(R.id.buttonLongitude)).setText(waypoint.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE)); } ((EditText) findViewById(R.id.name)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getName())).toString()); - ((EditText) findViewById(R.id.note)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString()); + if (BaseUtils.containsHtml(waypoint.getNote())) { + ((EditText) findViewById(R.id.note)).setText(Html.fromHtml(StringUtils.trimToEmpty(waypoint.getNote())).toString()); + } + else { + ((EditText) findViewById(R.id.note)).setText(StringUtils.trimToEmpty(waypoint.getNote())); + } } if (own) { diff --git a/main/src/cgeo/geocaching/concurrent/Task.java b/main/src/cgeo/geocaching/concurrent/Task.java deleted file mode 100644 index 2472538..0000000 --- a/main/src/cgeo/geocaching/concurrent/Task.java +++ /dev/null @@ -1,16 +0,0 @@ -package cgeo.geocaching.concurrent; - -/** - * Basic class for Runnables added to ThreadPool. - */ -public abstract class Task implements Runnable { - private String name = null; - - public Task(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } -} diff --git a/main/src/cgeo/geocaching/connector/gc/GCBase.java b/main/src/cgeo/geocaching/connector/gc/GCBase.java index d09f9af..2f79fab 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCBase.java +++ b/main/src/cgeo/geocaching/connector/gc/GCBase.java @@ -31,6 +31,7 @@ import android.graphics.Bitmap; import java.text.ParseException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -52,6 +53,9 @@ public class GCBase { protected final static long GC_BASE31 = 31; protected final static long GC_BASE16 = 16; + private final static LeastRecentlyUsedMap<Integer, Tile> tileCache = new LeastRecentlyUsedMap.LruCache<Integer, Tile>(64); + private static Viewport lastSearchViewport = null; + /** * Searches the view port on the live map with Strategy.AUTO * @@ -84,6 +88,17 @@ public class GCBase { } } + public static void removeFromTileCache(Geopoint coords) { + if (coords != null) { + Collection<Tile> tiles = new ArrayList<Tile>(tileCache.values()); + for (Tile tile : tiles) { + if (tile.containsPoint(coords)) { + tileCache.remove(tile.hashCode()); + } + } + } + } + /** * Searches the view port on the live map for caches. * The strategy dictates if only live map information is used or if an additional @@ -110,58 +125,78 @@ public class GCBase { for (Tile tile : tiles) { - StringBuilder url = new StringBuilder(); - url.append("?x=").append(tile.getX()) // x tile - .append("&y=").append(tile.getY()) // y tile - .append("&z=").append(tile.getZoomlevel()); // zoom level - if (tokens != null) { - url.append("&k=").append(tokens[0]); // user session - url.append("&st=").append(tokens[1]); // session token - } - url.append("&ep=1"); - if (Settings.isExcludeMyCaches()) { - url.append("&hf=1").append("&hh=1"); // hide found, hide hidden - } - if (Settings.getCacheType() == CacheType.TRADITIONAL) { - url.append("&ect=9,5,3,6,453,13,1304,137,11,4,8,1858"); // 2 = tradi 3 = multi 8 = mystery - } - if (Settings.getCacheType() == CacheType.MULTI) { - url.append("&ect=9,5,2,6,453,13,1304,137,11,4,8,1858"); - } - if (Settings.getCacheType() == CacheType.MYSTERY) { - url.append("&ect=9,5,3,6,453,13,1304,137,11,4,2,1858"); - } - if (tile.getZoomlevel() != 14) { - url.append("&_=").append(String.valueOf(System.currentTimeMillis())); - } - // other types t.b.d - final String urlString = url.toString(); + if (!tileCache.containsKey(tile.hashCode())) { - // The PNG must be request before ! Else the following request would return with 204 - No Content - Bitmap bitmap = Tile.requestMapTile(GCConstants.URL_MAP_TILE + urlString, referer); + StringBuilder url = new StringBuilder(); + url.append("?x=").append(tile.getX()) // x tile + .append("&y=").append(tile.getY()) // y tile + .append("&z=").append(tile.getZoomlevel()); // zoom level + if (tokens != null) { + url.append("&k=").append(tokens[0]); // user session + url.append("&st=").append(tokens[1]); // session token + } + url.append("&ep=1"); + if (Settings.isExcludeMyCaches()) { + url.append("&hf=1").append("&hh=1"); // hide found, hide hidden + } + if (Settings.getCacheType() == CacheType.TRADITIONAL) { + url.append("&ect=9,5,3,6,453,13,1304,137,11,4,8,1858"); // 2 = tradi 3 = multi 8 = mystery + } + if (Settings.getCacheType() == CacheType.MULTI) { + url.append("&ect=9,5,2,6,453,13,1304,137,11,4,8,1858"); + } + if (Settings.getCacheType() == CacheType.MYSTERY) { + url.append("&ect=9,5,3,6,453,13,1304,137,11,4,2,1858"); + } + if (tile.getZoomlevel() != 14) { + url.append("&_=").append(String.valueOf(System.currentTimeMillis())); + } + // other types t.b.d + final String urlString = url.toString(); - assert bitmap.getWidth() == Tile.TILE_SIZE : "Bitmap has wrong width"; - assert bitmap.getHeight() == Tile.TILE_SIZE : "Bitmap has wrong height"; + // The PNG must be requested first, otherwise the following request would always return with 204 - No Content + Bitmap bitmap = Tile.requestMapTile(GCConstants.URL_MAP_TILE + urlString, referer); - String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO + urlString, referer); - if (StringUtils.isEmpty(data)) { - Log.e(Settings.tag, "GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); - } else { - final SearchResult search = parseMapJSON(data, tile, bitmap, strategy); - if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) { - Log.e(Settings.tag, "GCBase.searchByViewport: No cache parsed for viewport " + viewport); + // Check bitmap size + if (bitmap.getWidth() != Tile.TILE_SIZE || + bitmap.getHeight() != Tile.TILE_SIZE) { + bitmap.recycle(); + bitmap = null; + } + + String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO + urlString, referer); + if (StringUtils.isEmpty(data)) { + Log.e(Settings.tag, "GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); + } else { + final SearchResult search = parseMapJSON(data, tile, bitmap, strategy); + if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) { + Log.e(Settings.tag, "GCBase.searchByViewport: No cache parsed for viewport " + viewport); + } + else { + searchResult.addGeocodes(search.getGeocodes()); + } + tileCache.put(tile.hashCode(), tile); } - else { - searchResult.addGeocodes(search.getGeocodes()); + + // release native bitmap memory + if (bitmap != null) { + bitmap.recycle(); } + } } } if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) { - SearchResult search = cgBase.searchByCoords(null, viewport.getCenter(), Settings.getCacheType(), false); - if (search != null) { - searchResult.addGeocodes(search.getGeocodes()); + Geopoint center = viewport.getCenter(); + if ((lastSearchViewport == null) || !lastSearchViewport.isInViewport(center)) { + SearchResult search = cgBase.searchByCoords(null, center, Settings.getCacheType(), false); + if (search != null) { + + List<Number> bounds = cgeoapplication.getInstance().getBounds(search.getGeocodes()); + lastSearchViewport = new Viewport(bounds.get(1).doubleValue(), bounds.get(2).doubleValue(), bounds.get(4).doubleValue(), bounds.get(3).doubleValue()); + searchResult.addGeocodes(search.getGeocodes()); + } } } @@ -265,7 +300,7 @@ public class GCBase { cache.setName(nameCache.get(id)); cache.setZoomlevel(tile.getZoomlevel()); cache.setCoords(tile.getCoord(xy)); - if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && positions.size() < 64) { + if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && positions.size() < 64 && bitmap != null) { // don't parse if there are too many caches. The decoding would return too much wrong results IconDecoder.parseMapPNG(cache, bitmap, xy, tile.getZoomlevel()); } else { @@ -325,62 +360,6 @@ public class GCBase { return gcid; } - private static String modulo(final long value, final long base, final String sequence) { - String result = ""; - long rest = 0; - long divResult = value; - do - { - rest = divResult % base; - divResult = (int) Math.floor(divResult / base); - result = sequence.charAt((int) rest) + result; - } while (divResult != 0); - return result; - } - - /** - * Convert (old) GCIds to GCCode (geocode) - * - * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 - */ - public static String gcidToGCCode(final long gcid) { - String gccode = modulo(gcid + 411120, GC_BASE31, SEQUENCE_GCID); - if ((gccode.length() < 4) || (gccode.length() == 4 && SEQUENCE_GCID.indexOf(gccode.charAt(0)) < 16)) { - gccode = modulo(gcid, GC_BASE16, SEQUENCE_GCID); - } - return "GC" + gccode; - } - - /** - * Convert ids from the live map to (old) GCIds - * - * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 - */ - public static long newidToGCId(final String newid) { - long gcid = 0; - for (int p = 0; p < newid.length(); p++) { - gcid = GC_BASE57 * gcid + SEQUENCE_NEWID.indexOf(newid.charAt(p)); - } - return gcid; - } - - /** - * Convert (old) GCIds to ids used in the live map - * - * Based on http://www.geoclub.de/viewtopic.php?f=111&t=54859&start=40 - */ - public static String gcidToNewId(final long gcid) { - return modulo(gcid, GC_BASE57, SEQUENCE_NEWID); - } - - /** - * Convert ids from the live map into GCCode (geocode) - */ - public static String newidToGeocode(final String newid) { - long gcid = GCBase.newidToGCId(newid); - return GCBase.gcidToGCCode(gcid); - } - /** Get user session & session token from the Live Map. Needed for following requests */ public static String[] getTokens() { final HttpResponse response = Network.request(GCConstants.URL_LIVE_MAP, null, false); diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java index 2a146cc..27b45de 100644 --- a/main/src/cgeo/geocaching/connector/gc/Tile.java +++ b/main/src/cgeo/geocaching/connector/gc/Tile.java @@ -2,6 +2,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.Settings; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Viewport; import cgeo.geocaching.network.Network; import cgeo.geocaching.utils.Log; @@ -45,22 +46,16 @@ public class Tile { private final int tileX; private final int tileY; private final int zoomlevel; + private final Viewport viewPort; public Tile(Geopoint origin, int zoomlevel) { - assert zoomlevel >= ZOOMLEVEL_MIN && zoomlevel <= ZOOMLEVEL_MAX : "zoomlevel out of range"; this.zoomlevel = Math.max(Math.min(zoomlevel, ZOOMLEVEL_MAX), ZOOMLEVEL_MIN); tileX = calcX(origin); tileY = calcY(origin); - } - - public Tile(int tileX, int tileY, int zoomlevel) { - assert zoomlevel >= ZOOMLEVEL_MIN && zoomlevel <= ZOOMLEVEL_MAX : "zoomlevel out of range"; - this.zoomlevel = zoomlevel; - this.tileX = tileX; - this.tileY = tileY; + viewPort = new Viewport(getCoord(new UTFGridPosition(0, 0)), getCoord(new UTFGridPosition(63, 63))); } public int getZoomlevel() { @@ -161,7 +156,7 @@ public class Tile { public static int calcZoomLat(final Geopoint bottom, final Geopoint top) { int zoom = (int) Math.ceil( - Math.log(2 * Math.PI / + Math.log(2.0 * Math.PI / Math.abs( asinh(tanGrad(bottom.getLatitude())) - asinh(tanGrad(top.getLatitude())) @@ -235,4 +230,9 @@ public class Tile { } return null; } + + public boolean containsPoint(Geopoint coords) { + + return viewPort.isInViewport(coords); + } } diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java index 5ea1093..daada06 100644 --- a/main/src/cgeo/geocaching/enumerations/CacheType.java +++ b/main/src/cgeo/geocaching/enumerations/CacheType.java @@ -86,4 +86,7 @@ public enum CacheType { this.l10n = cgeoapplication.getInstance().getBaseContext().getResources().getString(this.stringId); } + public boolean isEvent() { + return CacheType.EVENT == this || CacheType.MEGA_EVENT == this || CacheType.CITO == this || CacheType.LOSTANDFOUND == this; + } } diff --git a/main/src/cgeo/geocaching/enumerations/StatusCode.java b/main/src/cgeo/geocaching/enumerations/StatusCode.java index d49acb2..1a1f05d 100644 --- a/main/src/cgeo/geocaching/enumerations/StatusCode.java +++ b/main/src/cgeo/geocaching/enumerations/StatusCode.java @@ -2,41 +2,34 @@ package cgeo.geocaching.enumerations; import cgeo.geocaching.R; -import android.content.Context; import android.content.res.Resources; public enum StatusCode { - COMMUNICATION_NOT_STARTED(0, R.string.err_start), - NO_ERROR(1, R.string.err_none), - LOG_SAVED(2, R.string.info_log_saved), - LOGIN_PARSE_ERROR(-1, R.string.err_parse), - CONNECTION_FAILED(-2, R.string.err_server), - NO_LOGIN_INFO_STORED(-3, R.string.err_login), - UNKNOWN_ERROR(-4, R.string.err_unknown), - COMMUNICATION_ERROR(-5, R.string.err_comm), - WRONG_LOGIN_DATA(-6, R.string.err_wrong), - UNAPPROVED_LICENSE(-7, R.string.err_license), - UNPUBLISHED_CACHE(-8, R.string.err_unpublished), - PREMIUM_ONLY(-9, R.string.err_premium_only), - MAINTENANCE(-10, R.string.err_maintenance), - LOG_POST_ERROR(1000, R.string.err_log_post_failed), - NO_LOG_TEXT(1001, R.string.warn_log_text_fill), - NO_DATA_FROM_SERVER(1002, R.string.err_log_failed_server), - NOT_LOGGED_IN(-11, R.string.init_login_popup_failed); - - final private int error_code; + COMMUNICATION_NOT_STARTED(R.string.err_start), + NO_ERROR(R.string.err_none), + LOG_SAVED(R.string.info_log_saved), + LOGIN_PARSE_ERROR(R.string.err_parse), + CONNECTION_FAILED(R.string.err_server), + NO_LOGIN_INFO_STORED(R.string.err_login), + UNKNOWN_ERROR(R.string.err_unknown), + COMMUNICATION_ERROR(R.string.err_comm), + WRONG_LOGIN_DATA(R.string.err_wrong), + UNAPPROVED_LICENSE(R.string.err_license), + UNPUBLISHED_CACHE(R.string.err_unpublished), + PREMIUM_ONLY(R.string.err_premium_only), + MAINTENANCE(R.string.err_maintenance), + LOG_POST_ERROR(R.string.err_log_post_failed), + NO_LOG_TEXT(R.string.warn_log_text_fill), + NO_DATA_FROM_SERVER(R.string.err_log_failed_server), + NOT_LOGGED_IN(R.string.init_login_popup_failed); + final private int error_string; - StatusCode(int error_code, int error_string) { - this.error_code = error_code; + StatusCode(int error_string) { this.error_string = error_string; } - public int getCode() { - return error_code; - } - public int getErrorString() { return error_string; } @@ -45,8 +38,4 @@ public enum StatusCode { return res.getString(error_string); } - public String getErrorString(final Context context) { - return getErrorString(context.getResources()); - } - } diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java index 93d9c87..a672a6e 100644 --- a/main/src/cgeo/geocaching/geopoint/Geopoint.java +++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java @@ -47,19 +47,6 @@ public final class Geopoint implements ICoordinates { } /** - * Creates new Geopoint with given latitude and longitude (both microdegree). - * - * @param lat - * latitude - * @param lon - * longitude - */ - public Geopoint(final int lat, final int lon) - { - this(lat / 1e6, lon / 1e6); - } - - /** * Creates new Geopoint with latitude and longitude parsed from string. * * @param text @@ -247,7 +234,7 @@ public final class Geopoint implements ICoordinates { /** * Returns formatted coordinates with default format. * Default format is decimalminutes, e.g. N 52° 36.123 E 010° 03.456 - * + * * @return formatted coordinates */ @Override @@ -517,6 +504,8 @@ public final class Geopoint implements ICoordinates { return null; } + //FIXME: this interface implementation is totally confusing as it returns the class itself. + // it can therefore be removed completely (and any invocation of it) without any disadvantages @Override public Geopoint getCoords() { return this; diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java index 390bdb4..18c8342 100644 --- a/main/src/cgeo/geocaching/geopoint/Viewport.java +++ b/main/src/cgeo/geocaching/geopoint/Viewport.java @@ -1,7 +1,5 @@ package cgeo.geocaching.geopoint; -import cgeo.geocaching.Settings; -import cgeo.geocaching.utils.Log; public class Viewport { @@ -10,19 +8,27 @@ public class Viewport { public final Geopoint bottomLeft; public final Geopoint topRight; - public Viewport(final Geopoint bottomLeft, final Geopoint topRight) { - this.bottomLeft = bottomLeft; - this.topRight = topRight; - this.center = new Geopoint((bottomLeft.getLatitude() + topRight.getLatitude()) / 2, - (bottomLeft.getLongitude() + topRight.getLongitude()) / 2); + public Viewport(final Geopoint gp1, final Geopoint gp2) { + this.bottomLeft = new Geopoint(Math.min(gp1.getLatitude(), gp2.getLatitude()), + Math.min(gp1.getLongitude(), gp2.getLongitude())); + this.topRight = new Geopoint(Math.max(gp1.getLatitude(), gp2.getLatitude()), + Math.max(gp1.getLongitude(), gp2.getLongitude())); + this.center = new Geopoint((gp1.getLatitude() + gp2.getLatitude()) / 2, + (gp1.getLongitude() + gp2.getLongitude()) / 2); } public Viewport(final Geopoint center, final double latSpan, final double lonSpan) { this.center = center; final double centerLat = center.getLatitude(); final double centerLon = center.getLongitude(); - bottomLeft = new Geopoint(centerLat - latSpan / 2, centerLon - lonSpan / 2); - topRight = new Geopoint(centerLat + latSpan / 2, centerLon + lonSpan / 2); + final double latHalfSpan = Math.abs(latSpan) / 2; + final double lonHalfSpan = Math.abs(lonSpan) / 2; + bottomLeft = new Geopoint(centerLat - latHalfSpan, centerLon - lonHalfSpan); + topRight = new Geopoint(centerLat + latHalfSpan, centerLon + lonHalfSpan); + } + + public Viewport(final double lat1, final double lat2, final double lon1, final double lon2) { + this(new Geopoint(lat1, lon1), new Geopoint(lat2, lon2)); } public double getLatitudeMin() { @@ -45,12 +51,39 @@ public class Viewport { return center; } + public double getLatitudeSpan() { + return getLatitudeMax() - getLatitudeMin(); + } + + public double getLongitudeSpan() { + return getLongitudeMax() - getLongitudeMin(); + } + + public boolean isInViewport(final Geopoint coords) { + + return coords.getLongitudeE6() >= bottomLeft.getLongitudeE6() + && coords.getLongitudeE6() <= topRight.getLongitudeE6() + && coords.getLatitudeE6() >= bottomLeft.getLatitudeE6() + && coords.getLatitudeE6() <= topRight.getLatitudeE6(); + } + @Override public String toString() { return "(" + bottomLeft.toString() + "," + topRight.toString() + ")"; } /** + * Check whether another viewport is fully included into the current one. + * + * @param vp + * the other viewport + * @return true if the vp is fully included into this one, false otherwise + */ + public boolean includes(final Viewport vp) { + return isInViewport(vp.bottomLeft) && isInViewport(vp.topRight); + } + + /** * Check if coordinates are located in a viewport (defined by its center and span * in each direction). * @@ -66,9 +99,11 @@ public class Viewport { * the coordinates to check * @return true if the coordinates are in the viewport */ + // FIXME: this static method has nothing to do here and should be used with a viewport, not some int numbers, + // when CGeoMap.java gets rewritten public static boolean isCacheInViewPort(int centerLat, int centerLon, int spanLat, int spanLon, final Geopoint coords) { - return 2 * Math.abs(coords.getLatitudeE6() - centerLat) <= Math.abs(spanLat) && - 2 * Math.abs(coords.getLongitudeE6() - centerLon) <= Math.abs(spanLon); + final Viewport viewport = new Viewport(new Geopoint(centerLat / 1e6, centerLon / 1e6), spanLat / 1e6, spanLon / 1e6); + return viewport.isInViewport(coords); } /** @@ -87,36 +122,48 @@ public class Viewport { * @param spanLon2 * @return */ + // FIXME: this static method has nothing to do here and should be used with a viewport, not some int numbers, + // when CGeoMap.java gets rewritten public static boolean isInViewPort(int centerLat1, int centerLon1, int centerLat2, int centerLon2, int spanLat1, int spanLon1, int spanLat2, int spanLon2) { - try { - final int left1 = centerLat1 - (spanLat1 / 2); - final int left2 = centerLat2 - (spanLat2 / 2); - if (left2 <= left1) { - return false; - } - - final int right1 = centerLat1 + (spanLat1 / 2); - final int right2 = centerLat2 + (spanLat2 / 2); - if (right2 >= right1) { - return false; - } - - final int top1 = centerLon1 + (spanLon1 / 2); - final int top2 = centerLon2 + (spanLon2 / 2); - if (top2 >= top1) { - return false; - } - - final int bottom1 = centerLon1 - (spanLon1 / 2); - final int bottom2 = centerLon2 - (spanLon2 / 2); - if (bottom2 <= bottom1) { - return false; - } - - return true; - } catch (Exception e) { - Log.e(Settings.tag, "Viewport.isInViewPort: " + e.toString()); + final Viewport outer = new Viewport(new Geopoint(centerLat1 / 1e6, centerLon1 / 1e6), spanLat1 / 1e6, spanLon1 / 1e6); + final Viewport inner = new Viewport(new Geopoint(centerLat2 / 1e6, centerLon2 / 1e6), spanLat2 / 1e6, spanLon2 / 1e6); + return outer.includes(inner); + } + + /** + * Return the "where" part of the string appropriate for a SQL query. + * + * @return the string without the "where" keyword + */ + public String sqlWhere() { + return "latitude >= " + getLatitudeMin() + " and " + + "latitude <= " + getLatitudeMax() + " and " + + "longitude >= " + getLongitudeMin() + " and " + + "longitude <= " + getLongitudeMax(); + } + + /** + * Return a widened or shrunk viewport. + * + * @param factor + * multiplicative factor for the latitude and longitude span (> 1 to widen, < 1 to shrink) + * @return a widened or shrunk viewport + */ + public Viewport resize(final double factor) { + return new Viewport(getCenter(), getLatitudeSpan() * factor, getLongitudeSpan() * factor); + } + + @Override + public boolean equals(final Object other) { + if (other == null || !(other instanceof Viewport)) { return false; } + final Viewport vp = (Viewport) other; + return bottomLeft.equals(vp.bottomLeft) && topRight.equals(vp.topRight); + } + + @Override + public int hashCode() { + return bottomLeft.hashCode() ^ topRight.hashCode(); } } diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index d159095..09aeabd 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -988,6 +988,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto int centerLongitudeNow = mapCenterNow.getLongitudeE6(); int spanLatitudeNow = mapView.getLatitudeSpan(); int spanLongitudeNow = mapView.getLongitudeSpan(); + 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 @@ -1001,6 +1002,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto moved = true; } else if (spanLatitude == null || spanLongitude == null) { moved = true; + } else if (zoomNow != zoom) { + moved = true; } else if (((Math.abs(spanLatitudeNow - spanLatitude) > 50) || (Math.abs(spanLongitudeNow - spanLongitude) > 50) || // changed zoom (Math.abs(centerLatitudeNow - centerLatitude) > (spanLatitudeNow / 4)) || (Math.abs(centerLongitudeNow - centerLongitude) > (spanLongitudeNow / 4)) // map moved ) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) @@ -1009,7 +1012,6 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } // update title on any change - int zoomNow = mapView.getMapZoomLevel(); if (moved || zoomNow != zoom || spanLatitudeNow != spanLatitude || spanLongitudeNow != spanLongitude || centerLatitudeNow != centerLatitude || centerLongitudeNow != centerLongitude) { displayHandler.sendEmptyMessage(UPDATE_TITLE); } @@ -1311,8 +1313,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto @Override public void run() { - final Geopoint center = new Geopoint((int) centerLat, (int) centerLon); - final Viewport viewport = new Viewport(center, spanLat / 1e6 * 1.5, spanLon / 1e6 * 1.5); + final Geopoint center = new Geopoint(centerLat / 1e6, centerLon / 1e6); + final Viewport viewport = new Viewport(center, spanLat / 1e6, spanLon / 1e6).resize(1.5); try { go4CacheThreadRun = System.currentTimeMillis(); @@ -1524,6 +1526,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto } } + private Viewport listToViewport(final List<Number> l) { + return new Viewport(new Geopoint(l.get(1).doubleValue(), l.get(3).doubleValue()), new Geopoint(l.get(2).doubleValue(), l.get(4).doubleValue())); + } + // move map to view results of searchIntent private void centerMap(String geocodeCenter, final SearchResult searchCenter, final Geopoint coordsCenter, int[] mapState) { @@ -1539,46 +1545,30 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto alreadyCentered = true; } else if (!centered && (geocodeCenter != null || searchIntent != null)) { try { - List<Number> viewport = null; + List<Number> vp = null; if (geocodeCenter != null) { - viewport = app.getBounds(geocodeCenter); + vp = app.getBounds(geocodeCenter); } else { if (searchCenter != null) { - viewport = app.getBounds(searchCenter.getGeocodes()); + vp = app.getBounds(searchCenter.getGeocodes()); } } - if (viewport == null || viewport.size() < 5) { + if (vp == null || vp.size() < 5) { return; } - int cnt = (Integer) viewport.get(0); + int cnt = (Integer) vp.get(0); if (cnt <= 0) { return; } - int minLat = (int) ((Double) viewport.get(1) * 1e6); - int maxLat = (int) ((Double) viewport.get(2) * 1e6); - int maxLon = (int) ((Double) viewport.get(3) * 1e6); - int minLon = (int) ((Double) viewport.get(4) * 1e6); - int centerLat = 0; - int centerLon = 0; - - if ((Math.abs(maxLat) - Math.abs(minLat)) != 0) { - centerLat = minLat + ((maxLat - minLat) / 2); - } else { - centerLat = maxLat; - } - if ((Math.abs(maxLon) - Math.abs(minLon)) != 0) { - centerLon = minLon + ((maxLon - minLon) / 2); - } else { - centerLon = maxLon; - } + final Viewport viewport = listToViewport(vp); - mapController.setCenter(mapProvider.getGeoPointBase(new Geopoint(centerLat, centerLon))); - if (Math.abs(maxLat - minLat) != 0 && Math.abs(maxLon - minLon) != 0) { - mapController.zoomToSpan(Math.abs(maxLat - minLat), Math.abs(maxLon - minLon)); + mapController.setCenter(mapProvider.getGeoPointBase(viewport.center)); + if (viewport.getLatitudeSpan() != 0 && viewport.getLongitudeSpan() != 0) { + mapController.zoomToSpan((int) (viewport.getLatitudeSpan() * 1e6), (int) (viewport.getLongitudeSpan() * 1e6)); } } catch (Exception e) { // nothing at all diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java index ddd6ec6..4094280 100644 --- a/main/src/cgeo/geocaching/maps/CachesOverlay.java +++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java @@ -36,11 +36,9 @@ public class CachesOverlay extends AbstractItemizedOverlay { private Context context = null; private boolean displayCircles = false; private ProgressDialog waitDialog = null; - private Point center = new Point(); - private Point left = new Point(); private Paint blockedCircle = null; - private PaintFlagsDrawFilter setfil = null; - private PaintFlagsDrawFilter remfil = null; + private PaintFlagsDrawFilter setFilter = null; + private PaintFlagsDrawFilter removeFilter = null; private MapProvider mapProvider = null; public CachesOverlay(ItemizedOverlayImpl ovlImpl, Context contextIn) { @@ -107,65 +105,91 @@ public class CachesOverlay extends AbstractItemizedOverlay { } private void drawInternal(Canvas canvas, MapProjectionImpl projection) { + if (!displayCircles || items.isEmpty()) { + return; + } // prevent content changes getOverlayImpl().lock(); try { - if (displayCircles) { - if (blockedCircle == null) { - blockedCircle = new Paint(); - blockedCircle.setAntiAlias(true); - blockedCircle.setStrokeWidth(2.0f); - blockedCircle.setARGB(127, 0, 0, 0); - blockedCircle.setPathEffect(new DashPathEffect(new float[] { 3, 2 }, 0)); + lazyInitializeDrawingObjects(); + canvas.setDrawFilter(setFilter); + + final int radius = calculateDrawingRadius(projection); + final Point center = new Point(); + + for (CachesOverlayItemImpl item : items) { + final Geopoint itemCoord = item.getCoord().getCoords(); + final GeoPointImpl itemGeo = mapProvider.getGeoPointBase(itemCoord); + projection.toPixels(itemGeo, center); + + final CacheType type = item.getType(); + if (type == null || type == CacheType.MULTI || type == CacheType.MYSTERY || type == CacheType.VIRTUAL || type.isEvent()) { + blockedCircle.setColor(0x66000000); + blockedCircle.setStyle(Style.STROKE); + canvas.drawCircle(center.x, center.y, radius, blockedCircle); + } else { + blockedCircle.setColor(0x66BB0000); + blockedCircle.setStyle(Style.STROKE); + canvas.drawCircle(center.x, center.y, radius, blockedCircle); + + blockedCircle.setColor(0x44BB0000); + blockedCircle.setStyle(Style.FILL); + canvas.drawCircle(center.x, center.y, radius, blockedCircle); } + } + canvas.setDrawFilter(removeFilter); + } finally { + getOverlayImpl().unlock(); + } + } - if (setfil == null) { - setfil = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); - } - if (remfil == null) { - remfil = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); - } + /** + * calculate the radius of the circle to be drawn for the first item only. Those circles are only 161 meters in + * reality and therefore the minor changes due to the projection will not make any visible difference at the zoom + * levels which are used to see the circles. + * + * @param projection + * @return + */ + private int calculateDrawingRadius(MapProjectionImpl projection) { + float[] distanceArray = new float[1]; + final Geopoint itemCoord = items.get(0).getCoord().getCoords(); - canvas.setDrawFilter(setfil); + Location.distanceBetween(itemCoord.getLatitude(), itemCoord.getLongitude(), + itemCoord.getLatitude(), itemCoord.getLongitude() + 1, distanceArray); + final float longitudeLineDistance = distanceArray[0]; - for (CachesOverlayItemImpl item : items) { - final IWaypoint itemCoord = item.getCoord(); - float[] result = new float[1]; + final GeoPointImpl itemGeo = mapProvider.getGeoPointBase(itemCoord); - Location.distanceBetween(itemCoord.getCoords().getLatitude(), itemCoord.getCoords().getLongitude(), - itemCoord.getCoords().getLatitude(), itemCoord.getCoords().getLongitude() + 1, result); - final float longitudeLineDistance = result[0]; + final Geopoint leftCoords = new Geopoint(itemCoord.getLatitude(), + itemCoord.getLongitude() - 161 / longitudeLineDistance); + final GeoPointImpl leftGeo = mapProvider.getGeoPointBase(leftCoords); - GeoPointImpl itemGeo = mapProvider.getGeoPointBase(itemCoord.getCoords()); + final Point center = new Point(); + projection.toPixels(itemGeo, center); - final Geopoint leftCoords = new Geopoint(itemCoord.getCoords().getLatitude(), - itemCoord.getCoords().getLongitude() - 161 / longitudeLineDistance); - GeoPointImpl leftGeo = mapProvider.getGeoPointBase(leftCoords); + final Point left = new Point(); + projection.toPixels(leftGeo, left); - projection.toPixels(itemGeo, center); - projection.toPixels(leftGeo, left); - int radius = center.x - left.x; + final int radius = center.x - left.x; + return radius; + } - final CacheType type = item.getType(); - if (type == null || type == CacheType.MULTI || type == CacheType.MYSTERY || type == CacheType.VIRTUAL) { - blockedCircle.setColor(0x66000000); - blockedCircle.setStyle(Style.STROKE); - canvas.drawCircle(center.x, center.y, radius, blockedCircle); - } else { - blockedCircle.setColor(0x66BB0000); - blockedCircle.setStyle(Style.STROKE); - canvas.drawCircle(center.x, center.y, radius, blockedCircle); + private void lazyInitializeDrawingObjects() { + if (blockedCircle == null) { + blockedCircle = new Paint(); + blockedCircle.setAntiAlias(true); + blockedCircle.setStrokeWidth(2.0f); + blockedCircle.setARGB(127, 0, 0, 0); + blockedCircle.setPathEffect(new DashPathEffect(new float[] { 3, 2 }, 0)); + } - blockedCircle.setColor(0x44BB0000); - blockedCircle.setStyle(Style.FILL); - canvas.drawCircle(center.x, center.y, radius, blockedCircle); - } - } - canvas.setDrawFilter(remfil); - } - } finally { - getOverlayImpl().unlock(); + if (setFilter == null) { + setFilter = new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG); + } + if (removeFilter == null) { + removeFilter = new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0); } } diff --git a/main/src/cgeo/geocaching/network/Login.java b/main/src/cgeo/geocaching/network/Login.java index d5f511d..fe78978 100644 --- a/main/src/cgeo/geocaching/network/Login.java +++ b/main/src/cgeo/geocaching/network/Login.java @@ -32,7 +32,6 @@ public abstract class Login { // false = not logged in private static boolean actualLoginStatus = false; private static String actualUserName = ""; - private static String actualMemberStatus = ""; private static int actualCachesFound = -1; private static String actualStatus = ""; @@ -171,14 +170,6 @@ public abstract class Login { actualUserName = userName; } - public static String getActualMemberStatus() { - return actualMemberStatus; - } - - public static void setActualMemberStatus(final String memberStatus) { - actualMemberStatus = memberStatus; - } - public static int getActualCachesFound() { return actualCachesFound; } @@ -204,7 +195,6 @@ public abstract class Login { setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME)); if (isActualLoginStatus()) { setActualUserName(BaseUtils.getMatch(page, GCConstants.PATTERN_LOGIN_NAME, true, "???")); - setActualMemberStatus(BaseUtils.getMatch(page, GCConstants.PATTERN_MEMBER_STATUS, true, "???")); setActualCachesFound(Integer.parseInt(BaseUtils.getMatch(page, GCConstants.PATTERN_CACHES_FOUND, true, "0").replaceAll("[,.]", ""))); return true; } @@ -213,7 +203,6 @@ public abstract class Login { setActualLoginStatus(BaseUtils.matches(page, GCConstants.PATTERN_LOGIN_NAME_LOGIN_PAGE)); if (isActualLoginStatus()) { setActualUserName(Settings.getUsername()); - setActualMemberStatus(Settings.getMemberStatus()); // number of caches found is not part of this page return true; } @@ -389,10 +378,4 @@ public abstract class Login { putViewstates(params, getViewstates(page)); } - static public String[] requestViewstates(final String uri, final Parameters params, boolean xContentType, boolean my) { - final HttpResponse response = Network.request(uri, params, xContentType, my, false); - - return getViewstates(Network.getResponseData(response)); - } - } diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java index 6c03889..c6205f6 100644 --- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java +++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java @@ -195,17 +195,6 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> { notifyDataSetChanged(); } - public void clearFilter() { - if (originalList != null) { - list.clear(); - list.addAll(originalList); - - currentFilter = null; - } - - notifyDataSetChanged(); - } - public boolean isFilter() { return currentFilter != null; } diff --git a/main/src/cgeo/geocaching/utils/BaseUtils.java b/main/src/cgeo/geocaching/utils/BaseUtils.java index 44c35a1..d468fc9 100644 --- a/main/src/cgeo/geocaching/utils/BaseUtils.java +++ b/main/src/cgeo/geocaching/utils/BaseUtils.java @@ -3,8 +3,6 @@ */ package cgeo.geocaching.utils; -import java.util.ArrayList; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -84,17 +82,6 @@ public final class BaseUtils { return BaseUtils.getMatch(data, p, true, 1, defaultValue, false); } - public static List<String> getMatches(final String data, final Pattern p, int count) { - ArrayList<String> result = new ArrayList<String>(); - final Matcher matcher = p.matcher(data); - while (matcher.find()) { - for (int i = 0; i < count; i++) { - result.add(matcher.group(i)); - } - } - return result; - } - /** * Searches for the pattern p in the data. * diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java index 87b37c4..4cf0de2 100644 --- a/main/src/cgeo/geocaching/utils/CryptUtils.java +++ b/main/src/cgeo/geocaching/utils/CryptUtils.java @@ -136,49 +136,6 @@ public final class CryptUtils { return buffer; } - public static byte[] base64Decode(String text) { - char[] in = text.toCharArray(); - - int iLen = in.length; - if (iLen % 4 != 0) { - throw new IllegalArgumentException("Length of Base64 encoded input string is not a multiple of 4."); - } - while (iLen > 0 && in[iLen - 1] == '=') { - iLen--; - } - int oLen = (iLen * 3) / 4; - byte[] out = new byte[oLen]; - int ip = 0; - int op = 0; - while (ip < iLen) { - int i0 = in[ip++]; - int i1 = in[ip++]; - int i2 = ip < iLen ? in[ip++] : 'A'; - int i3 = ip < iLen ? in[ip++] : 'A'; - if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - int b0 = base64map2[i0]; - int b1 = base64map2[i1]; - int b2 = base64map2[i2]; - int b3 = base64map2[i3]; - if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { - throw new IllegalArgumentException("Illegal character in Base64 encoded data."); - } - int o0 = (b0 << 2) | (b1 >>> 4); - int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); - int o2 = ((b2 & 3) << 6) | b3; - out[op++] = (byte) o0; - if (op < oLen) { - out[op++] = (byte) o1; - } - if (op < oLen) { - out[op++] = (byte) o2; - } - } - return out; - } - public static String base64Encode(byte[] in) { int iLen = in.length; int oDataLen = (iLen * 4 + 2) / 3; // output length without padding diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java index 8a7d23f..5628a4b 100644 --- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java +++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java @@ -27,6 +27,7 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { private final int maxEntries; private final OperationModes opMode; + private RemoveHandler<V> removeHandler; // store the HashMap parameters for serialization, as we can't access the originals in the LinkedHashMap final int initialCapacity; @@ -49,7 +50,8 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { // in case the underlying Map is not running with accessOrder==true, the map won't notice any changes // of existing keys, so for the normal BOUNDED mode we remove and put the value to get its order updated. if (opMode == OperationModes.BOUNDED && containsKey(key)) { - final V oldVal = remove(key); + // avoid trigger the remove notification + final V oldVal = super.remove(key); put(key, value); return oldVal; } else { @@ -66,6 +68,29 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { return maxEntries; } + @Override + public V remove(Object key) { + + V removed = super.remove(key); + + if (removed != null && removeHandler != null) { + removeHandler.onRemove(removed); + } + + return removed; + } + + /** + * Sets a handler for remove notifications. Currently only one handler + * instance is supported + * + * @param removeHandler + * The new handler to receive notifications or null to remove a handler + */ + public void setRemoveHandler(RemoveHandler<V> removeHandler) { + this.removeHandler = removeHandler; + } + public static class LruCache<K, V> extends LeastRecentlyUsedMap<K, V> { private static final long serialVersionUID = 9028478916221334454L; @@ -90,4 +115,25 @@ public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> { super(maxEntries, OperationModes.BOUNDED); } } + + /** + * Interface for handlers that wish to get notified when items are + * removed from the LRUMap + * + * @author rsudev + * + * @param <V> + */ + public interface RemoveHandler<V> { + + /** + * Method will be called on remove + * + * @param removed + * Item that has been removed + */ + void onRemove(V removed); + + } + } diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java index 42c1705..caa13ee 100644 --- a/main/src/cgeo/geocaching/utils/Log.java +++ b/main/src/cgeo/geocaching/utils/Log.java @@ -4,6 +4,7 @@ import cgeo.geocaching.Settings; final public class Log { + //FIXME: tag should be private member of this log class public static void v(final String tag, final String msg) { if (Settings.isDebug()) { android.util.Log.v(tag, msg); |