aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/cgeo/calendar/ICalendar.java1
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java37
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java126
-rw-r--r--main/src/cgeo/geocaching/DirectionProvider.java14
-rw-r--r--main/src/cgeo/geocaching/GeoDataProvider.java34
-rw-r--r--main/src/cgeo/geocaching/ICache.java4
-rw-r--r--main/src/cgeo/geocaching/LiveMapInfo.java1
-rw-r--r--main/src/cgeo/geocaching/LogEntry.java12
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java4
-rw-r--r--main/src/cgeo/geocaching/Settings.java21
-rw-r--r--main/src/cgeo/geocaching/SettingsActivity.java12
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java34
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java52
-rw-r--r--main/src/cgeo/geocaching/VisitCacheActivity.java7
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActivity.java6
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractListActivity.java6
-rw-r--r--main/src/cgeo/geocaching/activity/ActivityMixin.java29
-rw-r--r--main/src/cgeo/geocaching/activity/IAbstractActivity.java2
-rw-r--r--main/src/cgeo/geocaching/activity/Progress.java2
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractApp.java5
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractLocusApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/App.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java15
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java56
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java36
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java17
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java44
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java22
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java13
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java37
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java39
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java37
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java110
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java52
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java22
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java2
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java15
-rw-r--r--main/src/cgeo/geocaching/backup/CentralBackupAgent.java2
-rw-r--r--main/src/cgeo/geocaching/cgCache.java98
-rw-r--r--main/src/cgeo/geocaching/cgData.java98
-rw-r--r--main/src/cgeo/geocaching/cgWaypoint.java2
-rw-r--r--main/src/cgeo/geocaching/cgeo.java11
-rw-r--r--main/src/cgeo/geocaching/cgeocaches.java247
-rw-r--r--main/src/cgeo/geocaching/cgeoimages.java33
-rw-r--r--main/src/cgeo/geocaching/cgeonavigate.java51
-rw-r--r--main/src/cgeo/geocaching/cgeotrackable.java4
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel11.java2
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel8.java2
-rw-r--r--main/src/cgeo/geocaching/compatibility/Compatibility.java16
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java10
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java11
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java66
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java8
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java7
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java2
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java169
-rw-r--r--main/src/cgeo/geocaching/files/FileList.java20
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java45
-rw-r--r--main/src/cgeo/geocaching/filter/FilterUserInterface.java13
-rw-r--r--main/src/cgeo/geocaching/geopoint/HumanDistance.java49
-rw-r--r--main/src/cgeo/geocaching/geopoint/Units.java73
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java131
-rw-r--r--main/src/cgeo/geocaching/maps/MapProviderFactory.java45
-rw-r--r--main/src/cgeo/geocaching/maps/ScaleOverlay.java4
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java118
-rw-r--r--main/src/cgeo/geocaching/sorting/DateComparator.java17
-rw-r--r--main/src/cgeo/geocaching/sorting/FindsComparator.java11
-rw-r--r--main/src/cgeo/geocaching/sorting/VisitComparator.java2
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractUIFactory.java9
-rw-r--r--main/src/cgeo/geocaching/ui/AddressListAdapter.java4
-rw-r--r--main/src/cgeo/geocaching/ui/CacheDetailsCreator.java4
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java57
-rw-r--r--main/src/cgeo/geocaching/ui/CompassView.java15
-rw-r--r--main/src/cgeo/geocaching/ui/DistanceView.java6
-rw-r--r--main/src/cgeo/geocaching/ui/Formatter.java91
-rw-r--r--main/src/cgeo/geocaching/ui/LoggingUI.java144
-rw-r--r--main/src/cgeo/geocaching/utils/DateUtils.java18
-rw-r--r--main/src/cgeo/geocaching/utils/UnknownTagsHandler.java14
84 files changed, 1602 insertions, 1073 deletions
diff --git a/main/src/cgeo/calendar/ICalendar.java b/main/src/cgeo/calendar/ICalendar.java
index 856de1a..933d248 100644
--- a/main/src/cgeo/calendar/ICalendar.java
+++ b/main/src/cgeo/calendar/ICalendar.java
@@ -15,4 +15,5 @@ public interface ICalendar {
static final String PARAM_NAME = "name"; // cache name
static final String PARAM_LOCATION = "location"; // cache location, or empty string
static final String PARAM_COORDS = "coords"; // cache coords, or empty string
+ static final String PARAM_START_TIME_MINUTES = "time"; // time of start
}
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index 588ba2a..a119949 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -4,12 +4,12 @@ import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.LoadFlags;
-import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.gcvote.GCVote;
import cgeo.geocaching.gcvote.GCVoteRating;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -64,7 +64,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
protected void updateGeoData(final IGeoData geo) {
try {
if (geo.getCoords() != null && cache != null && cache.getCoords() != null) {
- cacheDistance.setText(HumanDistance.getHumanDistance(geo.getCoords().distanceTo(cache.getCoords())));
+ cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
cacheDistance.bringToFront();
}
} catch (Exception e) {
@@ -123,15 +123,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
geocode = cache.getGeocode().toUpperCase();
}
- private void logOffline(int menuItem) {
- cache.logOffline(this, LogType.getById(menuItem - MENU_LOG_VISIT_OFFLINE));
- }
-
- private void logVisit() {
- cache.logVisit(this);
- finish();
- }
-
private void showInBrowser() {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/seek/cache_details.aspx?wp=" + cache.getGeocode())));
}
@@ -142,7 +133,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// set layout
- setTheme(R.style.transparent);
setContentView(layout);
setTitle(res.getString(R.string.detail));
@@ -174,7 +164,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName()).setIcon(R.drawable.ic_menu_compass); // default navigation tool
menu.add(0, MENU_NAVIGATION, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
- addVisitMenu(menu, cache);
+ LoggingUI.addMenuItems(menu, cache);
menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
menu.add(0, MENU_SHOW_IN_BROWSER, 0, res.getString(R.string.cache_menu_browser)).setIcon(R.drawable.ic_menu_info_details); // browser
@@ -188,21 +178,20 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
switch (menuItem) {
case MENU_DEFAULT_NAVIGATION:
navigateTo();
- break;
+ return true;
case MENU_NAVIGATION:
showNavigationMenu();
- break;
+ return true;
case MENU_CACHES_AROUND:
cachesAround();
- break;
- case MENU_LOG_VISIT:
- logVisit();
- break;
+ return true;
case MENU_SHOW_IN_BROWSER:
showInBrowser();
- break;
- default:
- logOffline(menuItem);
+ return true;
+ }
+
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ return true;
}
return true;
@@ -224,7 +213,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
menu.findItem(MENU_NAVIGATION).setVisible(visible);
menu.findItem(MENU_CACHES_AROUND).setVisible(visible);
- menu.findItem(MENU_LOG_VISIT).setEnabled(Settings.isLogin());
+ LoggingUI.onPrepareOptionsMenu(menu);
} catch (Exception e) {
// nothing
}
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index d9b4e96..93566c2 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -12,15 +12,14 @@ import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.LogType;
-import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.GeopointFormatter;
-import cgeo.geocaching.geopoint.HumanDistance;
-import cgeo.geocaching.geopoint.IConversion;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.DecryptTextClickListener;
import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.ClipboardUtils;
@@ -46,7 +45,6 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@@ -65,6 +63,7 @@ import android.text.Spannable;
import android.text.Spanned;
import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod;
+import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.view.ContextMenu;
@@ -139,20 +138,13 @@ public class CacheDetailActivity extends AbstractActivity {
final StringBuilder dist = new StringBuilder();
if (geo.getCoords() != null && cache != null && cache.getCoords() != null) {
- dist.append(HumanDistance.getHumanDistance(geo.getCoords().distanceTo(cache.getCoords())));
+ dist.append(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords())));
}
if (cache != null && cache.getElevation() != null) {
if (geo.getAltitude() != 0.0) {
- final double diff = cache.getElevation() - geo.getAltitude();
- dist.append(diff >= 0 ? " ↗" : " ↘");
- if (Settings.isUseMetricUnits()) {
- dist.append(Math.abs((int) diff));
- dist.append(" m");
- } else {
- dist.append(Math.abs((int) (diff * IConversion.METERS_TO_FEET)));
- dist.append(" ft");
- }
+ final float diff = (float) (cache.getElevation() - geo.getAltitude());
+ dist.append(' ').append(Units.getElevation(diff));
}
}
@@ -565,7 +557,7 @@ public class CacheDetailActivity extends AbstractActivity {
GeneralAppsFactory.addMenuItems(subMenu, cache);
menu.add(1, MENU_CALENDAR, 0, res.getString(R.string.cache_menu_event)).setIcon(R.drawable.ic_menu_agenda); // add event to calendar
- addVisitMenu(menu, cache);
+ LoggingUI.addMenuItems(menu, cache);
menu.add(0, MENU_CACHES_AROUND, 0, res.getString(R.string.cache_menu_around)).setIcon(R.drawable.ic_menu_rotate); // caches around
menu.add(1, MENU_BROWSER, 0, res.getString(R.string.cache_menu_browser)).setIcon(R.drawable.ic_menu_globe); // browser
menu.add(0, MENU_SHARE, 0, res.getString(R.string.cache_menu_share)).setIcon(R.drawable.ic_menu_share); // share cache
@@ -593,10 +585,6 @@ public class CacheDetailActivity extends AbstractActivity {
case MENU_DEFAULT_NAVIGATION:
startDefaultNavigation();
return true;
- case MENU_LOG_VISIT:
- refreshOnResume = true;
- cache.logVisit(this);
- return true;
case MENU_BROWSER:
cache.openInBrowser(this);
return true;
@@ -619,8 +607,11 @@ public class CacheDetailActivity extends AbstractActivity {
if (GeneralAppsFactory.onMenuItemSelected(item, this, cache)) {
return true;
}
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ refreshOnResume = true;
+ return true;
+ }
- cache.logOffline(this, LogType.getById(menuItem - MENU_LOG_VISIT_OFFLINE));
return true;
}
@@ -796,7 +787,8 @@ public class CacheDetailActivity extends AbstractActivity {
ICalendar.PARAM_URL, StringUtils.defaultString(cache.getUrl()),
ICalendar.PARAM_COORDS, cache.getCoords() == null ? "" : cache.getCoords().format(GeopointFormatter.Format.LAT_LON_DECMINUTE_RAW),
ICalendar.PARAM_LOCATION, StringUtils.defaultString(cache.getLocation()),
- ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription())
+ ICalendar.PARAM_SHORT_DESC, StringUtils.defaultString(cache.getShortDescription()),
+ ICalendar.PARAM_START_TIME_MINUTES, StringUtils.defaultString(cache.guessEventTimeMinutes())
);
startActivity(new Intent(ICalendar.INTENT,
@@ -894,8 +886,8 @@ public class CacheDetailActivity extends AbstractActivity {
}
// Use real owner name vice the one owner chose to display
- if (StringUtils.isNotBlank(cache.getOwnerReal())) {
- clickedItemText = cache.getOwnerReal();
+ if (StringUtils.isNotBlank(cache.getOwnerUserId())) {
+ clickedItemText = cache.getOwnerUserId();
} else {
clickedItemText = ((TextView) view).getText().toString();
}
@@ -1344,6 +1336,9 @@ public class CacheDetailActivity extends AbstractActivity {
if (cache.isDisabled() || cache.isArchived()) { // strike
span.setSpan(new StrikethroughSpan(), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
+ if (cache.isArchived()) {
+ span.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
details.add(R.string.cache_name, span);
details.add(R.string.cache_type, cache.getType().getL10n());
@@ -1367,12 +1362,12 @@ public class CacheDetailActivity extends AbstractActivity {
}
// cache author
- if (StringUtils.isNotBlank(cache.getOwner()) || StringUtils.isNotBlank(cache.getOwnerReal())) {
+ if (StringUtils.isNotBlank(cache.getOwnerDisplayName()) || StringUtils.isNotBlank(cache.getOwnerUserId())) {
TextView ownerView = details.add(R.string.cache_owner, "");
- if (StringUtils.isNotBlank(cache.getOwner())) {
- ownerView.setText(cache.getOwner(), TextView.BufferType.SPANNABLE);
+ if (StringUtils.isNotBlank(cache.getOwnerDisplayName())) {
+ ownerView.setText(cache.getOwnerDisplayName(), TextView.BufferType.SPANNABLE);
} else { // OwnerReal guaranteed to be not blank based on above
- ownerView.setText(cache.getOwnerReal(), TextView.BufferType.SPANNABLE);
+ ownerView.setText(cache.getOwnerUserId(), TextView.BufferType.SPANNABLE);
}
ownerView.setOnClickListener(new OwnerActionsClickListener());
}
@@ -1830,7 +1825,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
private Bitmap decode(final cgCache cache) {
- return BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(cache.getGeocode(), "preview", false).getPath());
+ return StaticMapsProvider.getPreviewMap(cache.getGeocode());
}
@Override
@@ -2027,8 +2022,10 @@ public class CacheDetailActivity extends AbstractActivity {
publishProgress();
}
- // if description has HTML table, add a note at the end of the long description
- if (unknownTagsHandler.isTableDetected() && descriptionView == view.findViewById(R.id.longdesc)) {
+ // If description has an HTML construct which may be problematic to render, add a note at the end of the long description.
+ // Technically, it may not be a table, but a pre, which has the same problems as a table, so the message is ok even though
+ // sometimes technically incorrect.
+ if (unknownTagsHandler.isProblematicDetected() && descriptionView == view.findViewById(R.id.longdesc)) {
final int startPos = description.length();
((Editable) description).append("\n\n").append(res.getString(R.string.cache_description_table_note));
((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -2113,43 +2110,33 @@ public class CacheDetailActivity extends AbstractActivity {
view = (ListView) getLayoutInflater().inflate(R.layout.cacheview_logs, null);
// log count
- if (cache.getLogCounts() != null) {
- final StringBuilder text = new StringBuilder(200);
- text.append(res.getString(R.string.cache_log_types));
- text.append(": ");
-
- // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones
- final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<Entry<LogType, Integer>>();
- for (Entry<LogType, Integer> entry : cache.getLogCounts().entrySet()) {
- sortedLogCounts.add(entry); // don't add these entries using addAll(), the iterator in the EntrySet can go wrong (see Findbugs)
+ final Map<LogType, Integer> logCounts = cache.getLogCounts();
+ if (logCounts != null) {
+ final List<Entry<LogType, Integer>> sortedLogCounts = new ArrayList<Entry<LogType, Integer>>(logCounts.size());
+ for (Entry<LogType, Integer> entry : logCounts.entrySet()) {
+ // it may happen that the label is unknown -> then avoid any output for this type
+ if (entry.getKey() != LogType.PUBLISH_LISTING && entry.getKey().getL10n() != null) {
+ sortedLogCounts.add(entry);
+ }
}
- Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() {
-
- @Override
- public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) {
- return logCountItem1.getKey().compareTo(logCountItem2.getKey());
- }
- });
+ if (sortedLogCounts.size() > 0) {
+ // sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones
+ Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() {
- boolean showLogCounter = false;
- for (Entry<LogType, Integer> pair : sortedLogCounts) {
- String logTypeLabel = pair.getKey().getL10n();
- // it may happen that the label is unknown -> then avoid any output for this type
- if (logTypeLabel != null && pair.getKey() != LogType.PUBLISH_LISTING) {
- if (showLogCounter) {
- text.append(", ");
+ @Override
+ public int compare(Entry<LogType, Integer> logCountItem1, Entry<LogType, Integer> logCountItem2) {
+ return logCountItem1.getKey().compareTo(logCountItem2.getKey());
}
- text.append(pair.getValue().intValue());
- text.append("× ");
- text.append(logTypeLabel);
+ });
+
+ ArrayList<String> labels = new ArrayList<String>(sortedLogCounts.size());
+ for (Entry<LogType, Integer> pair : sortedLogCounts) {
+ labels.add(pair.getValue() + "× " + pair.getKey().getL10n());
}
- showLogCounter = true;
- }
- if (showLogCounter) {
final TextView countView = new TextView(CacheDetailActivity.this);
- countView.setText(text.toString());
+ countView.setText(res.getString(R.string.cache_log_types) + ": " + StringUtils.join(labels, ", "));
view.addHeaderView(countView, null, false);
}
}
@@ -2317,23 +2304,10 @@ public class CacheDetailActivity extends AbstractActivity {
}
// info
- final List<String> infoTextList = new ArrayList<String>(3);
- if (WaypointType.ALL_TYPES_EXCEPT_OWN.contains(wpt.getWaypointType())) {
- infoTextList.add(wpt.getWaypointType().getL10n());
- }
- if (cgWaypoint.PREFIX_OWN.equalsIgnoreCase(wpt.getPrefix())) {
- infoTextList.add(res.getString(R.string.waypoint_custom));
- } else {
- if (StringUtils.isNotBlank(wpt.getPrefix())) {
- infoTextList.add(wpt.getPrefix());
- }
- if (StringUtils.isNotBlank(wpt.getLookup())) {
- infoTextList.add(wpt.getLookup());
- }
- }
- if (CollectionUtils.isNotEmpty(infoTextList)) {
+ final String waypointInfo = Formatter.formatWaypointInfo(wpt);
+ if (StringUtils.isNotBlank(waypointInfo)) {
final TextView infoView = (TextView) waypointView.findViewById(R.id.info);
- infoView.setText(StringUtils.join(infoTextList, Formatter.SEPARATOR));
+ infoView.setText(waypointInfo);
infoView.setVisibility(View.VISIBLE);
}
diff --git a/main/src/cgeo/geocaching/DirectionProvider.java b/main/src/cgeo/geocaching/DirectionProvider.java
index 7bb940f..14fd283 100644
--- a/main/src/cgeo/geocaching/DirectionProvider.java
+++ b/main/src/cgeo/geocaching/DirectionProvider.java
@@ -14,6 +14,12 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
private final SensorManager sensorManager;
+ // Previous values signalled to observers to avoid resending the same value when the
+ // device doesn't change orientation. The orientation is usually given with a 1 degree
+ // precision by Android, so it is not uncommon to obtain exactly the same value several
+ // times.
+ private float previous = -1;
+
public DirectionProvider(final Context context) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
@@ -46,7 +52,11 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
@Override
public void onSensorChanged(final SensorEvent event) {
- notifyObservers(event.values[0]);
+ final float direction = event.values[0];
+ if (direction != previous) {
+ notifyObservers(direction);
+ previous = direction;
+ }
}
/**
@@ -57,7 +67,7 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
* @return the adjusted direction in degrees, in the [0, 360[ range
*/
public static float getDirectionNow(final Activity activity, final float direction) {
- return Compatibility.getDirectionNow(direction, activity) % 360;
+ return Compatibility.getDirectionNow(direction, activity);
}
}
diff --git a/main/src/cgeo/geocaching/GeoDataProvider.java b/main/src/cgeo/geocaching/GeoDataProvider.java
index 441c871..1b9a0f5 100644
--- a/main/src/cgeo/geocaching/GeoDataProvider.java
+++ b/main/src/cgeo/geocaching/GeoDataProvider.java
@@ -168,11 +168,41 @@ class GeoDataProvider extends MemorySubject<IGeoData> {
GeoDataProvider(final Context context) {
geoManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
unregisterer.start();
- // Start with an empty GeoData just in case someone queries it before we get
+
+ final Location initialLocation = new Location(LAST_LOCATION_PSEUDO_PROVIDER);
+ try {
+ // Try to find a sensible initial location from the last locations known to Android.
+ final Location lastGpsLocation = geoManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ final Location lastNetworkLocation = geoManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
+
+ // If both providers are non-null, take the most recent one
+ if (lastGpsLocation != null && lastNetworkLocation != null) {
+ if (lastGpsLocation.getTime() >= lastNetworkLocation.getTime()) {
+ copyCoords(initialLocation, lastGpsLocation);
+ } else {
+ copyCoords(initialLocation, lastNetworkLocation);
+ }
+ } else if (lastGpsLocation != null) {
+ copyCoords(initialLocation, lastGpsLocation);
+ } else if (lastNetworkLocation != null) {
+ copyCoords(initialLocation, lastNetworkLocation);
+ } else {
+ Log.i("GeoDataProvider: no last known location available");
+ }
+ } catch (final Exception e) {
+ // This error is non-fatal as its only consequence is that we will start with a dummy location
+ // instead of a previously known one.
+ Log.e("GeoDataProvider: error when retrieving last known location", e);
+ }
+ // Start with an historical GeoData just in case someone queries it before we get
// a chance to get any information.
- notifyObservers(new GeoData(new Location(LAST_LOCATION_PSEUDO_PROVIDER), false, 0, 0));
+ notifyObservers(new GeoData(initialLocation, false, 0, 0));
}
+ private static void copyCoords(final Location target, final Location source) {
+ target.setLatitude(source.getLatitude());
+ target.setLongitude(source.getLongitude());
+ }
private void registerListeners() {
geoManager.addGpsStatusListener(gpsStatusListener);
diff --git a/main/src/cgeo/geocaching/ICache.java b/main/src/cgeo/geocaching/ICache.java
index a4f5eda..d76bacc 100644
--- a/main/src/cgeo/geocaching/ICache.java
+++ b/main/src/cgeo/geocaching/ICache.java
@@ -17,12 +17,12 @@ public interface ICache extends IBasicCache {
/**
* @return Displayed owner, might differ from the real owner
*/
- public String getOwner();
+ public String getOwnerDisplayName();
/**
* @return GC username of the (actual) owner, might differ from the owner. Never empty.
*/
- public String getOwnerReal();
+ public String getOwnerUserId();
/**
* @return true if the user is the owner of the cache, false else
diff --git a/main/src/cgeo/geocaching/LiveMapInfo.java b/main/src/cgeo/geocaching/LiveMapInfo.java
index 822fbf6..2fee940 100644
--- a/main/src/cgeo/geocaching/LiveMapInfo.java
+++ b/main/src/cgeo/geocaching/LiveMapInfo.java
@@ -13,7 +13,6 @@ public class LiveMapInfo extends AbstractActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setTheme(R.style.transparent);
setContentView(R.layout.livemapinfo);
final int showCount = Settings.getLiveMapHintShowCount();
diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java
index 31a9703..e03dc66 100644
--- a/main/src/cgeo/geocaching/LogEntry.java
+++ b/main/src/cgeo/geocaching/LogEntry.java
@@ -1,6 +1,7 @@
package cgeo.geocaching;
import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.utils.DateUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -94,15 +95,6 @@ public final class LogEntry {
}
public int daysSinceLog() {
- final Calendar logDate = Calendar.getInstance();
- logDate.setTimeInMillis(date);
- logDate.set(Calendar.SECOND, 0);
- logDate.set(Calendar.MINUTE, 0);
- logDate.set(Calendar.HOUR, 0);
- final Calendar today = Calendar.getInstance();
- today.set(Calendar.SECOND, 0);
- today.set(Calendar.MINUTE, 0);
- today.set(Calendar.HOUR, 0);
- return (int) Math.round((today.getTimeInMillis() - logDate.getTimeInMillis()) / 86400000d);
+ return DateUtils.daysSince(date);
}
}
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index 2a0d503..578bd62 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -247,8 +247,8 @@ public class LogTrackableActivity extends AbstractActivity implements DateDialog
});
final Button dateButton = (Button) findViewById(R.id.date);
- dateButton.setText(Formatter.formatShortDate(date.getTime().getTime()));
dateButton.setOnClickListener(new DateListener());
+ setDate(date);
if (tweetBox == null) {
tweetBox = (LinearLayout) findViewById(R.id.tweet_box);
@@ -281,7 +281,7 @@ public class LogTrackableActivity extends AbstractActivity implements DateDialog
date = dateIn;
final Button dateButton = (Button) findViewById(R.id.date);
- dateButton.setText(Formatter.formatShortDate(date.getTime().getTime()));
+ dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime()));
}
public void setType(LogType type) {
diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java
index 2d86c2f..bbcb80b 100644
--- a/main/src/cgeo/geocaching/Settings.java
+++ b/main/src/cgeo/geocaching/Settings.java
@@ -94,6 +94,7 @@ public final class Settings {
private static final String KEY_SETTINGS_VERSION = "settingsversion";
private static final String KEY_DB_ON_SDCARD = "dbonsdcard";
private static final String KEY_LAST_TRACKABLE_ACTION = "trackableaction";
+ private static final String KEY_SHARE_AFTER_EXPORT = "shareafterexport";
private final static int unitsMetric = 1;
@@ -202,7 +203,7 @@ public final class Settings {
e.putBoolean(KEY_HIDE_LIVE_MAP_HINT, old.getInt(KEY_HIDE_LIVE_MAP_HINT, 0) != 0);
e.putInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, old.getInt(KEY_LIVE_MAP_HINT_SHOW_COUNT, 0));
- e.putInt(KEY_SETTINGS_VERSION, 1) ; // mark migrated
+ e.putInt(KEY_SETTINGS_VERSION, 1); // mark migrated
e.commit();
}
}
@@ -1109,7 +1110,6 @@ public final class Settings {
});
}
-
public static boolean isDebug() {
return Log.isDebug();
}
@@ -1117,7 +1117,8 @@ public final class Settings {
public static void setDebug(final boolean debug) {
editSharedSettings(new PrefRunnable() {
- @Override public void edit(Editor edit) {
+ @Override
+ public void edit(Editor edit) {
edit.putBoolean(KEY_DEBUG, debug);
}
});
@@ -1158,7 +1159,6 @@ public final class Settings {
public static void setDbOnSDCard(final boolean dbOnSDCard) {
editSharedSettings(new PrefRunnable() {
-
@Override
public void edit(Editor edit) {
edit.putBoolean(KEY_DB_ON_SDCARD, dbOnSDCard);
@@ -1166,6 +1166,15 @@ public final class Settings {
});
}
+ public static void setShareAfterExport(final boolean shareAfterExport) {
+ editSharedSettings(new PrefRunnable() {
+ @Override
+ public void edit(Editor edit) {
+ edit.putBoolean(KEY_SHARE_AFTER_EXPORT, shareAfterExport);
+ }
+ });
+ }
+
public static int getTrackableAction() {
return sharedPrefs.getInt(KEY_LAST_TRACKABLE_ACTION, LogType.RETRIEVED_IT.id);
}
@@ -1178,6 +1187,10 @@ public final class Settings {
edit.putInt(KEY_LAST_TRACKABLE_ACTION, trackableAction);
}
});
+ }
+
+ public static boolean getShareAfterExport() {
+ return sharedPrefs.getBoolean(KEY_SHARE_AFTER_EXPORT, true);
}
public static String getPreferencesName() {
diff --git a/main/src/cgeo/geocaching/SettingsActivity.java b/main/src/cgeo/geocaching/SettingsActivity.java
index b87bd73..d70b300 100644
--- a/main/src/cgeo/geocaching/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/SettingsActivity.java
@@ -19,6 +19,7 @@ import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogTemplate;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -57,6 +58,7 @@ public class SettingsActivity extends AbstractActivity {
private ProgressDialog loginDialog = null;
private ProgressDialog webDialog = null;
+ private boolean enableTemplatesMenu = false;
private Handler logInHandler = new Handler() {
@Override
@@ -115,7 +117,6 @@ public class SettingsActivity extends AbstractActivity {
init();
}
};
- protected boolean enableTemplatesMenu = false;
public SettingsActivity() {
super("c:geo-configuration");
@@ -135,12 +136,6 @@ public class SettingsActivity extends AbstractActivity {
}
@Override
- public void onResume() {
- super.onResume();
-
- }
-
- @Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -594,7 +589,7 @@ public class SettingsActivity extends AbstractActivity {
// Default navigation tool settings
Spinner defaultNavigationToolSelector = (Spinner) findViewById(R.id.default_navigation_tool);
- final List<NavigationAppsEnum> apps = NavigationAppFactory.getInstalledNavigationApps();
+ final List<NavigationAppsEnum> apps = NavigationAppFactory.getInstalledDefaultNavigationApps();
ArrayAdapter<NavigationAppsEnum> naviAdapter = new ArrayAdapter<NavigationAppsEnum>(this, android.R.layout.simple_spinner_item, apps) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
@@ -602,6 +597,7 @@ public class SettingsActivity extends AbstractActivity {
textView.setText(getItem(position).app.getName());
return textView;
}
+
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView) super.getDropDownView(position, convertView, parent);
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index a95f4d2..7ddc4e0 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -135,42 +135,28 @@ public class StaticMapsActivity extends AbstractActivity {
factory = new BitmapFactory();
}
- for (int level = 1; level <= 5; level++) {
- try {
- if (waypoint_id != null) {
- final Bitmap image = BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, "wp" + waypoint_id + "_" + level, false).getPath());
- if (image != null) {
- maps.add(image);
- }
- } else {
- final Bitmap image = BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, "" + level, false).getPath());
- if (image != null) {
- maps.add(image);
- }
- }
- } catch (Exception e) {
- Log.e("StaticMapsActivity.LoadMapsThread.run.1: " + e.toString());
- }
- }
-
- if (maps.isEmpty()) {
+ // try downloading 2 times
+ for (int trials = 0; trials < 2; trials++) {
for (int level = 1; level <= 5; level++) {
try {
if (waypoint_id != null) {
- final Bitmap image = BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, "wp" + waypoint_id + "_" + level, false).getPath());
+ final Bitmap image = StaticMapsProvider.getWaypointMap(geocode, waypoint_id, level);
if (image != null) {
maps.add(image);
}
} else {
- final Bitmap image = BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, "" + level, false).getPath());
+ final Bitmap image = StaticMapsProvider.getCacheMap(geocode, level);
if (image != null) {
maps.add(image);
}
}
} catch (Exception e) {
- Log.e("StaticMapsActivity.LoadMapsThread.run.2: " + e.toString());
+ Log.e("StaticMapsActivity.LoadMapsThread.run: " + e.toString());
}
}
+ if (!maps.isEmpty()) {
+ break;
+ }
}
loadMapsHandler.sendMessage(Message.obtain());
@@ -201,13 +187,13 @@ public class StaticMapsActivity extends AbstractActivity {
if (waypoint_id == null) {
showToast(res.getString(R.string.info_storing_static_maps));
StaticMapsProvider.storeCacheStaticMap(cache, this, true);
- return StaticMapsProvider.doesExistStaticMapForCache(geocode);
+ return StaticMapsProvider.hasStaticMapForCache(geocode);
}
final cgWaypoint waypoint = cache.getWaypointById(waypoint_id);
if (waypoint != null) {
showToast(res.getString(R.string.info_storing_static_maps));
StaticMapsProvider.storeWaypointStaticMap(cache, this, waypoint, true);
- return StaticMapsProvider.doesExistStaticMapForWaypoint(geocode, waypoint_id);
+ return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint_id);
}
showToast(res.getString(R.string.err_detail_not_load_map_static));
return false;
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index 030efeb..6de1291 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -8,11 +8,14 @@ import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
@@ -21,6 +24,7 @@ import java.io.File;
import java.util.concurrent.TimeUnit;
public class StaticMapsProvider {
+ private static final String PREFIX_PREVIEW = "preview";
private static final String GOOGLE_STATICMAP_URL = "http://maps.google.com/maps/api/staticmap";
private static final String SATELLITE = "satellite";
private static final String ROADMAP = "roadmap";
@@ -32,7 +36,7 @@ public class StaticMapsProvider {
/** ThreadPool restricting this to 1 Thread. **/
private static final BlockingThreadPool pool = new BlockingThreadPool(1, Thread.MIN_PRIORITY);
- public static File getMapFile(final String geocode, String prefix, final boolean createDirs) {
+ private static File getMapFile(final String geocode, String prefix, final boolean createDirs) {
return LocalStorage.getStorageFile(geocode, MAP_FILENAME_PREFIX + prefix, false, createDirs);
}
@@ -48,7 +52,7 @@ public class StaticMapsProvider {
final Parameters params = new Parameters(
"center", latlonMap,
"zoom", String.valueOf(zoom),
- "size", width + "x" + height,
+ "size", String.valueOf(width) + 'x' + String.valueOf(height),
"maptype", mapType,
"markers", "icon:" + markerUrl + '|' + shadow + latlonMap,
"sensor", "false");
@@ -80,7 +84,7 @@ public class StaticMapsProvider {
downloadMaps(cache, display);
}
- public static void downloadMaps(cgCache cache, Display display) {
+ private static void downloadMaps(cgCache cache, Display display) {
if ((!Settings.isStoreOfflineMaps() && !Settings.isStoreOfflineWpMaps()) || StringUtils.isBlank(cache.getGeocode())) {
return;
}
@@ -114,7 +118,7 @@ public class StaticMapsProvider {
String wpLatlonMap = waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA);
String wpMarkerUrl = getWpMarkerUrl(waypoint);
// download map images in separate background thread for higher performance
- downloadMaps(geocode, wpMarkerUrl, WAYPOINT_PREFIX + waypoint.getId() + "_", wpLatlonMap, edge, null, waitForResult);
+ downloadMaps(geocode, wpMarkerUrl, WAYPOINT_PREFIX + waypoint.getId() + '_', wpLatlonMap, edge, null, waitForResult);
}
public static void storeCacheStaticMap(cgCache cache, Activity activity, final boolean waitForResult) {
@@ -130,7 +134,7 @@ public class StaticMapsProvider {
continue;
}
final String wpMarkerUrl = getWpMarkerUrl(waypoint);
- waypoints.put("markers", "icon:" + wpMarkerUrl + "|" + waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA));
+ waypoints.put("markers", "icon:" + wpMarkerUrl + '|' + waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA));
}
// download map images in separate background thread for higher performance
final String cacheMarkerUrl = getCacheMarkerUrl(cache);
@@ -145,7 +149,7 @@ public class StaticMapsProvider {
display.getMetrics(metrics);
final int width = metrics.widthPixels;
final int height = (int) (110 * metrics.density);
- downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, "preview", "shadow:false|", latlonMap, width, height, null);
+ downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, width, height, null);
}
private static int guessMaxDisplaySide(Display display) {
@@ -182,14 +186,15 @@ public class StaticMapsProvider {
}
private static String getCacheMarkerUrl(final cgCache cache) {
- String type = cache.getType().id;
+ StringBuilder url = new StringBuilder(MARKERS_URL);
+ url.append("marker_cache_").append(cache.getType().id);
if (cache.isFound()) {
- type += "_found";
+ url.append("_found");
} else if (cache.isDisabled()) {
- type += "_disabled";
+ url.append("_disabled");
}
-
- return MARKERS_URL + "marker_cache_" + type + ".png";
+ url.append(".png");
+ return url.toString();
}
private static String getWpMarkerUrl(final cgWaypoint waypoint) {
@@ -198,11 +203,12 @@ public class StaticMapsProvider {
}
public static void removeWpStaticMaps(int wp_id, final String geocode) {
+ if (wp_id <= 0) {
+ return;
+ }
for (int level = 1; level <= 5; level++) {
try {
- if (wp_id > 0) {
- StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + wp_id + "_" + level, false).delete();
- }
+ StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + wp_id + '_' + level, false).delete();
} catch (Exception e) {
Log.e("StaticMapsProvider.removeWpStaticMaps: " + e.toString());
}
@@ -215,9 +221,9 @@ public class StaticMapsProvider {
* @param geocode
* @return <code>true</code> if at least one mapfile exists; <code>false</code> otherwise
*/
- public static boolean doesExistStaticMapForCache(String geocode) {
+ public static boolean hasStaticMapForCache(String geocode) {
for (int level = 1; level <= 5; level++) {
- File mapFile = StaticMapsProvider.getMapFile(geocode, "" + level, false);
+ File mapFile = StaticMapsProvider.getMapFile(geocode, String.valueOf(level), false);
if (mapFile != null && mapFile.exists()) {
return true;
}
@@ -232,7 +238,7 @@ public class StaticMapsProvider {
* @param waypointId
* @return <code>true</code> if at least one mapfile exists; <code>false</code> otherwise
*/
- public static boolean doesExistStaticMapForWaypoint(String geocode, int waypointId) {
+ public static boolean hasStaticMapForWaypoint(String geocode, int waypointId) {
for (int level = 1; level <= 5; level++) {
File mapFile = StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + waypointId + "_" + level, false);
if (mapFile != null && mapFile.exists()) {
@@ -241,4 +247,16 @@ public class StaticMapsProvider {
}
return false;
}
+
+ public static Bitmap getPreviewMap(final String geocode) {
+ return BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, PREFIX_PREVIEW, false).getPath());
+ }
+
+ public static Bitmap getWaypointMap(final String geocode, int waypoint_id, int level) {
+ return BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + waypoint_id + "_" + level, false).getPath());
+ }
+
+ public static Bitmap getCacheMap(final String geocode, int level) {
+ return BitmapFactory.decodeFile(StaticMapsProvider.getMapFile(geocode, String.valueOf(level), false).getPath());
+ }
}
diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java
index c211157..e5410e7 100644
--- a/main/src/cgeo/geocaching/VisitCacheActivity.java
+++ b/main/src/cgeo/geocaching/VisitCacheActivity.java
@@ -510,7 +510,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D
});
final Button dateButton = (Button) findViewById(R.id.date);
- dateButton.setText(Formatter.formatShortDate(date.getTime().getTime()));
+ setDate(date);
dateButton.setOnClickListener(new DateListener());
final EditText logView = (EditText) findViewById(R.id.log);
@@ -548,7 +548,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D
date = dateIn;
final Button dateButton = (Button) findViewById(R.id.date);
- dateButton.setText(Formatter.formatShortDate(date.getTime().getTime()));
+ dateButton.setText(Formatter.formatShortDateVerbally(date.getTime().getTime()));
}
public void setType(LogType type) {
@@ -602,6 +602,7 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D
@Override
public void onClick(View arg0) {
+ //TODO: unify this method and the code in init()
app.clearLogOffline(geocode);
if (alreadyFound) {
@@ -615,8 +616,8 @@ public class VisitCacheActivity extends AbstractActivity implements DateDialog.D
setType(typeSelected);
final Button dateButton = (Button) findViewById(R.id.date);
- dateButton.setText(Formatter.formatShortDate(date.getTime().getTime()));
dateButton.setOnClickListener(new DateListener());
+ setDate(date);
final EditText logView = (EditText) findViewById(R.id.log);
logView.setText("");
diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java
index 5a90238..a648486 100644
--- a/main/src/cgeo/geocaching/activity/AbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java
@@ -1,7 +1,6 @@
package cgeo.geocaching.activity;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.network.Cookies;
@@ -10,7 +9,6 @@ import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.view.Menu;
import android.view.View;
import android.widget.EditText;
@@ -90,10 +88,6 @@ public abstract class AbstractActivity extends Activity implements IAbstractActi
ActivityMixin.keepScreenOn(this, keepScreenOn);
}
- public void addVisitMenu(Menu menu, cgCache cache) {
- ActivityMixin.addVisitMenu(this, menu, cache);
- }
-
protected static void disableSuggestions(final EditText edit) {
Compatibility.disableSuggestions(edit);
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
index a209b23..dc9c0fe 100644
--- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
@@ -1,6 +1,5 @@
package cgeo.geocaching.activity;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
@@ -8,7 +7,6 @@ import android.app.ListActivity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.view.Menu;
import android.view.View;
public abstract class AbstractListActivity extends ListActivity implements
@@ -85,10 +83,6 @@ public abstract class AbstractListActivity extends ListActivity implements
ActivityMixin.setTitle(this, title);
}
- public void addVisitMenu(Menu menu, cgCache cache) {
- ActivityMixin.addVisitMenu(this, menu, cache);
- }
-
@Override
public void invalidateOptionsMenuCompatible() {
Compatibility.invalidateOptionsMenu(this);
diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java
index 8d5611b..8900593 100644
--- a/main/src/cgeo/geocaching/activity/ActivityMixin.java
+++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java
@@ -2,10 +2,8 @@ package cgeo.geocaching.activity;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeo;
import cgeo.geocaching.compatibility.Compatibility;
-import cgeo.geocaching.enumerations.LogType;
import org.apache.commons.lang3.StringUtils;
@@ -14,11 +12,8 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
-import android.view.Menu;
-import android.view.SubMenu;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
@@ -27,10 +22,7 @@ import android.widget.Toast;
import gnu.android.app.appmanualclient.AppManualReaderClient;
-import java.util.List;
-
public final class ActivityMixin {
- private static final int MENU_ICON_LOG_VISIT = R.drawable.ic_menu_edit;
public final static void goHome(final Activity fromActivity) {
final Intent intent = new Intent(fromActivity, cgeo.class);
@@ -129,27 +121,6 @@ public final class ActivityMixin {
helpDialog(activity, title, message, null);
}
- protected static void addVisitMenu(IAbstractActivity activity, Menu menu, cgCache cache) {
- if (cache == null) {
- return;
- }
- if (!cache.supportsLogging()) {
- return;
- }
- Resources res = ((Activity) activity).getResources();
- if (Settings.getLogOffline()) {
- SubMenu logMenu = menu.addSubMenu(1, IAbstractActivity.MENU_LOG_VISIT_OFFLINE, 0, res.getString(R.string.cache_menu_visit_offline)).setIcon(MENU_ICON_LOG_VISIT);
- List<LogType> logTypes = cache.getPossibleLogTypes();
- for (LogType logType : logTypes) {
- logMenu.add(1, IAbstractActivity.MENU_LOG_VISIT_OFFLINE + logType.id, 0, logType.getL10n());
- }
- logMenu.add(1, IAbstractActivity.MENU_LOG_VISIT, 0, res.getString(R.string.cache_menu_visit));
- }
- else {
- menu.add(1, IAbstractActivity.MENU_LOG_VISIT, 0, res.getString(R.string.cache_menu_visit)).setIcon(MENU_ICON_LOG_VISIT);
- }
- }
-
public static void keepScreenOn(final Activity abstractActivity, boolean keepScreenOn) {
if (keepScreenOn) {
abstractActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
diff --git a/main/src/cgeo/geocaching/activity/IAbstractActivity.java b/main/src/cgeo/geocaching/activity/IAbstractActivity.java
index 2503b99..04709c6 100644
--- a/main/src/cgeo/geocaching/activity/IAbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/IAbstractActivity.java
@@ -3,8 +3,6 @@ package cgeo.geocaching.activity;
import android.view.View;
public interface IAbstractActivity {
- static final int MENU_LOG_VISIT = 100;
- static final int MENU_LOG_VISIT_OFFLINE = 101;
public void goHome(View view);
diff --git a/main/src/cgeo/geocaching/activity/Progress.java b/main/src/cgeo/geocaching/activity/Progress.java
index dbe4700..7a1995d 100644
--- a/main/src/cgeo/geocaching/activity/Progress.java
+++ b/main/src/cgeo/geocaching/activity/Progress.java
@@ -27,6 +27,7 @@ public class Progress {
dialog = ProgressDialog.show(context, title, message, indeterminate, cancelMessage != null);
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
dialog.setProgress(0);
+ dialog.setCanceledOnTouchOutside(false);
this.progress = 0;
if (cancelMessage != null) {
dialog.setCancelMessage(cancelMessage);
@@ -38,6 +39,7 @@ public class Progress {
if (dialog == null) {
dialog = new ProgressDialog(context);
dialog.setProgress(0);
+ dialog.setCanceledOnTouchOutside(false);
this.progress = 0;
dialog.setTitle(title);
dialog.setMessage(message);
diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java
index 9acc0ae..5bed2d9 100644
--- a/main/src/cgeo/geocaching/apps/AbstractApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractApp.java
@@ -47,6 +47,11 @@ public abstract class AbstractApp implements App {
}
@Override
+ public boolean isDefaultNavigationApp() {
+ return true;
+ }
+
+ @Override
public String getName() {
return name;
}
diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
index 8f5160a..ac6fc1c 100644
--- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
@@ -123,7 +123,7 @@ public abstract class AbstractLocusApp extends AbstractApp {
pg.archived = cache.isArchived();
pg.premiumOnly = cache.isPremiumMembersOnly();
pg.name = cache.getName();
- pg.placedBy = cache.getOwner();
+ pg.placedBy = cache.getOwnerDisplayName();
if (cache.getHiddenDate() != null) {
pg.hidden = ISO8601DATE.format(cache.getHiddenDate().getTime());
}
diff --git a/main/src/cgeo/geocaching/apps/App.java b/main/src/cgeo/geocaching/apps/App.java
index 2e5e730..9d6d371 100644
--- a/main/src/cgeo/geocaching/apps/App.java
+++ b/main/src/cgeo/geocaching/apps/App.java
@@ -5,6 +5,8 @@ import cgeo.geocaching.cgCache;
public interface App {
public boolean isInstalled();
+ public boolean isDefaultNavigationApp();
+
public String getName();
int getId();
diff --git a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java b/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java
index 22ce677..98e7db8 100644
--- a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java
@@ -31,14 +31,15 @@ public final class GeneralAppsFactory extends AbstractAppFactory {
public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgCache cache) {
final GeneralApp app = (GeneralApp) getAppFromMenuItem(item, apps);
- if (app != null) {
- try {
- return app.invoke(activity, cache);
- } catch (Exception e) {
- Log.e("GeneralAppsFactory.onMenuItemSelected: " + e.toString());
- }
+ if (app == null) {
+ return false;
+ }
+ try {
+ app.invoke(activity, cache);
+ } catch (Exception e) {
+ Log.e("GeneralAppsFactory.onMenuItemSelected: " + e.toString());
}
- return false;
+ return true;
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
index 5817763..ca8c7db 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
@@ -2,14 +2,14 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.apps.AbstractApp;
import android.app.Activity;
/**
* navigation app for simple point navigation (no differentiation between cache/waypoint/point)
*/
-abstract class AbstractPointNavigationApp extends AbstractNavigationApp {
+abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp {
protected AbstractPointNavigationApp(String name, String intent) {
super(name, intent);
@@ -20,46 +20,22 @@ abstract class AbstractPointNavigationApp extends AbstractNavigationApp {
}
@Override
- public final boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, Geopoint coords) {
- if (cache == null && waypoint == null && coords == null) {
- return false;
- }
-
- try {
- if (isInstalled()) {
- final Geopoint point = getCoordinates(cache, waypoint, coords);
- if (point != null) {
- navigate(activity, point);
- return true;
- }
- }
- } catch (Exception e) {
- // nothing
- }
-
- return false;
+ public void navigate(Activity activity, cgCache cache) {
+ navigate(activity, cache.getCoords());
}
- protected abstract void navigate(Activity activity, Geopoint point);
-
- /**
- * Return the first of the cache coordinates, the waypoint coordinates or the extra coordinates. <code>null</code>
- * entities are skipped.
- *
- * @param cache a cache
- * @param waypoint a waypoint
- * @param coords extra coordinates
- * @return the first non-null coordinates, or null if none are set
- */
- private static Geopoint getCoordinates(final cgCache cache, final cgWaypoint waypoint, final Geopoint coords) {
- if (cache != null && cache.getCoords() != null) {
- return cache.getCoords();
- }
+ @Override
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ navigate(activity, waypoint.getCoords());
+ }
- if (waypoint != null && waypoint.getCoords() != null) {
- return waypoint.getCoords();
- }
+ @Override
+ public boolean isEnabled(cgCache cache) {
+ return cache.getCoords() != null;
+ }
- return coords;
+ @Override
+ public boolean isEnabled(cgWaypoint waypoint) {
+ return waypoint.getCoords() != null;
}
-} \ No newline at end of file
+}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
index 266acfd..dacb03f 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
@@ -8,13 +8,13 @@ import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.apps.AbstractApp;
import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
-abstract class AbstractStaticMapsApp extends AbstractNavigationApp {
+abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp {
public AbstractStaticMapsApp(String name) {
super(name, null);
}
@@ -24,28 +24,29 @@ abstract class AbstractStaticMapsApp extends AbstractNavigationApp {
return true;
}
+ @Override
+ public boolean isDefaultNavigationApp() {
+ return false;
+ }
+
protected static boolean hasStaticMap(cgCache cache) {
- if (cache != null) {
- String geocode = cache.getGeocode();
- if (StringUtils.isNotEmpty(geocode) && cgeoapplication.getInstance().isOffline(geocode, null)) {
- return StaticMapsProvider.doesExistStaticMapForCache(geocode);
- }
+ String geocode = cache.getGeocode();
+ if (StringUtils.isNotEmpty(geocode) && cgeoapplication.getInstance().isOffline(geocode, null)) {
+ return StaticMapsProvider.hasStaticMapForCache(geocode);
}
return false;
}
protected static boolean hasStaticMap(cgWaypoint waypoint) {
- if (waypoint != null) {
- String geocode = waypoint.getGeocode();
- int id = waypoint.getId();
- if (StringUtils.isNotEmpty(geocode) && cgeoapplication.getInstance().isOffline(geocode, null)) {
- return StaticMapsProvider.doesExistStaticMapForWaypoint(geocode, id);
- }
+ String geocode = waypoint.getGeocode();
+ int id = waypoint.getId();
+ if (StringUtils.isNotEmpty(geocode) && cgeoapplication.getInstance().isOffline(geocode, null)) {
+ return StaticMapsProvider.hasStaticMapForWaypoint(geocode, id);
}
return false;
}
- protected static boolean invoke(final Activity activity, final cgCache cache, final cgWaypoint waypoint, final boolean download) {
+ protected static boolean invokeStaticMaps(final Activity activity, final cgCache cache, final cgWaypoint waypoint, final boolean download) {
final ILogable logable = cache != null && cache.getListId() != 0 ? cache : waypoint;
final String geocode = StringUtils.upperCase(logable.getGeocode());
if (geocode == null) {
@@ -56,11 +57,4 @@ abstract class AbstractStaticMapsApp extends AbstractNavigationApp {
StaticMapsActivity.startActivity(activity, geocode, download, waypoint);
return true;
}
-
-
- @Override
- public boolean isEnabled(Geopoint geopoint) {
- return false;
- }
-
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java
new file mode 100644
index 0000000..e47150f
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java
@@ -0,0 +1,17 @@
+package cgeo.geocaching.apps.cache.navi;
+
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.apps.App;
+
+import android.app.Activity;
+
+/**
+ * interface for navigation to a cache
+ *
+ */
+public interface CacheNavigationApp extends App {
+ void navigate(final Activity activity, final cgCache cache);
+
+ @Override
+ boolean isEnabled(final cgCache cache);
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
index 1576617..5275d53 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
@@ -4,11 +4,13 @@ import cgeo.geocaching.R;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeonavigate;
+import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.ui.Formatter;
import android.app.Activity;
-class CompassApp extends AbstractNavigationApp {
+class CompassApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp {
CompassApp() {
super(getString(R.string.compass_title), null);
@@ -20,22 +22,30 @@ class CompassApp extends AbstractNavigationApp {
}
@Override
- public boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint coords) {
-
- if (cache != null && cache.getGeocode() != null) {
- cgeonavigate.startActivity(activity, cache.getGeocode(), cache.getName(), cache.getCoords(), null);
- return true;
- }
- if (waypoint != null && waypoint.getCoords() != null) {
- cgeonavigate.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null);
- return true;
- }
- if (coords != null) {
- cgeonavigate.startActivity(activity, getString(R.string.navigation_direct_navigation), getString(R.string.navigation_target), coords, null);
- return true;
- }
- // search is not handled here
- return false;
+ public void navigate(Activity activity, Geopoint coords) {
+ cgeonavigate.startActivity(activity, getString(R.string.navigation_direct_navigation), getString(R.string.navigation_target), coords, null);
+ }
+
+ @Override
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ cgeonavigate.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null,
+ waypoint.getWaypointType().getL10n());
+ }
+
+ @Override
+ public boolean isEnabled(cgWaypoint waypoint) {
+ return waypoint.getCoords() != null;
+ }
+
+ @Override
+ public void navigate(Activity activity, cgCache cache) {
+ cgeonavigate.startActivity(activity, cache.getGeocode(), cache.getName(), cache.getCoords(), null,
+ Formatter.formatCacheInfoShort(cache));
+ }
+
+ @Override
+ public boolean isEnabled(cgCache cache) {
+ return cache.getGeocode() != null;
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
index 1625ef7..f093937 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.R;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.geopoint.Geopoint;
import android.app.Activity;
@@ -14,23 +13,22 @@ class DownloadStaticMapsApp extends AbstractStaticMapsApp {
}
@Override
- public boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint coords) {
- return invoke(activity, cache, waypoint, true);
- }
-
- @Override
public boolean isEnabled(cgCache cache) {
- if (cache == null) {
- return false;
- }
return !hasStaticMap(cache);
}
@Override
public boolean isEnabled(cgWaypoint waypoint) {
- if (waypoint == null) {
- return false;
- }
return !hasStaticMap(waypoint);
}
+
+ @Override
+ public void navigate(Activity activity, cgCache cache) {
+ invokeStaticMaps(activity, cache, null, true);
+ }
+
+ @Override
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ invokeStaticMaps(activity, null, waypoint, true);
+ }
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java
new file mode 100644
index 0000000..fe4fd5d
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GeopointNavigationApp.java
@@ -0,0 +1,13 @@
+package cgeo.geocaching.apps.cache.navi;
+
+import cgeo.geocaching.geopoint.Geopoint;
+
+import android.app.Activity;
+
+/**
+ * interface for navigation to a coordinate. This one cannot be enabled/disabled.
+ *
+ */
+public interface GeopointNavigationApp {
+ void navigate(final Activity activity, final Geopoint coords);
+}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java
index 4e6e62b..eac33cc 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsApp.java
@@ -21,7 +21,7 @@ class GoogleMapsApp extends AbstractPointNavigationApp {
}
@Override
- protected void navigate(Activity activity, Geopoint point) {
+ public void navigate(Activity activity, Geopoint point) {
// INFO: q parameter works with Google Maps, but breaks cooperation with all other apps
try {
activity.startActivity(new Intent(Intent.ACTION_VIEW,
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
index 31d99e9..7258e11 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
@@ -3,8 +3,6 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.geopoint.Geopoint;
@@ -14,7 +12,7 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
-class GoogleNavigationApp extends AbstractNavigationApp {
+class GoogleNavigationApp extends AbstractPointNavigationApp {
GoogleNavigationApp() {
super(getString(R.string.cache_menu_tbt), null);
@@ -25,33 +23,8 @@ class GoogleNavigationApp extends AbstractNavigationApp {
return true;
}
- @Override
- public boolean invoke(final Activity activity, final cgCache cache, final cgWaypoint waypoint, final Geopoint coords) {
- if (activity == null) {
- return false;
- }
-
+ private static boolean navigateToCoordinates(Activity activity, final Geopoint coords) {
IGeoData geo = cgeoapplication.getInstance().currentGeo();
- boolean navigationResult = false;
- if (coords != null) {
- navigationResult = navigateToCoordinates(geo, activity, coords);
- }
- else if (waypoint != null) {
- navigationResult = navigateToCoordinates(geo, activity, waypoint.getCoords());
- }
- else if (cache != null) {
- navigationResult = navigateToCoordinates(geo, activity, cache.getCoords());
- }
-
- if (!navigationResult) {
- ActivityMixin.showToast(activity, getString(R.string.err_navigation_no));
- return false;
- }
-
- return true;
- }
-
- private static boolean navigateToCoordinates(IGeoData geo, Activity activity, final Geopoint coords) {
final Geopoint coordsNow = geo == null ? null : geo.getCoords();
// Google Navigation
@@ -89,4 +62,10 @@ class GoogleNavigationApp extends AbstractNavigationApp {
return false;
}
+ @Override
+ public void navigate(Activity activity, Geopoint coords) {
+ if (!navigateToCoordinates(activity, coords)) {
+ ActivityMixin.showToast(activity, getString(R.string.err_navigation_no));
+ }
+ }
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
index f1e03ed..8185f40 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
@@ -3,37 +3,46 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.R;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.maps.CGeoMap;
import android.app.Activity;
-class InternalMap extends AbstractNavigationApp {
+class InternalMap extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp {
InternalMap() {
super(getString(R.string.cache_menu_map), null);
}
@Override
- public boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint coords) {
- if (cache != null) {
- CGeoMap.startActivityGeoCode(activity, cache.getGeocode());
- // may need some code from CGeoMap.startActivitySearch(activity, search, cache != null ? cache.getGeocode() : null, true);
- }
- else if (waypoint != null) {
- CGeoMap.startActivityCoords(activity, waypoint.getCoords(), waypoint.getWaypointType(), waypoint.getName());
- }
- else if (coords != null) {
- CGeoMap.startActivityCoords(activity, coords, WaypointType.WAYPOINT, null);
- }
-
+ public boolean isInstalled() {
return true;
}
@Override
- public boolean isInstalled() {
- return true;
+ public void navigate(Activity activity, Geopoint coords) {
+ CGeoMap.startActivityCoords(activity, coords, WaypointType.WAYPOINT, null);
}
+ @Override
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ CGeoMap.startActivityCoords(activity, waypoint.getCoords(), waypoint.getWaypointType(), waypoint.getName());
+ }
+
+ @Override
+ public boolean isEnabled(cgWaypoint waypoint) {
+ return waypoint.getCoords() != null;
+ }
+
+ @Override
+ public void navigate(Activity activity, cgCache cache) {
+ CGeoMap.startActivityGeoCode(activity, cache.getGeocode());
+ }
+
+ @Override
+ public boolean isEnabled(cgCache cache) {
+ return cache.getCoords() != null;
+ }
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
index d71a474..a20f2ce 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
@@ -3,45 +3,30 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.apps.AbstractLocusApp;
-import cgeo.geocaching.geopoint.Geopoint;
import android.app.Activity;
-import java.util.ArrayList;
+import java.util.Collections;
-class LocusApp extends AbstractLocusApp implements NavigationApp {
+class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointNavigationApp {
+
+ @Override
+ public boolean isEnabled(cgWaypoint waypoint) {
+ return waypoint.getCoords() != null;
+ }
/**
* Show a single cache with waypoints or a single waypoint in Locus.
* This method constructs a list of cache and waypoints only.
*
- * @see AbstractLocusApp#showInLocus
*/
@Override
- public boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint coords) {
-
- final ArrayList<Object> points = new ArrayList<Object>();
-
- // add cache if present
- if (cache != null && cache.getCoords() != null) {
- points.add(cache);
- }
-
- // add waypoint if present
- if (waypoint != null && waypoint.getCoords() != null) {
- points.add(waypoint);
- }
-
- return showInLocus(points, true, false, activity);
- }
-
- @Override
- public boolean isEnabled(cgWaypoint waypoint) {
- return waypoint != null;
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ showInLocus(Collections.singletonList(waypoint), true, false, activity);
}
@Override
- public boolean isEnabled(Geopoint geopoint) {
- return geopoint != null;
+ public void navigate(Activity activity, cgCache cache) {
+ showInLocus(Collections.singletonList(cache), true, false, activity);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index 95f6408..bf0517f 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -7,8 +7,8 @@ import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractAppFactory;
+import cgeo.geocaching.apps.App;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.utils.Log;
import android.app.Activity;
import android.app.AlertDialog;
@@ -48,7 +48,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
/** The external navigon app */
NAVIGON(new NavigonApp(), 10);
- NavigationAppsEnum(NavigationApp app, int id) {
+ NavigationAppsEnum(App app, int id) {
this.app = app;
this.id = id;
}
@@ -56,7 +56,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
/**
* The app instance to use
*/
- public final NavigationApp app;
+ public final App app;
/**
* The id - used in c:geo settings
*/
@@ -119,7 +119,17 @@ public final class NavigationAppFactory extends AbstractAppFactory {
for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if ((showInternalMap || !(navApp.app instanceof InternalMap)) &&
(showDefaultNavigation || defaultNavigationTool != navApp.id)) {
- if (navApp.app.isEnabled(cache) || navApp.app.isEnabled(waypoint) || navApp.app.isEnabled(destination)) {
+ boolean add = false;
+ if (cache != null && navApp.app instanceof CacheNavigationApp && ((CacheNavigationApp) navApp.app).isEnabled(cache)) {
+ add = true;
+ }
+ if (waypoint != null && navApp.app instanceof WaypointNavigationApp && ((WaypointNavigationApp) navApp.app).isEnabled(waypoint)) {
+ add = true;
+ }
+ if (destination != null && navApp.app instanceof GeopointNavigationApp) {
+ add = true;
+ }
+ if (add) {
items.add(navApp);
}
}
@@ -134,7 +144,18 @@ public final class NavigationAppFactory extends AbstractAppFactory {
@Override
public void onClick(DialogInterface dialog, int item) {
NavigationAppsEnum selectedItem = adapter.getItem(item);
- selectedItem.app.invoke(activity, cache, waypoint, destination);
+ if (cache != null) {
+ CacheNavigationApp cacheApp = (CacheNavigationApp) selectedItem.app;
+ cacheApp.navigate(activity, cache);
+ }
+ else if (waypoint != null) {
+ WaypointNavigationApp waypointApp = (WaypointNavigationApp) selectedItem.app;
+ waypointApp.navigate(activity, waypoint);
+ }
+ else {
+ GeopointNavigationApp geopointApp = (GeopointNavigationApp) selectedItem.app;
+ geopointApp.navigate(activity, destination);
+ }
}
});
final AlertDialog alert = builder.create();
@@ -157,6 +178,21 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
/**
+ * Returns all installed navigation apps for default navigation.
+ *
+ * @return
+ */
+ public static List<NavigationAppsEnum> getInstalledDefaultNavigationApps() {
+ final List<NavigationAppsEnum> installedNavigationApps = new ArrayList<NavigationAppsEnum>();
+ for (NavigationAppsEnum appEnum : NavigationAppsEnum.values()) {
+ if (appEnum.app.isInstalled() && appEnum.app.isDefaultNavigationApp()) {
+ installedNavigationApps.add(appEnum);
+ }
+ }
+ return installedNavigationApps;
+ }
+
+ /**
* This offset is used to build unique menu ids to avoid collisions of ids in menus
*/
private static final int MENU_ITEM_OFFSET = 12345;
@@ -174,16 +210,22 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*/
public static void addMenuItems(final Menu menu, final cgCache cache) {
for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
- if (navApp.app.isEnabled(cache)) {
- menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
+ if (navApp.app instanceof CacheNavigationApp) {
+ CacheNavigationApp cacheApp = (CacheNavigationApp) navApp.app;
+ if (cacheApp.isEnabled(cache)) {
+ menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
+ }
}
}
}
public static void addMenuItems(final Menu menu, final cgWaypoint waypoint) {
for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
- if (navApp.app.isEnabled(waypoint)) {
- menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
+ if (navApp.app instanceof WaypointNavigationApp) {
+ WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app;
+ if (waypointApp.isEnabled(waypoint)) {
+ menu.add(0, MENU_ITEM_OFFSET + navApp.id, 0, navApp.app.getName());
+ }
}
}
}
@@ -197,29 +239,39 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @return
*/
public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgCache cache) {
- return invokeApp(activity, cache, null, null, getAppFromMenuItem(item));
+ final App menuItem = getAppFromMenuItem(item);
+ navigateCache(activity, cache, menuItem);
+ return menuItem != null;
+ }
+
+ private static void navigateCache(Activity activity, cgCache cache, App app) {
+ if (app instanceof CacheNavigationApp) {
+ CacheNavigationApp cacheApp = (CacheNavigationApp) app;
+ cacheApp.navigate(activity, cache);
+ }
}
public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgWaypoint waypoint) {
- return invokeApp(activity, null, waypoint, null, getAppFromMenuItem(item));
+ final App menuItem = getAppFromMenuItem(item);
+ navigateWaypoint(activity, waypoint, menuItem);
+ return menuItem != null;
}
- private static boolean invokeApp(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint destination, final NavigationApp app) {
- if (app == null) {
- return false;
+ private static void navigateWaypoint(Activity activity, cgWaypoint waypoint, App app) {
+ if (app instanceof WaypointNavigationApp) {
+ WaypointNavigationApp waypointApp = (WaypointNavigationApp) app;
+ waypointApp.navigate(activity, waypoint);
}
- if (cache == null && waypoint == null && destination == null) {
- return false;
- }
- try {
- return app.invoke(activity, cache, waypoint, destination);
- } catch (Exception e) {
- Log.e("NavigationAppFactory.onMenuItemSelected: " + e.toString());
+ }
+
+ private static void navigateGeopoint(Activity activity, Geopoint destination, App app) {
+ if (app instanceof GeopointNavigationApp) {
+ GeopointNavigationApp geopointApp = (GeopointNavigationApp) app;
+ geopointApp.navigate(activity, destination);
}
- return false;
}
- private static NavigationApp getAppFromMenuItem(MenuItem item) {
+ private static App getAppFromMenuItem(MenuItem item) {
final int id = item.getItemId();
for (NavigationAppsEnum navApp : NavigationAppsEnum.values()) {
if (MENU_ITEM_OFFSET + navApp.id == id) {
@@ -243,10 +295,10 @@ public final class NavigationAppFactory extends AbstractAppFactory {
return;
}
- invokeApp(activity, cache, null, null, getDefaultNavigationApplication(defaultNavigation));
+ navigateCache(activity, cache, getDefaultNavigationApplication(defaultNavigation));
}
- private static NavigationApp getDefaultNavigationApplication(int defaultNavigation) {
+ private static App getDefaultNavigationApplication(int defaultNavigation) {
if (defaultNavigation == 2) {
return getNavigationAppFromSetting(Settings.getDefaultNavigationTool2());
}
@@ -264,7 +316,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown));
return;
}
- invokeApp(activity, null, waypoint, null, getDefaultNavigationApplication(defaultNavigation));
+ navigateWaypoint(activity, waypoint, getDefaultNavigationApplication(defaultNavigation));
}
/**
@@ -279,7 +331,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
return;
}
- invokeApp(activity, null, null, destination, getDefaultNavigationApplication(defaultNavigation));
+ navigateGeopoint(activity, destination, getDefaultNavigationApplication(defaultNavigation));
}
/**
@@ -287,11 +339,11 @@ public final class NavigationAppFactory extends AbstractAppFactory {
*
* @return never <code>null</code>
*/
- public static NavigationApp getDefaultNavigationApplication() {
+ public static App getDefaultNavigationApplication() {
return getNavigationAppFromSetting(Settings.getDefaultNavigationTool());
}
- private static NavigationApp getNavigationAppFromSetting(final int defaultNavigationTool) {
+ private static App getNavigationAppFromSetting(final int defaultNavigationTool) {
final List<NavigationAppsEnum> installedNavigationApps = getInstalledNavigationApps();
for (NavigationAppsEnum navigationApp : installedNavigationApps) {
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
index 69f63dc..7ea86fb 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigonApp.java
@@ -16,7 +16,7 @@ class NavigonApp extends AbstractPointNavigationApp {
}
@Override
- protected void navigate(Activity activity, Geopoint point) {
+ public void navigate(Activity activity, Geopoint point) {
final Intent intent = new Intent(INTENT);
/*
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java
index 27ec2fa..24ef81b 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/OruxMapsApp.java
@@ -15,7 +15,7 @@ class OruxMapsApp extends AbstractPointNavigationApp {
}
@Override
- protected void navigate(Activity activity, Geopoint point) {
+ public void navigate(Activity activity, Geopoint point) {
final Intent intent = new Intent(INTENT);
intent.putExtra("latitude", point.getLatitude());//latitude, wgs84 datum
intent.putExtra("longitude", point.getLongitude());//longitude, wgs84 datum
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
index 8044cc6..a481813 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.R;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter.Format;
@@ -11,7 +12,7 @@ import android.content.Intent;
import java.util.ArrayList;
-class RMapsApp extends AbstractNavigationApp {
+class RMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp, GeopointNavigationApp {
private static final String INTENT = "com.robert.maps.action.SHOW_POINTS";
@@ -20,29 +21,30 @@ class RMapsApp extends AbstractNavigationApp {
}
@Override
- public boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint coords) {
- try {
- final ArrayList<String> locations = new ArrayList<String>();
- if (cache != null && cache.getCoords() != null) {
- locations.add(cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA)
- + ";" + cache.getGeocode()
- + ";" + cache.getName());
- } else if (waypoint != null && waypoint.getCoords() != null) {
- locations.add(waypoint.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA)
- + ";" + waypoint.getLookup()
- + ";" + waypoint.getName());
- }
-
- if (!locations.isEmpty()) {
- final Intent intent = new Intent(INTENT);
- intent.putStringArrayListExtra("locations", locations);
- activity.startActivity(intent);
- return true;
- }
- } catch (Exception e) {
- // nothing
- }
-
- return false;
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ navigate(activity, waypoint.getCoords(), waypoint.getLookup(), waypoint.getName());
+ }
+
+ private static void navigate(Activity activity, Geopoint coords, String code, String name) {
+ final ArrayList<String> locations = new ArrayList<String>();
+ locations.add(coords.format(Format.LAT_LON_DECDEGREE_COMMA) + ";" + code + ";" + name);
+ final Intent intent = new Intent(INTENT);
+ intent.putStringArrayListExtra("locations", locations);
+ activity.startActivity(intent);
+ }
+
+ @Override
+ public boolean isEnabled(cgWaypoint waypoint) {
+ return waypoint.getCoords() != null;
+ }
+
+ @Override
+ public void navigate(Activity activity, cgCache cache) {
+ navigate(activity, cache.getCoords(), cache.getGeocode(), cache.getName());
+ }
+
+ @Override
+ public void navigate(Activity activity, Geopoint coords) {
+ navigate(activity, coords, "", "");
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java
index 3374691..b01539c 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/RadarApp.java
@@ -16,7 +16,7 @@ class RadarApp extends AbstractPointNavigationApp {
}
@Override
- protected void navigate(Activity activity, Geopoint point) {
+ public void navigate(Activity activity, Geopoint point) {
final Intent radarIntent = new Intent(INTENT);
radarIntent.putExtra("latitude", (float) point.getLatitude());
radarIntent.putExtra("longitude", (float) point.getLongitude());
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
index d805656..6be027f 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.R;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.geopoint.Geopoint;
import android.app.Activity;
@@ -14,23 +13,22 @@ class StaticMapApp extends AbstractStaticMapsApp {
}
@Override
- public boolean invoke(Activity activity, cgCache cache, cgWaypoint waypoint, final Geopoint coords) {
- return invoke(activity, cache, waypoint, false);
- }
-
- @Override
public boolean isEnabled(cgCache cache) {
- if (cache == null) {
- return false;
- }
return hasStaticMap(cache);
}
@Override
public boolean isEnabled(cgWaypoint waypoint) {
- if (waypoint == null) {
- return false;
- }
return hasStaticMap(waypoint);
}
+
+ @Override
+ public void navigate(Activity activity, cgCache cache) {
+ invokeStaticMaps(activity, cache, null, false);
+ }
+
+ @Override
+ public void navigate(Activity activity, cgWaypoint waypoint) {
+ invokeStaticMaps(activity, null, waypoint, false);
+ }
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
index 41f958d..012b94f 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StreetviewApp.java
@@ -22,7 +22,7 @@ class StreetviewApp extends AbstractPointNavigationApp {
}
@Override
- protected void navigate(Activity activity, Geopoint point) {
+ public void navigate(Activity activity, Geopoint point) {
try {
activity.startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("google.streetview:cbll=" + point.getLatitude() + "," + point.getLongitude())));
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java
new file mode 100644
index 0000000..7d3a706
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java
@@ -0,0 +1,15 @@
+package cgeo.geocaching.apps.cache.navi;
+
+import cgeo.geocaching.cgWaypoint;
+
+import android.app.Activity;
+
+/**
+ * interface for navigation to a waypoint
+ *
+ */
+public interface WaypointNavigationApp {
+ void navigate(final Activity activity, final cgWaypoint waypoint);
+
+ boolean isEnabled(final cgWaypoint waypoint);
+}
diff --git a/main/src/cgeo/geocaching/backup/CentralBackupAgent.java b/main/src/cgeo/geocaching/backup/CentralBackupAgent.java
index aef2b7b..f6b9024 100644
--- a/main/src/cgeo/geocaching/backup/CentralBackupAgent.java
+++ b/main/src/cgeo/geocaching/backup/CentralBackupAgent.java
@@ -2,9 +2,11 @@ package cgeo.geocaching.backup;
import cgeo.geocaching.Settings;
+import android.annotation.TargetApi;
import android.app.backup.BackupAgentHelper;
import android.app.backup.SharedPreferencesBackupHelper;
+@TargetApi(8)
public class CentralBackupAgent extends BackupAgentHelper {
private static final String PREFS_BACKUP_KEY = "prefs";
diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/cgCache.java
index c765678..b8590e5 100644
--- a/main/src/cgeo/geocaching/cgCache.java
+++ b/main/src/cgeo/geocaching/cgCache.java
@@ -1,6 +1,7 @@
package cgeo.geocaching;
import cgeo.geocaching.cgData.StorageLocation;
+import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
@@ -61,8 +62,8 @@ public class cgCache implements ICache, IWaypoint {
private CacheType cacheType = CacheType.UNKNOWN;
private String name = "";
private Spannable nameSp = null;
- private String owner = "";
- private String ownerReal = "";
+ private String ownerDisplayName = "";
+ private String ownerUserId = "";
private Date hidden = null;
private String hint = "";
private CacheSize size = CacheSize.UNKNOWN;
@@ -189,11 +190,11 @@ public class cgCache implements ICache, IWaypoint {
if (StringUtils.isBlank(nameSp)) {
nameSp = other.nameSp;
}
- if (StringUtils.isBlank(owner)) {
- owner = other.owner;
+ if (StringUtils.isBlank(ownerDisplayName)) {
+ ownerDisplayName = other.ownerDisplayName;
}
- if (StringUtils.isBlank(ownerReal)) {
- ownerReal = other.ownerReal;
+ if (StringUtils.isBlank(ownerUserId)) {
+ ownerUserId = other.ownerUserId;
}
if (hidden == null) {
hidden = other.hidden;
@@ -316,8 +317,8 @@ public class cgCache implements ICache, IWaypoint {
disabled == other.disabled &&
archived == other.archived &&
listId == other.listId &&
- StringUtils.equalsIgnoreCase(owner, other.owner) &&
- StringUtils.equalsIgnoreCase(ownerReal, other.ownerReal) &&
+ StringUtils.equalsIgnoreCase(ownerDisplayName, other.ownerDisplayName) &&
+ StringUtils.equalsIgnoreCase(ownerUserId, other.ownerUserId) &&
StringUtils.equalsIgnoreCase(description, other.description) &&
StringUtils.equalsIgnoreCase(personalNote, other.personalNote) &&
StringUtils.equalsIgnoreCase(shortdesc, other.shortdesc) &&
@@ -404,33 +405,33 @@ public class cgCache implements ICache, IWaypoint {
((Activity) fromActivity).startActivity(logVisitIntent);
}
- public void logOffline(final IAbstractActivity fromActivity, final LogType logType) {
+ public void logOffline(final Activity fromActivity, final LogType logType) {
final boolean mustIncludeSignature = StringUtils.isNotBlank(Settings.getSignature()) && Settings.isAutoInsertSignature();
final String initial = mustIncludeSignature ? LogTemplateProvider.applyTemplates(Settings.getSignature(), true) : "";
logOffline(fromActivity, initial, Calendar.getInstance(), logType);
}
- void logOffline(final IAbstractActivity fromActivity, final String log, Calendar date, final LogType logType) {
+ void logOffline(final Activity fromActivity, final String log, Calendar date, final LogType logType) {
if (logType == LogType.UNKNOWN) {
return;
}
- cgeoapplication app = (cgeoapplication) ((Activity) fromActivity).getApplication();
+ cgeoapplication app = (cgeoapplication) fromActivity.getApplication();
final boolean status = app.saveLogOffline(geocode, date.getTime(), logType, log);
- Resources res = ((Activity) fromActivity).getResources();
+ Resources res = fromActivity.getResources();
if (status) {
- fromActivity.showToast(res.getString(R.string.info_log_saved));
+ ActivityMixin.showToast(fromActivity, res.getString(R.string.info_log_saved));
app.saveVisitDate(geocode);
logOffline = true;
notifyChange();
} else {
- fromActivity.showToast(res.getString(R.string.err_log_post_failed));
+ ActivityMixin.showToast(fromActivity, res.getString(R.string.err_log_post_failed));
}
}
public List<LogType> getPossibleLogTypes() {
- boolean isOwner = owner != null && owner.equalsIgnoreCase(Settings.getUsername());
+ boolean isOwner = getOwnerUserId() != null && getOwnerUserId().equalsIgnoreCase(Settings.getUsername());
List<LogType> logTypes = new ArrayList<LogType>();
if (isEventCache()) {
logTypes.add(LogType.WILL_ATTEND);
@@ -506,8 +507,8 @@ public class cgCache implements ICache, IWaypoint {
}
@Override
- public String getOwner() {
- return owner;
+ public String getOwnerDisplayName() {
+ return ownerDisplayName;
}
@Override
@@ -548,8 +549,8 @@ public class cgCache implements ICache, IWaypoint {
}
@Override
- public String getOwnerReal() {
- return ownerReal;
+ public String getOwnerUserId() {
+ return ownerUserId;
}
@Override
@@ -988,12 +989,12 @@ public class cgCache implements ICache, IWaypoint {
this.name = name;
}
- public void setOwner(String owner) {
- this.owner = owner;
+ public void setOwnerDisplayName(String ownerDisplayName) {
+ this.ownerDisplayName = ownerDisplayName;
}
- public void setOwnerReal(String ownerReal) {
- this.ownerReal = ownerReal;
+ public void setOwnerUserId(String ownerUserId) {
+ this.ownerUserId = ownerUserId;
}
public void setHint(String hint) {
@@ -1403,11 +1404,11 @@ public class cgCache implements ICache, IWaypoint {
if (getDifficulty() == 0.0) {
Log.e("difficulty not parsed correctly");
}
- if (StringUtils.isBlank(getOwner())) {
- Log.e("owner not parsed correctly");
+ if (StringUtils.isBlank(getOwnerDisplayName())) {
+ Log.e("owner display name not parsed correctly");
}
- if (StringUtils.isBlank(getOwnerReal())) {
- Log.e("owner real not parsed correctly");
+ if (StringUtils.isBlank(getOwnerUserId())) {
+ Log.e("owner user id real not parsed correctly");
}
if (getHiddenDate() == null) {
Log.e("hidden not parsed correctly");
@@ -1549,4 +1550,45 @@ public class cgCache implements ICache, IWaypoint {
return listId >= StoredList.STANDARD_LIST_ID;
}
-}
+ /**
+ * guess an event start time from the description
+ *
+ * @return start time in minutes after midnight
+ */
+ public String guessEventTimeMinutes() {
+ if (!isEventCache()) {
+ return null;
+ }
+ // 12:34
+ final Pattern time = Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b");
+ final Matcher matcher = time.matcher(getDescription());
+ while (matcher.find()) {
+ try {
+ final int hours = Integer.valueOf(matcher.group(1));
+ final int minutes = Integer.valueOf(matcher.group(2));
+ if (hours >= 0 && hours < 24 && minutes >= 0 && minutes < 60) {
+ return String.valueOf(hours * 60 + minutes);
+ }
+ } catch (NumberFormatException e) {
+ // cannot happen, but static code analysis doesn't know
+ }
+ }
+ // 12 o'clock
+ final String hourLocalized = cgeoapplication.getInstance().getString(R.string.cache_time_full_hours);
+ if (StringUtils.isNotBlank(hourLocalized)) {
+ final Pattern fullHours = Pattern.compile("\\b(\\d{1,2})\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE);
+ final Matcher matcherHours = fullHours.matcher(getDescription());
+ if (matcherHours.find()) {
+ try {
+ final int hours = Integer.valueOf(matcherHours.group(1));
+ if (hours >= 0 && hours < 24) {
+ return String.valueOf(hours * 60);
+ }
+ } catch (NumberFormatException e) {
+ // cannot happen, but static code analysis doesn't know
+ }
+ }
+ }
+ return null;
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java
index 4831524..53ac334 100644
--- a/main/src/cgeo/geocaching/cgData.java
+++ b/main/src/cgeo/geocaching/cgData.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.database.Cursor;
+import android.database.DatabaseUtils;
import android.database.DatabaseUtils.InsertHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -1003,8 +1004,8 @@ public class cgData {
values.put("type", cache.getType().id);
values.put("name", cache.getName());
values.put("own", cache.isOwn() ? 1 : 0);
- values.put("owner", cache.getOwner());
- values.put("owner_real", cache.getOwnerReal());
+ values.put("owner", cache.getOwnerDisplayName());
+ values.put("owner_real", cache.getOwnerUserId());
if (cache.getHiddenDate() == null) {
values.put("hidden", 0);
} else {
@@ -1467,22 +1468,28 @@ public class cgData {
init();
- final Cursor cursor = database.query(
- dbTableCaches,
- CACHE_COLUMNS,
- cgData.whereGeocodeIn(geocodes),
- null,
- null,
- null,
- null,
- null);
+ final StringBuilder query = new StringBuilder("SELECT ");
+ for (int i = 0; i < CACHE_COLUMNS.length; i++) {
+ query.append(i > 0 ? ", " : "").append(dbTableCaches).append('.').append(CACHE_COLUMNS[i]).append(' ');
+ }
+ query.append(',').append(dbTableLogsOffline).append(".log");
+ query.append(" FROM ").append(dbTableCaches);
+ if (loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) {
+ query.append(" LEFT OUTER JOIN ").append(dbTableLogsOffline).append(" ON ( ").append(dbTableCaches).append(".geocode == ").append(dbTableLogsOffline).append(".geocode) ");
+ }
+
+ query.append(" WHERE ").append(dbTableCaches).append('.');
+ query.append(cgData.whereGeocodeIn(geocodes));
+
+ Cursor cursor = database.rawQuery(query.toString(), null);
try {
if (!cursor.moveToFirst()) {
return Collections.emptySet();
}
final Set<cgCache> caches = new HashSet<cgCache>();
+ int logIndex = -1;
do {
//Extracted Method = LOADDBMINIMAL
cgCache cache = cgData.createCacheFromDatabaseContent(cursor);
@@ -1532,7 +1539,10 @@ public class cgData {
}
if (loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) {
- cache.setLogOffline(hasLogOffline(cache.getGeocode()));
+ if (logIndex < 0) {
+ logIndex = cursor.getColumnIndex("log");
+ }
+ cache.setLogOffline(!cursor.isNull(logIndex));
}
cache.addStorageLocation(StorageLocation.DATABASE);
cacheCache.putCacheInCache(cache);
@@ -1545,6 +1555,7 @@ public class cgData {
}
}
+
/**
* Builds a where for a viewport with the size enhanced by 50%.
*
@@ -1624,8 +1635,8 @@ public class cgData {
cache.setType(CacheType.getById(cursor.getString(cacheColumnIndex[8])));
cache.setName(cursor.getString(cacheColumnIndex[9]));
cache.setOwn(cursor.getInt(cacheColumnIndex[10]) == 1);
- cache.setOwner(cursor.getString(cacheColumnIndex[11]));
- cache.setOwnerReal(cursor.getString(cacheColumnIndex[12]));
+ cache.setOwnerDisplayName(cursor.getString(cacheColumnIndex[11]));
+ cache.setOwnerUserId(cursor.getString(cacheColumnIndex[12]));
long dateValue = cursor.getLong(cacheColumnIndex[13]);
if (dateValue != 0) {
cache.setHidden(new Date(dateValue));
@@ -2116,13 +2127,13 @@ public class cgData {
if (cacheType == CacheType.ALL) {
sql = "select count(_id) from " + dbTableCaches + listSql;
} else {
- sql = "select count(_id) from " + dbTableCaches + " where type = \"" + cacheType.id + "\"" + listSqlW;
+ sql = "select count(_id) from " + dbTableCaches + " where type = " + DatabaseUtils.sqlEscapeString(cacheType.id) + listSqlW;
}
} else {
if (cacheType == CacheType.ALL) {
sql = "select count(_id) from " + dbTableCaches + " where detailed = 1" + listSqlW;
} else {
- sql = "select count(_id) from " + dbTableCaches + " where detailed = 1 and type = \"" + cacheType.id + "\"" + listSqlW;
+ sql = "select count(_id) from " + dbTableCaches + " where detailed = 1 and type = " + DatabaseUtils.sqlEscapeString(cacheType.id) + listSqlW;
}
}
SQLiteStatement compiledStmnt = database.compileStatement(sql);
@@ -2179,9 +2190,8 @@ public class cgData {
}
if (cacheType != CacheType.ALL) {
- specifySql.append(" and type = \"");
- specifySql.append(cacheType.id);
- specifySql.append('"');
+ specifySql.append(" and type = ");
+ specifySql.append(DatabaseUtils.sqlEscapeString(cacheType.id));
}
try {
@@ -2237,9 +2247,8 @@ public class cgData {
specifySql.append(" and detailed = 1");
}
if (cacheType != CacheType.ALL) {
- specifySql.append(" and type = \"");
- specifySql.append(cacheType.id);
- specifySql.append('"');
+ specifySql.append(" and type = ");
+ specifySql.append(DatabaseUtils.sqlEscapeString(cacheType.id));
}
try {
@@ -2312,9 +2321,8 @@ public class cgData {
// cacheType limitation
if (cacheType != CacheType.ALL) {
- where.append(" and type = \"");
- where.append(cacheType.id);
- where.append('"');
+ where.append(" and type = ");
+ where.append(DatabaseUtils.sqlEscapeString(cacheType.id));
}
// offline caches only
@@ -2458,7 +2466,7 @@ public class cgData {
// Drop caches from the database
final ArrayList<String> quotedGeocodes = new ArrayList<String>(geocodes.size());
for (final String geocode : geocodes) {
- quotedGeocodes.add('"' + geocode + '"');
+ quotedGeocodes.add(DatabaseUtils.sqlEscapeString(geocode));
}
final String geocodeList = StringUtils.join(quotedGeocodes.toArray(), ',');
final String baseWhereClause = "geocode in (" + geocodeList + ")";
@@ -2470,7 +2478,7 @@ public class cgData {
database.delete(dbTableLogs, baseWhereClause, null);
database.delete(dbTableLogCount, baseWhereClause, null);
database.delete(dbTableLogsOffline, baseWhereClause, null);
- database.delete(dbTableWaypoints, baseWhereClause + " and type <> \"own\"", null);
+ database.delete(dbTableWaypoints, baseWhereClause + " and type <> 'own'", null);
database.delete(dbTableTrackables, baseWhereClause, null);
database.setTransactionSuccessful();
} finally {
@@ -2486,41 +2494,29 @@ public class cgData {
public boolean saveLogOffline(String geocode, Date date, LogType type, String log) {
if (StringUtils.isBlank(geocode)) {
+ Log.e("cgData.saveLogOffline: cannot log a blank geocode");
return false;
}
if (LogType.UNKNOWN == type && StringUtils.isBlank(log)) {
+ Log.e("cgData.saveLogOffline: cannot log an unknown log type and no message");
return false;
}
init();
- boolean status = false;
- ContentValues values = new ContentValues();
+ final ContentValues values = new ContentValues();
values.put("geocode", geocode);
values.put("updated", System.currentTimeMillis());
values.put("type", type.id);
values.put("log", log);
values.put("date", date.getTime());
- try {
- if (hasLogOffline(geocode)) {
- final int rows = database.update(dbTableLogsOffline, values, "geocode = ?", new String[] { geocode });
-
- if (rows > 0) {
- status = true;
- }
- } else {
- final long id = database.insert(dbTableLogsOffline, null, values);
-
- if (id > 0) {
- status = true;
- }
- }
- } catch (Exception e) {
- Log.e("cgData.saveLogOffline: " + e.toString());
+ if (hasLogOffline(geocode)) {
+ final int rows = database.update(dbTableLogsOffline, values, "geocode = ?", new String[] { geocode });
+ return rows > 0;
}
-
- return status;
+ final long id = database.insert(dbTableLogsOffline, null, values);
+ return id != -1;
}
public LogEntry loadLogOffline(String geocode) {
@@ -2917,14 +2913,10 @@ public class cgData {
if (all.length() > 0) {
all.append(", ");
}
- all.append('"');
- all.append(geocode);
- all.append('"');
+ all.append(DatabaseUtils.sqlEscapeString(geocode));
}
- where.append("geocode in (");
- where.append(all);
- where.append(')');
+ where.append("geocode in (").append(all).append(')');
}
return where.toString();
diff --git a/main/src/cgeo/geocaching/cgWaypoint.java b/main/src/cgeo/geocaching/cgWaypoint.java
index c847b24..af6bab5 100644
--- a/main/src/cgeo/geocaching/cgWaypoint.java
+++ b/main/src/cgeo/geocaching/cgWaypoint.java
@@ -12,7 +12,7 @@ import java.util.List;
public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
- static final String PREFIX_OWN = "OWN";
+ public static final String PREFIX_OWN = "OWN";
private static final int ORDER_UNDEFINED = -2;
private int id = 0;
private String geocode = "geocode";
diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java
index 1c81a63..5bf728f 100644
--- a/main/src/cgeo/geocaching/cgeo.java
+++ b/main/src/cgeo/geocaching/cgeo.java
@@ -6,8 +6,7 @@ import cgeo.geocaching.connector.gc.Login;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
-import cgeo.geocaching.geopoint.IConversion;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.network.StatusUpdater.Status;
import cgeo.geocaching.ui.Formatter;
@@ -628,11 +627,7 @@ public class cgeo extends AbstractActivity {
if (geo.getAccuracy() >= 0) {
int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000;
- if (Settings.isUseMetricUnits()) {
- navAccuracy.setText("±" + Math.round(geo.getAccuracy()) + " m" + Formatter.SEPARATOR + speed + " km/h");
- } else {
- navAccuracy.setText("±" + Math.round(geo.getAccuracy() * IConversion.METERS_TO_FEET) + " ft" + Formatter.SEPARATOR + speed / IConversion.MILES_TO_KILOMETER + " mph");
- }
+ navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()) + Formatter.SEPARATOR + Units.getSpeed(speed));
} else {
navAccuracy.setText(null);
}
@@ -646,7 +641,7 @@ public class cgeo extends AbstractActivity {
}
} else {
if (geo.getAltitude() != 0.0) {
- final String humanAlt = HumanDistance.getHumanDistance((float) geo.getAltitude() / 1000);
+ final String humanAlt = Units.getDistanceFromKilometers((float) geo.getAltitude() / 1000);
navLocation.setText(geo.getCoords() + " | " + humanAlt);
} else {
navLocation.setText(geo.getCoords().toString());
diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java
index 3be48ca..340122a 100644
--- a/main/src/cgeo/geocaching/cgeocaches.java
+++ b/main/src/cgeo/geocaching/cgeocaches.java
@@ -12,7 +12,6 @@ import cgeo.geocaching.connector.gc.SearchHandler;
import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
-import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.export.ExportFactory;
import cgeo.geocaching.files.GPXImporter;
@@ -24,27 +23,17 @@ import cgeo.geocaching.network.Cookies;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.sorting.CacheComparator;
-import cgeo.geocaching.sorting.DateComparator;
-import cgeo.geocaching.sorting.DifficultyComparator;
+import cgeo.geocaching.sorting.ComparatorUserInterface;
import cgeo.geocaching.sorting.EventDateComparator;
-import cgeo.geocaching.sorting.FindsComparator;
-import cgeo.geocaching.sorting.GeocodeComparator;
-import cgeo.geocaching.sorting.InventoryComparator;
-import cgeo.geocaching.sorting.NameComparator;
-import cgeo.geocaching.sorting.PopularityComparator;
-import cgeo.geocaching.sorting.RatingComparator;
-import cgeo.geocaching.sorting.SizeComparator;
-import cgeo.geocaching.sorting.StateComparator;
-import cgeo.geocaching.sorting.StorageTimeComparator;
-import cgeo.geocaching.sorting.TerrainComparator;
import cgeo.geocaching.sorting.VisitComparator;
-import cgeo.geocaching.sorting.VoteComparator;
import cgeo.geocaching.ui.CacheListAdapter;
+import cgeo.geocaching.ui.LoggingUI;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.RunnableWithArgument;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -71,10 +60,8 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
public class cgeocaches extends AbstractListActivity {
@@ -93,17 +80,7 @@ public class cgeocaches extends AbstractListActivity {
private static final int MENU_CREATE_LIST = 7;
private static final int MENU_DROP_LIST = 8;
private static final int MENU_INVERT_SELECTION = 9;
- private static final int MENU_SORT_DISTANCE = 10;
- private static final int MENU_SORT_DIFFICULTY = 11;
- private static final int MENU_SORT_TERRAIN = 12;
- private static final int MENU_SORT_SIZE = 13;
- private static final int MENU_SORT_FAVORITES = 14;
- private static final int MENU_SORT_NAME = 15;
- private static final int MENU_SORT_GEOCODE = 16;
private static final int MENU_SWITCH_LIST = 17;
- private static final int MENU_SORT_RATING = 18;
- private static final int MENU_SORT_VOTE = 19;
- private static final int MENU_SORT_INVENTORY = 20;
private static final int MENU_IMPORT_WEB = 21;
private static final int MENU_EXPORT = 22;
private static final int MENU_REMOVE_FROM_HISTORY = 23;
@@ -113,18 +90,14 @@ public class cgeocaches extends AbstractListActivity {
private static final int SUBMENU_SHOW_MAP = 54;
private static final int SUBMENU_MANAGE_LISTS = 55;
private static final int SUBMENU_MANAGE_OFFLINE = 56;
- private static final int SUBMENU_SORT = 57;
+ private static final int MENU_SORT = 57;
private static final int SUBMENU_MANAGE_HISTORY = 60;
- private static final int MENU_SORT_DATE = 61;
- private static final int MENU_SORT_FINDS = 62;
- private static final int MENU_SORT_STATE = 63;
private static final int MENU_RENAME_LIST = 64;
private static final int MENU_DROP_CACHES_AND_LIST = 65;
private static final int MENU_DEFAULT_NAVIGATION = 66;
private static final int MENU_NAVIGATION = 69;
private static final int MENU_STORE_CACHE = 73;
private static final int MENU_FILTER = 74;
- private static final int MENU_SORT_STORAGE = 75;
private static final int MSG_DONE = -1;
private static final int MSG_RESTART_GEO_AND_DIR = -2;
@@ -133,7 +106,6 @@ public class cgeocaches extends AbstractListActivity {
private String action = null;
private CacheListType type = null;
private Geopoint coords = null;
- private CacheType cacheType = Settings.getCacheType();
private SearchResult search = null;
private final List<cgCache> cacheList = new ArrayList<cgCache>();
private CacheListAdapter adapter = null;
@@ -141,7 +113,6 @@ public class cgeocaches extends AbstractListActivity {
private View listFooter = null;
private TextView listFooterText = null;
private final Progress progress = new Progress();
- private Float northHeading = 0f;
private String title = "";
private int detailTotal = 0;
private int detailProgress = 0;
@@ -151,41 +122,31 @@ public class cgeocaches extends AbstractListActivity {
private int listId = StoredList.TEMPORARY_LIST_ID; // Only meaningful for the OFFLINE type
private final GeoDirHandler geoDirHandler = new GeoDirHandler() {
- @Override
+ @Override
public void updateGeoData(final IGeoData geo) {
if (adapter == null) {
return;
}
- try {
- if (geo.getCoords() != null) {
- adapter.setActualCoordinates(geo.getCoords());
- }
-
- if (!Settings.isUseCompass() || geo.getSpeed() > 5) { // use GPS when speed is higher than 18 km/h
- if (!Settings.isUseCompass()) {
- adapter.setActualHeading(geo.getBearing());
- }
- if (northHeading != null) {
- adapter.setActualHeading(northHeading);
- }
- }
- } catch (Exception e) {
- Log.w("Failed to UpdateLocation location.");
+ if (geo.getCoords() != null) {
+ adapter.setActualCoordinates(geo.getCoords());
+ }
+ if (!Settings.isUseCompass() || geo.getSpeed() > 5) { // use GPS when speed is higher than 18 km/h
+ adapter.setActualHeading(geo.getBearing());
}
}
- @Override
- public void updateDirection(final float direction) {
- if (!Settings.isLiveList()) {
- return;
- }
+ @Override
+ public void updateDirection(final float direction) {
+ if (adapter == null || !Settings.isLiveList()) {
+ return;
+ }
- northHeading = DirectionProvider.getDirectionNow(cgeocaches.this, direction);
- if (northHeading != null && adapter != null && (app.currentGeo().getSpeed() <= 5)) { // use compass when speed is lower than 18 km/h) {
- adapter.setActualHeading(northHeading);
- }
- }
+ if (app.currentGeo().getSpeed() <= 5) { // use compass when speed is lower than 18 km/h) {
+ final float northHeading = DirectionProvider.getDirectionNow(cgeocaches.this, direction);
+ adapter.setActualHeading(northHeading);
+ }
+ }
};
private ContextMenuInfo lastMenuInfo;
@@ -202,8 +163,6 @@ public class cgeocaches extends AbstractListActivity {
try {
if (search != null) {
setTitle(title + " [" + search.getCount() + ']');
- cacheList.clear();
- cacheList.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB));
} else {
setTitle(title);
}
@@ -248,11 +207,7 @@ public class cgeocaches extends AbstractListActivity {
return;
}
- final Geopoint coordsNow = app.currentGeo().getCoords();
- if (coordsNow != null) {
- adapter.setActualCoordinates(coordsNow);
- adapter.setActualHeading(northHeading);
- }
+ setAdapterCurrentCoordinates(false);
} catch (Exception e) {
showToast(res.getString(R.string.err_detail_cache_find_any));
Log.e("cgeocaches.loadCachesHandler: " + e.toString());
@@ -283,8 +238,7 @@ public class cgeocaches extends AbstractListActivity {
try {
if (search != null) {
setTitle(title + " [" + search.getCount() + "]");
- cacheList.clear();
- cacheList.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB));
+ replaceCacheListFromSearch();
if (adapter != null) {
adapter.reFilter();
}
@@ -307,11 +261,7 @@ public class cgeocaches extends AbstractListActivity {
return;
}
- final Geopoint coordsNow = app.currentGeo().getCoords();
- if (coordsNow != null) {
- adapter.setActualCoordinates(coordsNow);
- adapter.setActualHeading(northHeading);
- }
+ setAdapterCurrentCoordinates(false);
} catch (Exception e) {
showToast(res.getString(R.string.err_detail_cache_find_next));
Log.e("cgeocaches.loadNextPageHandler: " + e.toString());
@@ -325,6 +275,12 @@ public class cgeocaches extends AbstractListActivity {
}
}
};
+
+ private void replaceCacheListFromSearch() {
+ cacheList.clear();
+ cacheList.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB));
+ }
+
private Handler loadDetailsHandler = new Handler() {
@Override
@@ -364,11 +320,7 @@ public class cgeocaches extends AbstractListActivity {
}
}
- final Geopoint coordsNow = app.currentGeo().getCoords();
- if (coordsNow != null) {
- adapter.setActualCoordinates(coordsNow);
- adapter.setActualHeading(northHeading);
- }
+ setAdapterCurrentCoordinates(false);
showProgress(false);
progress.dismiss();
@@ -410,8 +362,7 @@ public class cgeocaches extends AbstractListActivity {
adapter.setSelectMode(false);
}
- cacheList.clear();
- cacheList.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB));
+ replaceCacheListFromSearch();
progress.dismiss();
}
@@ -428,8 +379,7 @@ public class cgeocaches extends AbstractListActivity {
refreshCurrentList();
- cacheList.clear();
- cacheList.addAll(search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB));
+ replaceCacheListFromSearch();
progress.dismiss();
}
@@ -487,7 +437,6 @@ public class cgeocaches extends AbstractListActivity {
else {
extras = new Bundle();
}
- cacheType = Settings.getCacheType();
if (isInvokedFromAttachment()) {
type = CacheListType.OFFLINE;
if (coords == null) {
@@ -613,8 +562,8 @@ public class cgeocaches extends AbstractListActivity {
title = res.getString(R.string.map_map);
setTitle(title);
showProgress(true);
- SearchResult result = (SearchResult) extras.get(EXTRAS_SEARCH);
- search = new SearchResult(result);
+ search = (SearchResult) extras.get(EXTRAS_SEARCH);
+ replaceCacheListFromSearch();
loadCachesHandler.sendMessage(Message.obtain());
break;
default:
@@ -668,27 +617,33 @@ public class cgeocaches extends AbstractListActivity {
if (adapter != null) {
adapter.setSelectMode(false);
- final Geopoint coordsNow = app.currentGeo().getCoords();
- if (coordsNow != null) {
- adapter.setActualCoordinates(coordsNow);
- adapter.setActualHeading(northHeading);
- adapter.forceSort();
- }
+ setAdapterCurrentCoordinates(true);
}
if (loadCachesHandler != null && search != null) {
+ replaceCacheListFromSearch();
loadCachesHandler.sendEmptyMessage(0);
}
// refresh standard list if it has changed (new caches downloaded)
if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) {
- SearchResult newSearch = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, cacheType, listId);
+ SearchResult newSearch = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId);
if (newSearch != null && newSearch.getTotal() != search.getTotal()) {
refreshCurrentList();
}
}
}
+ private void setAdapterCurrentCoordinates(final boolean forceSort) {
+ final Geopoint coordsNow = app.currentGeo().getCoords();
+ if (coordsNow != null) {
+ adapter.setActualCoordinates(coordsNow);
+ if (forceSort) {
+ adapter.forceSort();
+ }
+ }
+ }
+
@Override
public void onDestroy() {
if (adapter != null) {
@@ -710,34 +665,7 @@ public class cgeocaches extends AbstractListActivity {
menu.add(0, MENU_FILTER, 0, res.getString(R.string.caches_filter)).setIcon(R.drawable.ic_menu_filter);
if (type != CacheListType.HISTORY) {
- final SubMenu subMenuSort = menu.addSubMenu(0, SUBMENU_SORT, 0, res.getString(R.string.caches_sort)).setIcon(R.drawable.ic_menu_sort_alphabetically);
- subMenuSort.setHeaderTitle(res.getString(R.string.caches_sort_title));
-
- // sort the context menu labels alphabetically for easier reading
- final Map<String, Integer> comparators = new HashMap<String, Integer>();
- comparators.put(res.getString(R.string.caches_sort_distance), MENU_SORT_DISTANCE);
- comparators.put(res.getString(R.string.caches_sort_difficulty), MENU_SORT_DIFFICULTY);
- comparators.put(res.getString(R.string.caches_sort_terrain), MENU_SORT_TERRAIN);
- comparators.put(res.getString(R.string.caches_sort_size), MENU_SORT_SIZE);
- comparators.put(res.getString(R.string.caches_sort_favorites), MENU_SORT_FAVORITES);
- comparators.put(res.getString(R.string.caches_sort_name), MENU_SORT_NAME);
- comparators.put(res.getString(R.string.caches_sort_gccode), MENU_SORT_GEOCODE);
- comparators.put(res.getString(R.string.caches_sort_rating), MENU_SORT_RATING);
- comparators.put(res.getString(R.string.caches_sort_vote), MENU_SORT_VOTE);
- comparators.put(res.getString(R.string.caches_sort_inventory), MENU_SORT_INVENTORY);
- comparators.put(res.getString(R.string.caches_sort_date), MENU_SORT_DATE);
- comparators.put(res.getString(R.string.caches_sort_finds), MENU_SORT_FINDS);
- comparators.put(res.getString(R.string.caches_sort_state), MENU_SORT_STATE);
- comparators.put(res.getString(R.string.caches_sort_storage), MENU_SORT_STORAGE);
-
- final List<String> sortedLabels = new ArrayList<String>(comparators.keySet());
- Collections.sort(sortedLabels);
- for (String label : sortedLabels) {
- Integer id = comparators.get(label);
- subMenuSort.add(1, id, 0, label).setCheckable(true).setChecked(id == MENU_SORT_DISTANCE);
- }
-
- subMenuSort.setGroupCheckable(1, true, true);
+ menu.add(0, MENU_SORT, 0, res.getString(R.string.caches_sort)).setIcon(R.drawable.ic_menu_sort_alphabetically);
}
menu.add(0, MENU_SWITCH_SELECT_MODE, 0, res.getString(R.string.caches_select_mode)).setIcon(R.drawable.ic_menu_agenda);
@@ -806,7 +734,7 @@ public class cgeocaches extends AbstractListActivity {
setVisible(menu, MENU_SWITCH_SELECT_MODE, !isEmpty);
setVisible(menu, SUBMENU_MANAGE_HISTORY, !isEmpty);
setVisible(menu, SUBMENU_SHOW_MAP, !isEmpty);
- setVisible(menu, SUBMENU_SORT, !isEmpty);
+ setVisible(menu, MENU_SORT, !isEmpty);
setVisible(menu, MENU_REFRESH_STORED, !isEmpty && (isConcrete || type != CacheListType.OFFLINE));
setVisible(menu, MENU_DROP_CACHES, !isEmpty);
setVisible(menu, MENU_DROP_CACHES_AND_LIST, isConcrete && !isEmpty);
@@ -916,52 +844,10 @@ public class cgeocaches extends AbstractListActivity {
}
invalidateOptionsMenuCompatible();
return false;
- case MENU_SORT_DISTANCE:
- setComparator(item, null);
- return false;
- case MENU_SORT_DIFFICULTY:
- setComparator(item, new DifficultyComparator());
- return false;
- case MENU_SORT_TERRAIN:
- setComparator(item, new TerrainComparator());
- return false;
- case MENU_SORT_SIZE:
- setComparator(item, new SizeComparator());
- return false;
- case MENU_SORT_FAVORITES:
- setComparator(item, new PopularityComparator());
- return false;
- case MENU_SORT_NAME:
- setComparator(item, new NameComparator());
- return false;
- case MENU_SORT_GEOCODE:
- setComparator(item, new GeocodeComparator());
- return false;
- case MENU_SORT_STORAGE:
- setComparator(item, new StorageTimeComparator());
- return false;
case MENU_SWITCH_LIST:
selectList(null);
invalidateOptionsMenuCompatible();
return false;
- case MENU_SORT_RATING:
- setComparator(item, new RatingComparator());
- return false;
- case MENU_SORT_VOTE:
- setComparator(item, new VoteComparator());
- return false;
- case MENU_SORT_INVENTORY:
- setComparator(item, new InventoryComparator());
- return false;
- case MENU_SORT_DATE:
- setComparator(item, new DateComparator());
- return true;
- case MENU_SORT_FINDS:
- setComparator(item, new FindsComparator(app));
- return true;
- case MENU_SORT_STATE:
- setComparator(item, new StateComparator());
- return true;
case MENU_FILTER:
new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() {
@Override
@@ -978,6 +864,14 @@ public class cgeocaches extends AbstractListActivity {
}
});
return true;
+ case MENU_SORT:
+ new ComparatorUserInterface(this).selectComparator(adapter.getCacheComparator(), new RunnableWithArgument<CacheComparator>() {
+ @Override
+ public void run(CacheComparator selectedComparator) {
+ setComparator(selectedComparator);
+ }
+ });
+ return true;
case MENU_IMPORT_WEB:
importWeb();
return false;
@@ -997,12 +891,10 @@ public class cgeocaches extends AbstractListActivity {
return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search);
}
- private void setComparator(MenuItem item,
- CacheComparator comparator) {
+ private void setComparator(final CacheComparator comparator) {
if (adapter != null) {
adapter.setComparator(comparator);
}
- item.setChecked(true);
}
@Override
@@ -1032,7 +924,7 @@ public class cgeocaches extends AbstractListActivity {
if (cache.getCoords() != null) {
menu.add(0, MENU_DEFAULT_NAVIGATION, 0, NavigationAppFactory.getDefaultNavigationApplication().getName());
menu.add(1, MENU_NAVIGATION, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
- addVisitMenu(menu, cache);
+ LoggingUI.addMenuItems(menu, cache);
menu.add(0, MENU_CACHE_DETAILS, 0, res.getString(R.string.cache_menu_details));
}
if (cache.isOffline()) {
@@ -1094,9 +986,6 @@ public class cgeocaches extends AbstractListActivity {
case MENU_NAVIGATION:
NavigationAppFactory.showNavigationMenu(this, cache, null, null);
break;
- case MENU_LOG_VISIT:
- cache.logVisit(this);
- break;
case MENU_CACHE_DETAILS:
final Intent cachesIntent = new Intent(this, CacheDetailActivity.class);
cachesIntent.putExtra("geocode", cache.getGeocode().toUpperCase());
@@ -1107,6 +996,7 @@ public class cgeocaches extends AbstractListActivity {
cache.drop(new Handler() {
@Override
public void handleMessage(Message msg) {
+ adapter.notifyDataSetChanged();
refreshCurrentList();
}
});
@@ -1134,8 +1024,7 @@ public class cgeocaches extends AbstractListActivity {
// in Android:
// https://code.google.com/p/android/issues/detail?id=7139
lastMenuInfo = info;
- // create a search for a single cache (as if in details view)
- cache.logOffline(this, LogType.getById(id - MENU_LOG_VISIT_OFFLINE));
+ LoggingUI.onMenuItemSelected(item, this, cache);
}
return true;
@@ -1381,6 +1270,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run() {
search = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId);
+ replaceCacheListFromSearch();
loadCachesHandler.sendMessage(Message.obtain());
}
}
@@ -1389,6 +1279,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run() {
search = cgeoapplication.getInstance().getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
+ replaceCacheListFromSearch();
loadCachesHandler.sendMessage(Message.obtain());
}
}
@@ -1414,7 +1305,8 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void runSearch() {
- search = GCParser.searchByCoords(coords, cacheType, Settings.isShowCaptcha());
+ search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha());
+ replaceCacheListFromSearch();
}
}
@@ -1428,7 +1320,8 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void runSearch() {
- search = GCParser.searchByKeyword(keyword, cacheType, Settings.isShowCaptcha());
+ search = GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha());
+ replaceCacheListFromSearch();
}
}
@@ -1442,7 +1335,8 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void runSearch() {
- search = GCParser.searchByUsername(username, cacheType, Settings.isShowCaptcha());
+ search = GCParser.searchByUsername(username, Settings.getCacheType(), Settings.isShowCaptcha());
+ replaceCacheListFromSearch();
}
}
@@ -1456,7 +1350,8 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void runSearch() {
- search = GCParser.searchByOwner(username, cacheType, Settings.isShowCaptcha());
+ search = GCParser.searchByOwner(username, Settings.getCacheType(), Settings.isShowCaptcha());
+ replaceCacheListFromSearch();
}
}
diff --git a/main/src/cgeo/geocaching/cgeoimages.java b/main/src/cgeo/geocaching/cgeoimages.java
index b2f7ad6..6de6444 100644
--- a/main/src/cgeo/geocaching/cgeoimages.java
+++ b/main/src/cgeo/geocaching/cgeoimages.java
@@ -34,7 +34,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
public class cgeoimages extends AbstractActivity {
@@ -55,7 +55,11 @@ public class cgeoimages extends AbstractActivity {
private BitmapDrawable currentDrawable;
private cgImage currentImage;
- static private final Collection<Bitmap> bitmaps = Collections.synchronizedCollection(new ArrayList<Bitmap>());
+ // We could use a Set here, but we will insert no duplicates, so there is no need to check for uniqueness.
+ private final Collection<Bitmap> bitmaps = new LinkedList<Bitmap>();
+ private int message;
+ private boolean offline;
+ private ArrayList<cgImage> imageNames;
private void loadImages(final List<cgImage> images, final int progressMessage, final boolean offline) {
@@ -175,31 +179,34 @@ public class cgeoimages extends AbstractActivity {
setTitle(res.getString(img_type == SPOILER_IMAGES ? R.string.cache_spoiler_images_title : R.string.cache_log_images_title));
inflater = getLayoutInflater();
- if (imagesView == null) {
- imagesView = (LinearLayout) findViewById(R.id.spoiler_list);
- }
+ imagesView = (LinearLayout) findViewById(R.id.spoiler_list);
- final ArrayList<cgImage> images = extras.getParcelableArrayList("images");
- if (CollectionUtils.isEmpty(images)) {
+ imageNames = extras.getParcelableArrayList("images");
+ if (CollectionUtils.isEmpty(imageNames)) {
showToast(res.getString(R.string.warn_load_images));
finish();
return;
}
- final int message = img_type == SPOILER_IMAGES ? R.string.cache_spoiler_images_loading : R.string.cache_log_images_loading;
- final boolean offline = app.isOffline(geocode, null) && (img_type == SPOILER_IMAGES || Settings.isStoreLogImages());
+ message = img_type == SPOILER_IMAGES ? R.string.cache_spoiler_images_loading : R.string.cache_log_images_loading;
+ offline = app.isOffline(geocode, null) && (img_type == SPOILER_IMAGES || Settings.isStoreLogImages());
+ }
- loadImages(images, message, offline);
+ @Override
+ public void onStart() {
+ super.onStart();
+ loadImages(imageNames, message, offline);
}
@Override
- public void onDestroy() {
+ public void onStop() {
// Reclaim native memory faster than the finalizers would
- for (Bitmap b : bitmaps) {
+ imagesView.removeAllViews();
+ for (final Bitmap b : bitmaps) {
b.recycle();
}
bitmaps.clear();
- super.onDestroy();
+ super.onStop();
}
private void viewImageInStandardApp(final BitmapDrawable image) {
diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java
index 567ae74..53470b3 100644
--- a/main/src/cgeo/geocaching/cgeonavigate.java
+++ b/main/src/cgeo/geocaching/cgeonavigate.java
@@ -2,8 +2,7 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
-import cgeo.geocaching.geopoint.IConversion;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.ui.CompassView;
import cgeo.geocaching.utils.GeoDirHandler;
@@ -18,6 +17,7 @@ import android.os.PowerManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
+import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
@@ -29,6 +29,7 @@ public class cgeonavigate extends AbstractActivity {
private static final String EXTRAS_COORDS = "coords";
private static final String EXTRAS_NAME = "name";
private static final String EXTRAS_GEOCODE = "geocode";
+ private static final String EXTRAS_CACHE_INFO = "cacheinfo";
private static final List<IWaypoint> coordinates = new ArrayList<IWaypoint>();
private static final int MENU_MAP = 0;
private static final int MENU_SWITCH_COMPASS_GPS = 1;
@@ -37,6 +38,7 @@ public class cgeonavigate extends AbstractActivity {
private float cacheHeading = 0;
private String title = null;
private String name = null;
+ private String info = null;
private TextView navType = null;
private TextView navAccuracy = null;
private TextView navSatellites = null;
@@ -65,6 +67,7 @@ public class cgeonavigate extends AbstractActivity {
title = geocode;
name = extras.getString(EXTRAS_NAME);
dstCoords = (Geopoint) extras.getParcelable(EXTRAS_COORDS);
+ info = extras.getString(EXTRAS_CACHE_INFO);
if (StringUtils.isNotBlank(name)) {
if (StringUtils.isNotBlank(title)) {
@@ -86,6 +89,7 @@ public class cgeonavigate extends AbstractActivity {
// set header
setTitle();
setDestCoords();
+ setCacheInfo();
// get textviews once
compassView = (CompassView) findViewById(R.id.rose);
@@ -179,6 +183,7 @@ public class cgeonavigate extends AbstractActivity {
dstCoords = coordinate.getCoords();
setTitle();
setDestCoords();
+ setCacheInfo();
updateDistanceInfo(app.currentGeo());
Log.d("destination set: " + title + " (" + dstCoords + ")");
@@ -204,6 +209,16 @@ public class cgeonavigate extends AbstractActivity {
((TextView) findViewById(R.id.destination)).setText(dstCoords.toString());
}
+ private void setCacheInfo() {
+ final TextView cacheInfoView = (TextView) findViewById(R.id.cacheinfo);
+ if (info == null) {
+ cacheInfoView.setVisibility(View.GONE);
+ return;
+ }
+ cacheInfoView.setVisibility(View.VISIBLE);
+ cacheInfoView.setText(info);
+ }
+
private void updateDistanceInfo(final IGeoData geo) {
if (geo.getCoords() == null || dstCoords == null) {
return;
@@ -217,7 +232,7 @@ public class cgeonavigate extends AbstractActivity {
}
cacheHeading = geo.getCoords().bearingTo(dstCoords);
- distanceView.setText(HumanDistance.getHumanDistance(geo.getCoords().distanceTo(dstCoords)));
+ distanceView.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(dstCoords)));
headingView.setText(Math.round(cacheHeading) + "°");
}
@@ -233,29 +248,22 @@ public class cgeonavigate extends AbstractActivity {
}
if (geo.getCoords() != null) {
- String satellites;
- if (geo.getSatellitesFixed() > 0) {
- satellites = res.getString(R.string.loc_sat) + ": " + geo.getSatellitesFixed() + "/" + geo.getSatellitesVisible();
- } else if (geo.getSatellitesVisible() >= 0) {
- satellites = res.getString(R.string.loc_sat) + ": 0/" + geo.getSatellitesVisible();
- } else {
- satellites = "";
+ if (geo.getSatellitesVisible() >= 0) {
+ navSatellites.setText(res.getString(R.string.loc_sat) + ": " + geo.getSatellitesFixed() + "/" + geo.getSatellitesVisible());
+ }
+ else {
+ navSatellites.setText("");
}
- navSatellites.setText(satellites);
navType.setText(res.getString(geo.getLocationProvider().resourceId));
if (geo.getAccuracy() >= 0) {
- if (Settings.isUseMetricUnits()) {
- navAccuracy.setText("±" + Math.round(geo.getAccuracy()) + " m");
- } else {
- navAccuracy.setText("±" + Math.round(geo.getAccuracy() * IConversion.METERS_TO_FEET) + " ft");
- }
+ navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()));
} else {
navAccuracy.setText(null);
}
if (geo.getAltitude() != 0.0f) {
- final String humanAlt = HumanDistance.getHumanDistance((float) geo.getAltitude() / 1000);
+ final String humanAlt = Units.getDistanceFromMeters((float) geo.getAltitude());
navLocation.setText(geo.getCoords() + " | " + humanAlt);
} else {
navLocation.setText(geo.getCoords().toString());
@@ -290,7 +298,8 @@ public class cgeonavigate extends AbstractActivity {
}
}
- public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType) {
+ public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType,
+ final String info) {
coordinates.clear();
if (coordinatesWithType != null) { // avoid possible NPE
coordinates.addAll(coordinatesWithType);
@@ -302,6 +311,12 @@ public class cgeonavigate extends AbstractActivity {
if (null != displayedName) {
navigateIntent.putExtra(EXTRAS_NAME, displayedName);
}
+ navigateIntent.putExtra(EXTRAS_CACHE_INFO, info);
context.startActivity(navigateIntent);
}
+
+ public static void startActivity(final Context context, final String geocode, final String displayedName, final Geopoint coords, final Collection<IWaypoint> coordinatesWithType) {
+ cgeonavigate.startActivity(context, geocode, displayedName, coords, coordinatesWithType, null);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/cgeotrackable.java b/main/src/cgeo/geocaching/cgeotrackable.java
index c635e41..acd351d 100644
--- a/main/src/cgeo/geocaching/cgeotrackable.java
+++ b/main/src/cgeo/geocaching/cgeotrackable.java
@@ -3,7 +3,7 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.connector.gc.GCParser;
import cgeo.geocaching.enumerations.LogType;
-import cgeo.geocaching.geopoint.HumanDistance;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.network.HtmlImage;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.Formatter;
@@ -166,7 +166,7 @@ public class cgeotrackable extends AbstractActivity {
// trackable distance
if (trackable.getDistance() >= 0) {
- details.add(R.string.trackable_distance, HumanDistance.getHumanDistance(trackable.getDistance()));
+ details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()));
}
// trackable goal
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java
index f933071..a425ee5 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11.java
@@ -1,10 +1,12 @@
package cgeo.geocaching.compatibility;
+import android.annotation.TargetApi;
import android.app.Activity;
/**
* Android level 11 support
*/
+@TargetApi(11)
public class AndroidLevel11 implements AndroidLevel11Interface {
@Override
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java
index 859fdf1..ea5a795 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java
@@ -2,10 +2,12 @@ package cgeo.geocaching.compatibility;
import cgeo.geocaching.utils.Log;
+import android.annotation.TargetApi;
import android.app.Activity;
import android.app.backup.BackupManager;
import android.view.Display;
+@TargetApi(8)
public class AndroidLevel8 implements AndroidLevel8Interface {
@Override
diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java
index d869c58..0821655 100644
--- a/main/src/cgeo/geocaching/compatibility/Compatibility.java
+++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.compatibility;
import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.reflect.MethodUtils;
@@ -40,23 +41,22 @@ public final class Compatibility {
/**
* Add 90, 180 or 270 degrees to the given rotation.
- * <br/>
- * Note: the result is not normalized and may fall outside your desired range.
*
* @param directionNowPre the direction in degrees before adjustment
* @param activity the activity whose rotation is used to adjust the direction
- * @return the adjusted direction
+ * @return the adjusted direction, in the [0, 360[ range
*/
public static float getDirectionNow(final float directionNowPre, final Activity activity) {
+ float offset = 0;
if (isLevel8) {
try {
final int rotation = level8.getRotation(activity);
if (rotation == Surface.ROTATION_90) {
- return directionNowPre + 90;
+ offset = 90;
} else if (rotation == Surface.ROTATION_180) {
- return directionNowPre + 180;
+ offset = 180;
} else if (rotation == Surface.ROTATION_270) {
- return directionNowPre + 270;
+ offset = 270;
}
} catch (final Exception e) {
// This should never happen: IllegalArgumentException, IllegalAccessException or InvocationTargetException
@@ -66,10 +66,10 @@ public final class Compatibility {
final Display display = activity.getWindowManager().getDefaultDisplay();
final int rotation = display.getOrientation();
if (rotation == Configuration.ORIENTATION_LANDSCAPE) {
- return directionNowPre + 90;
+ offset = 90;
}
}
- return directionNowPre;
+ return AngleUtils.normalize(directionNowPre + offset);
}
public static void dataChanged(final String name) {
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index 72c5259..ff1b442 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -37,11 +37,12 @@ public final class GCConstants {
public final static Pattern PATTERN_NAME = Pattern.compile("<span id=\"ctl00_ContentBody_CacheName\">(.*?)</span>");
public final static Pattern PATTERN_DIFFICULTY = Pattern.compile("<span id=\"ctl00_ContentBody_uxLegendScale\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\"");
public final static Pattern PATTERN_TERRAIN = Pattern.compile("<span id=\"ctl00_ContentBody_Localize[\\d]+\"[^>]*>[^<]*<img src=\"[^\"]*/images/stars/stars([0-9_]+)\\.gif\"");
- public final static Pattern PATTERN_OWNERREAL = Pattern.compile("<a id=\"ctl00_ContentBody_uxFindLinksHiddenByThisUser\" href=\"[^\"]*/seek/nearest\\.aspx\\?u=(.*?)\"");
+ public final static Pattern PATTERN_OWNER_USERID = Pattern.compile("<a id=\"ctl00_ContentBody_uxFindLinksHiddenByThisUser\" href=\"[^\"]*/seek/nearest\\.aspx\\?u=(.*?)\"");
public final static Pattern PATTERN_FOUND = Pattern.compile("<a id=\"ctl00_ContentBody_hlFoundItLog\"[^<]*<img src=\".*/images/stockholm/16x16/check\\.gif\"[^>]*>[^<]*</a>[^<]*</p>");
public final static Pattern PATTERN_FOUND_ALTERNATIVE = Pattern.compile("<div class=\"StatusInformationWidget FavoriteWidget\"");
- public final static Pattern PATTERN_OWNER = Pattern.compile("<div id=\"ctl00_ContentBody_mcd1\">[^<]+<a href=\"[^\"]+\">([^<]+)</a></div>");
- public final static Pattern PATTERN_TYPE = Pattern.compile("<img src=\"[^\"]*/WptTypes/\\d+\\.gif\" alt=\"([^\"]+?)\" title=\"[^\"]+\" />");
+ public final static Pattern PATTERN_FOUND_DATE = Pattern.compile("You logged this as Found on ([^.]+?)\\.[^<]*</a>[^<]*</p>");
+ public final static Pattern PATTERN_OWNER_DISPLAYNAME = Pattern.compile("<div id=\"ctl00_ContentBody_mcd1\">[^<]+<a href=\"[^\"]+\">([^<]+)</a></div>");
+ public final static Pattern PATTERN_TYPE = Pattern.compile("<img src=\"[^\"]*/WptTypes/\\d+\\.gif\" alt=\"([^\"]+?)\"[^>]*>");
public final static Pattern PATTERN_HIDDEN = Pattern.compile("<div id=\"ctl00_ContentBody_mcd2\">\\W*Hidden[\\s:]*([^<]+?)</div>");
public final static Pattern PATTERN_HIDDENEVENT = Pattern.compile("Event\\s*Date\\s*:\\s*([^<]+)<div id=\"calLinks\">", Pattern.DOTALL);
public final static Pattern PATTERN_FAVORITE = Pattern.compile("<div id=\"pnlFavoriteCache\">"); // without 'class="hideMe"' inside the tag !
@@ -54,8 +55,7 @@ public final class GCConstants {
public final static Pattern PATTERN_ATTRIBUTES = Pattern.compile("<h3 class=\"WidgetHeader\">[^<]*<img[^>]+>\\W*Attributes[^<]*</h3>[^<]*<div class=\"WidgetBody\">((?:[^<]*<img src=\"[^\"]+\" alt=\"[^\"]+\"[^>]*>)+?)[^<]*<p");
/** Two groups ! */
public final static Pattern PATTERN_ATTRIBUTESINSIDE = Pattern.compile("[^<]*<img src=\"([^\"]+)\" alt=\"([^\"]+?)\"");
- public final static Pattern PATTERN_SPOILERS = Pattern.compile("<p class=\"NoPrint\">\\s+((?:<a href=\"http://img\\.geocaching\\.com/cache/[^.]+\\.jpg\"[^>]+><img class=\"StatusIcon\"[^>]+><span>[^<]+</span></a><br />(?:[^<]+<br /><br />)?)+)\\s+</p>");
- public final static Pattern PATTERN_SPOILERSINSIDE = Pattern.compile("<a href=\"(http://img\\.geocaching\\.com/cache/[^.]+\\.jpg)\"[^>]+><img class=\"StatusIcon\"[^>]+><span>([^<]+)</span></a><br />(?:([^<]+)<br /><br />)?");
+ public final static Pattern PATTERN_SPOILER_IMAGE = Pattern.compile("<a href=\"(http://img\\.geocaching\\.com/cache/[^.]+\\.jpg)\"[^>]+><img[^>]+><span>([^<]+)</span></a>(?:<br />([^<]+)<br /><br />)?");
public final static Pattern PATTERN_INVENTORY = Pattern.compile("<span id=\"ctl00_ContentBody_uxTravelBugList_uxInventoryLabel\">\\W*Inventory[^<]*</span>[^<]*</h3>[^<]*<div class=\"WidgetBody\">([^<]*<ul>(([^<]*<li>[^<]*<a href=\"[^\"]+\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>[^<]+<\\/span>[^<]*<\\/a>[^<]*<\\/li>)+)[^<]*<\\/ul>)?");
public final static Pattern PATTERN_INVENTORYINSIDE = Pattern.compile("[^<]*<li>[^<]*<a href=\"[a-z0-9\\-\\_\\.\\?\\/\\:\\@]*\\/track\\/details\\.aspx\\?guid=([0-9a-z\\-]+)[^\"]*\"[^>]*>[^<]*<img src=\"[^\"]+\"[^>]*>[^<]*<span>([^<]+)<\\/span>[^<]*<\\/a>[^<]*<\\/li>");
public final static Pattern PATTERN_WATCHLIST = Pattern.compile("icon_stop_watchlist.gif");
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index a8509b8..c71b859 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -10,7 +10,7 @@ import cgeo.geocaching.enumerations.LiveMapStrategy.Strategy;
import cgeo.geocaching.enumerations.LiveMapStrategy.StrategyFlag;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.IConversion;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.ui.Formatter;
@@ -88,7 +88,7 @@ public class GCMap {
JSONObject typeObj = dataObject.getJSONObject("type");
cache.setType(CacheType.getByPattern(typeObj.getString("text"))); // Traditional Cache
JSONObject ownerObj = dataObject.getJSONObject("owner");
- cache.setOwner(ownerObj.getString("text"));
+ cache.setOwnerDisplayName(ownerObj.getString("text"));
result.addCache(cache);
@@ -243,12 +243,7 @@ public class GCMap {
SearchResult result = searchByViewport(viewport, tokens, strategy);
if (Settings.isDebug()) {
- String text = Formatter.SEPARATOR + strategy.getL10n() + Formatter.SEPARATOR;
- if (Settings.isUseMetricUnits()) {
- text += speed + " km/h";
- } else {
- text += speed / IConversion.MILES_TO_KILOMETER + " mph";
- }
+ StringBuilder text = new StringBuilder(Formatter.SEPARATOR).append(strategy.getL10n()).append(Formatter.SEPARATOR).append(Units.getSpeed(speed));
result.setUrl(result.getUrl() + text);
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 053c248..2ca505d 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -44,6 +44,7 @@ import android.net.Uri;
import android.text.Html;
import android.text.Spannable;
import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import java.net.URLDecoder;
@@ -225,6 +226,9 @@ public abstract class GCParser {
if (cache.isDisabled() || cache.isArchived()) { // strike
cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
+ if (cache.isArchived()) {
+ cache.getNameSp().setSpan(new ForegroundColorSpan(cgeoapplication.getInstance().getResources().getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
}
searchResult.addCache(cache);
@@ -378,9 +382,9 @@ public abstract class GCParser {
cache.setName(cacheName);
// owner real name
- cache.setOwnerReal(URLDecoder.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNERREAL, true, cache.getOwnerReal())));
+ cache.setOwnerUserId(URLDecoder.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
- cache.setOwn(StringUtils.equalsIgnoreCase(cache.getOwnerReal(), Settings.getUsername()));
+ cache.setOwn(StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getUsername()));
String tableInside = page;
@@ -406,7 +410,7 @@ public abstract class GCParser {
}
// owner
- cache.setOwner(StringEscapeUtils.unescapeHtml4(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_OWNER, true, cache.getOwner())).toString());
+ cache.setOwnerDisplayName(StringEscapeUtils.unescapeHtml4(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_OWNER_DISPLAYNAME, true, cache.getOwnerDisplayName())));
// hidden
try {
@@ -436,6 +440,17 @@ public abstract class GCParser {
// cache found
cache.setFound(BaseUtils.matches(page, GCConstants.PATTERN_FOUND) || BaseUtils.matches(page, GCConstants.PATTERN_FOUND_ALTERNATIVE));
+ // cache found date
+ try {
+ final String foundDateString = BaseUtils.getMatch(page, GCConstants.PATTERN_FOUND_DATE, true, null);
+ if (StringUtils.isNotBlank(foundDateString)) {
+ cache.setVisitedDate(Login.parseGcCustomDate(foundDateString).getTime());
+ }
+ } catch (ParseException e) {
+ // failed to parse cache found date
+ Log.w("GCParser.parseCache: Failed to parse cache found date");
+ }
+
// cache type
cache.setType(CacheType.getByPattern(BaseUtils.getMatch(page, GCConstants.PATTERN_TYPE, true, cache.getType().id)));
@@ -508,35 +523,32 @@ public abstract class GCParser {
// cache spoilers
try {
- final String spoilers = BaseUtils.getMatch(page, GCConstants.PATTERN_SPOILERS, false, null);
- if (null != spoilers) {
- if (CancellableHandler.isCancelled(handler)) {
- return null;
- }
- CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers);
+ if (CancellableHandler.isCancelled(handler)) {
+ return null;
+ }
+ CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers);
- final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILERSINSIDE.matcher(spoilers);
+ final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILER_IMAGE.matcher(page);
- while (matcherSpoilersInside.find()) {
- // the original spoiler URL (include .../display/... contains a low-resolution image
- // if we shorten the URL we get the original-resolution image
- String url = matcherSpoilersInside.group(1).replace("/display", "");
+ while (matcherSpoilersInside.find()) {
+ // the original spoiler URL (include .../display/... contains a low-resolution image
+ // if we shorten the URL we get the original-resolution image
+ String url = matcherSpoilersInside.group(1).replace("/display", "");
- String title = null;
- if (matcherSpoilersInside.group(2) != null) {
- title = matcherSpoilersInside.group(2);
- }
- String description = null;
- if (matcherSpoilersInside.group(3) != null) {
- description = matcherSpoilersInside.group(3);
- }
- final cgImage spoiler = new cgImage(url, title, description);
+ String title = null;
+ if (matcherSpoilersInside.group(2) != null) {
+ title = matcherSpoilersInside.group(2);
+ }
+ String description = null;
+ if (matcherSpoilersInside.group(3) != null) {
+ description = matcherSpoilersInside.group(3);
+ }
+ final cgImage spoiler = new cgImage(url, title, description);
- if (cache.getSpoilers() == null) {
- cache.setSpoilers(new ArrayList<cgImage>());
- }
- cache.getSpoilers().add(spoiler);
+ if (cache.getSpoilers() == null) {
+ cache.setSpoilers(new ArrayList<cgImage>());
}
+ cache.getSpoilers().add(spoiler);
}
} catch (Exception e) {
// failed to parse cache spoilers
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index 39f81f0..8c79aca 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -144,7 +144,7 @@ public abstract class Login {
return StatusCode.NO_ERROR;
}
- public static void setActualCachesFound(final int found) {
+ static void setActualCachesFound(final int found) {
actualCachesFound = found;
}
@@ -152,7 +152,7 @@ public abstract class Login {
return actualStatus;
}
- public static void setActualStatus(final String status) {
+ private static void setActualStatus(final String status) {
actualStatus = status;
}
@@ -160,7 +160,7 @@ public abstract class Login {
return actualLoginStatus;
}
- public static void setActualLoginStatus(boolean loginStatus) {
+ private static void setActualLoginStatus(boolean loginStatus) {
actualLoginStatus = loginStatus;
}
@@ -168,7 +168,7 @@ public abstract class Login {
return actualUserName;
}
- public static void setActualUserName(String userName) {
+ private static void setActualUserName(String userName) {
actualUserName = userName;
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 0212a64..8bdb9a4 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -133,7 +133,7 @@ final public class OkapiClient {
// not used: url
final JSONObject owner = response.getJSONObject(CACHE_OWNER);
- cache.setOwner(parseUser(owner));
+ cache.setOwnerDisplayName(parseUser(owner));
cache.getLogCounts().put(LogType.FOUND_IT, response.getInt(CACHE_FOUNDS));
cache.getLogCounts().put(LogType.DIDNT_FIND_IT, response.getInt(CACHE_NOTFOUNDS));
diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java
index be66de1..730c989 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -31,7 +31,14 @@ public enum CacheType {
/** No real cache type -> filter */
ALL("all", "display all caches", "9a79e6ce-3344-409c-bbe9-496530baf758", R.string.all_types, R.drawable.type_unknown);
+ /**
+ * id field is used when for storing caches in the database.
+ */
public final String id;
+ /**
+ * human readable name of the cache type<br>
+ * used in web parsing as well as for gpx import/export.
+ */
public final String pattern;
public final String guid;
private final int stringId;
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index ad39acd..e87555f 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -169,7 +169,7 @@ class FieldnoteExport extends AbstractExport {
Writer fw = null;
try {
os = new FileOutputStream(exportFile);
- fw = new OutputStreamWriter(os, "ISO-8859-1"); // gc.com doesn't support neither UTF-8 nor html entities
+ fw = new OutputStreamWriter(os, "UTF-16");
fw.write(fieldNoteBuffer.toString());
} catch (IOException e) {
Log.e("FieldnoteExport.ExportTask export", e);
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index 156d9d4..9bc3963 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -2,6 +2,7 @@ package cgeo.geocaching.export;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeoapplication;
@@ -16,9 +17,15 @@ import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringEscapeUtils;
import android.app.Activity;
+import android.app.AlertDialog;
import android.app.ProgressDialog;
+import android.content.Intent;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
import java.io.BufferedWriter;
import java.io.File;
@@ -26,6 +33,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -39,7 +47,48 @@ class GpxExport extends AbstractExport {
@Override
public void export(final List<cgCache> caches, final Activity activity) {
- new ExportTask(caches, activity).execute((Void) null);
+ if (null == activity) {
+ // No activity given, so no user interaction possible.
+ // Start export with default parameters.
+ new ExportTask(caches, activity).execute((Void) null);
+
+ } else {
+ // Show configuration dialog
+ new ExportOptionsDialog(caches, activity).show();
+ }
+ }
+
+ /**
+ * A dialog to allow the user to set options for the export.
+ *
+ * Currently available option is: opening of share menu after successful export
+ */
+ private class ExportOptionsDialog extends AlertDialog {
+ public ExportOptionsDialog(final List<cgCache> caches, final Activity activity) {
+ super(activity);
+
+ View layout = activity.getLayoutInflater().inflate(R.layout.gpx_export_dialog, null);
+ setView(layout);
+
+ final CheckBox shareOption = (CheckBox) layout.findViewById(R.id.share);
+
+ shareOption.setChecked(Settings.getShareAfterExport());
+
+ shareOption.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Settings.setShareAfterExport(shareOption.isChecked());
+ }
+ });
+
+ ((Button) layout.findViewById(R.id.export)).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ new ExportTask(caches, activity).execute((Void) null);
+ }
+ });
+ }
}
private class ExportTask extends AsyncTask<Void, Integer, Boolean> {
@@ -88,7 +137,6 @@ class GpxExport extends AbstractExport {
gpx.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
gpx.write("<gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd\">");
-
for (int i = 0; i < caches.size(); i++) {
// reload the cache. otherwise logs, attributes and other detailed information is not available
final cgCache cache = cgeoapplication.getInstance().loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY);
@@ -113,6 +161,14 @@ class GpxExport extends AbstractExport {
gpx.write(StringEscapeUtils.escapeXml(cache.getName()));
gpx.write("</desc>");
+ gpx.write("<url>");
+ gpx.write(cache.getUrl());
+ gpx.write("</url>");
+
+ gpx.write("<urlname>");
+ gpx.write(StringEscapeUtils.escapeXml(cache.getName()));
+ gpx.write("</urlname>");
+
gpx.write("<sym>");
gpx.write(cache.isFound() ? "Geocache Found" : "Geocache");
gpx.write("</sym>");
@@ -122,7 +178,9 @@ class GpxExport extends AbstractExport {
gpx.write("</type>");
gpx.write("<groundspeak:cache ");
- gpx.write("available=\"");
+ gpx.write("id=\"");
+ gpx.write(cache.getCacheId());
+ gpx.write("\" available=\"");
gpx.write(!cache.isDisabled() ? "True" : "False");
gpx.write("\" archived=\"");
gpx.write(cache.isArchived() ? "True" : "False");
@@ -134,11 +192,11 @@ class GpxExport extends AbstractExport {
gpx.write("</groundspeak:name>");
gpx.write("<groundspeak:placed_by>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getOwner()));
+ gpx.write(StringEscapeUtils.escapeXml(cache.getOwnerDisplayName()));
gpx.write("</groundspeak:placed_by>");
gpx.write("<groundspeak:owner>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getOwnerReal()));
+ gpx.write(StringEscapeUtils.escapeXml(cache.getOwnerUserId()));
gpx.write("</groundspeak:owner>");
gpx.write("<groundspeak:type>");
@@ -225,35 +283,75 @@ class GpxExport extends AbstractExport {
}
private void writeWaypoints(final cgCache cache) throws IOException {
+ List<cgWaypoint> waypoints = cache.getWaypoints();
+ List<cgWaypoint> ownWaypoints = new ArrayList<cgWaypoint>(waypoints.size());
+ List<cgWaypoint> originWaypoints = new ArrayList<cgWaypoint>(waypoints.size());
for (cgWaypoint wp : cache.getWaypoints()) {
- gpx.write("<wpt lat=\"");
- final Geopoint coords = wp.getCoords();
- gpx.write(coords != null ? Double.toString(coords.getLatitude()) : ""); // TODO: check whether is the best way to handle unknown waypoint coordinates
- gpx.write("\" lon=\"");
- gpx.write(coords != null ? Double.toString(coords.getLongitude()) : "");
- gpx.write("\">");
-
- gpx.write("<name>");
- gpx.write(StringEscapeUtils.escapeXml(wp.getPrefix()));
- gpx.write(StringEscapeUtils.escapeXml(cache.getGeocode().substring(2)));
- gpx.write("</name>");
-
- gpx.write("<cmt />");
-
- gpx.write("<desc>");
- gpx.write(StringEscapeUtils.escapeXml(wp.getNote()));
- gpx.write("</desc>");
-
- gpx.write("<sym>");
- gpx.write(StringEscapeUtils.escapeXml(wp.getWaypointType().toString())); //TODO: Correct identifier string
- gpx.write("</sym>");
-
- gpx.write("<type>Waypoint|");
- gpx.write(StringEscapeUtils.escapeXml(wp.getWaypointType().toString())); //TODO: Correct identifier string
- gpx.write("</type>");
-
- gpx.write("</wpt>");
+ if (wp.isUserDefined()) {
+ ownWaypoints.add(wp);
+ } else {
+ originWaypoints.add(wp);
+ }
+ }
+ int maxPrefix = 0;
+ for (cgWaypoint wp : originWaypoints) {
+ String prefix = wp.getPrefix();
+ try {
+ maxPrefix = Math.max(Integer.parseInt(prefix), maxPrefix);
+ } catch (NumberFormatException ex) {
+ Log.e("Unexpected origin waypoint prefix='" + prefix + "'", ex);
+ }
+ writeCacheWaypoint(wp, prefix);
}
+ for (cgWaypoint wp : ownWaypoints) {
+ maxPrefix++;
+ String prefix = String.valueOf(maxPrefix);
+ if (prefix.length() == 1) {
+ prefix = "0" + prefix;
+ }
+ writeCacheWaypoint(wp, prefix);
+ }
+ }
+
+ /**
+ * Writes one waypoint entry for cache waypoint.
+ *
+ * @param cache
+ * The
+ * @param wp
+ * @param prefix
+ * @throws IOException
+ */
+ private void writeCacheWaypoint(final cgWaypoint wp, final String prefix) throws IOException {
+ gpx.write("<wpt lat=\"");
+ final Geopoint coords = wp.getCoords();
+ gpx.write(coords != null ? Double.toString(coords.getLatitude()) : ""); // TODO: check whether is the best way to handle unknown waypoint coordinates
+ gpx.write("\" lon=\"");
+ gpx.write(coords != null ? Double.toString(coords.getLongitude()) : "");
+ gpx.write("\">");
+
+ gpx.write("<name>");
+ gpx.write(StringEscapeUtils.escapeXml(prefix));
+ gpx.write(StringEscapeUtils.escapeXml(wp.getGeocode().substring(2)));
+ gpx.write("</name>");
+
+ gpx.write("<cmt>");
+ gpx.write(StringEscapeUtils.escapeXml(wp.getNote()));
+ gpx.write("</cmt>");
+
+ gpx.write("<desc>");
+ gpx.write(StringEscapeUtils.escapeXml(wp.getName()));
+ gpx.write("</desc>");
+
+ gpx.write("<sym>");
+ gpx.write(StringEscapeUtils.escapeXml(wp.getWaypointType().toString())); //TODO: Correct identifier string
+ gpx.write("</sym>");
+
+ gpx.write("<type>Waypoint|");
+ gpx.write(StringEscapeUtils.escapeXml(wp.getWaypointType().toString())); //TODO: Correct identifier string
+ gpx.write("</type>");
+
+ gpx.write("</wpt>");
}
private void writeLogs(final cgCache cache) throws IOException {
@@ -322,6 +420,13 @@ class GpxExport extends AbstractExport {
progress.dismiss();
if (result) {
ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
+ if (Settings.getShareAfterExport()) {
+ Intent shareIntent = new Intent();
+ shareIntent.setAction(Intent.ACTION_SEND);
+ shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(exportFile));
+ shareIntent.setType("application/xml");
+ activity.startActivity(Intent.createChooser(shareIntent, getString(R.string.export_gpx_to)));
+ }
} else {
ActivityMixin.showToast(activity, getString(R.string.export_failed));
}
diff --git a/main/src/cgeo/geocaching/files/FileList.java b/main/src/cgeo/geocaching/files/FileList.java
index 431fe3b..08c1940 100644
--- a/main/src/cgeo/geocaching/files/FileList.java
+++ b/main/src/cgeo/geocaching/files/FileList.java
@@ -19,15 +19,17 @@ import android.widget.ArrayAdapter;
import java.io.File;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractListActivity {
private static final int MSG_SEARCH_WHOLE_SD_CARD = 1;
- private List<File> files = new ArrayList<File>();
+ private final List<File> files = new ArrayList<File>();
private T adapter = null;
private ProgressDialog waitDialog = null;
- private loadFiles searchingThread = null;
+ private SearchFilesThread searchingThread = null;
private boolean endSearching = false;
private int listId = StoredList.STANDARD_LIST_ID;
final private Handler changeWaitDialogHandler = new Handler() {
@@ -114,7 +116,7 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
);
endSearching = false;
- searchingThread = new loadFiles();
+ searchingThread = new SearchFilesThread();
searchingThread.start();
}
@@ -145,14 +147,14 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
*/
protected abstract void setTitle();
- private class loadFiles extends Thread {
+ private class SearchFilesThread extends Thread {
public void notifyEnd() {
endSearching = true;
}
@Override
public void run() {
- List<File> list = new ArrayList<File>();
+ final List<File> list = new ArrayList<File>();
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
@@ -181,7 +183,13 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
changeWaitDialogHandler.sendMessage(Message.obtain(changeWaitDialogHandler, 0, "loaded directories"));
files.addAll(list);
- list.clear();
+ Collections.sort(files, new Comparator<File>() {
+
+ @Override
+ public int compare(File lhs, File rhs) {
+ return lhs.getName().compareToIgnoreCase(rhs.getName());
+ }
+ });
loadFilesHandler.sendMessage(Message.obtain(loadFilesHandler));
}
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index e083f58..454c494 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -51,6 +51,7 @@ public abstract class GPXParser extends FileParser {
*/
private static final Pattern patternGeocode = Pattern.compile("([A-Z][0-9A-Z]+)");
private static final Pattern patternGuid = Pattern.compile(".*" + Pattern.quote("guid=") + "([0-9a-z\\-]+)", Pattern.CASE_INSENSITIVE);
+ private static final Pattern patternUrlGeocode = Pattern.compile(".*" + Pattern.quote("wp=") + "([A-Z][0-9A-Z]+)", Pattern.CASE_INSENSITIVE);
/**
* supported groundspeak extensions of the GPX format
*/
@@ -228,7 +229,7 @@ public abstract class GPXParser extends FileParser {
static Date parseDate(String inputUntrimmed) throws ParseException {
String input = inputUntrimmed.trim();
- // remove milli seconds to reduce number of needed patterns
+ // remove milliseconds to reduce number of needed patterns
final Matcher matcher = PATTERN_MILLISECONDS.matcher(input);
input = matcher.replaceFirst("");
if (input.contains("Z")) {
@@ -254,8 +255,13 @@ public abstract class GPXParser extends FileParser {
public void start(Attributes attrs) {
try {
if (attrs.getIndex("lat") > -1 && attrs.getIndex("lon") > -1) {
- cache.setCoords(new Geopoint(Double.valueOf(attrs.getValue("lat")),
- Double.valueOf(attrs.getValue("lon"))));
+ final String latitude = attrs.getValue("lat");
+ final String longitude = attrs.getValue("lon");
+ // latitude and longitude are required attributes, but we export them empty for waypoints without coordinates
+ if (StringUtils.isNotBlank(latitude) && StringUtils.isNotBlank(longitude)) {
+ cache.setCoords(new Geopoint(Double.valueOf(latitude),
+ Double.valueOf(longitude)));
+ }
}
} catch (Exception e) {
Log.w("Failed to parse waypoint's latitude and/or longitude.");
@@ -299,8 +305,7 @@ public abstract class GPXParser extends FileParser {
result.put(key, cache);
showProgressMessage(progressHandler, progressStream.getProgress());
} else if (StringUtils.isNotBlank(cache.getName())
- && cache.getCoords() != null
- && StringUtils.contains(type, "waypoint")) {
+ && StringUtils.containsIgnoreCase(type, "waypoint")) {
addWaypointToCache();
}
@@ -422,6 +427,11 @@ public abstract class GPXParser extends FileParser {
cache.setGuid(guid);
}
}
+ final Matcher matcherCode = patternUrlGeocode.matcher(url);
+ if (matcherCode.matches()) {
+ String geocode = matcherCode.group(1);
+ cache.setGeocode(geocode);
+ }
}
});
@@ -485,8 +495,17 @@ public abstract class GPXParser extends FileParser {
gcCache.getChild(nsGC, "owner").setEndTextElementListener(new EndTextElementListener() {
@Override
- public void end(String cacheOwner) {
- cache.setOwner(validate(cacheOwner));
+ public void end(String ownerUserId) {
+ cache.setOwnerUserId(validate(ownerUserId));
+ }
+ });
+
+ // waypoint.cache.getOwner()
+ gcCache.getChild(nsGC, "placed_by").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String ownerDisplayName) {
+ cache.setOwnerDisplayName(validate(ownerDisplayName));
}
});
@@ -775,9 +794,17 @@ public abstract class GPXParser extends FileParser {
return WaypointType.TRAILHEAD;
} else if ("final location".equalsIgnoreCase(sym)) {
return WaypointType.FINAL;
- } else {
- return WaypointType.WAYPOINT;
}
+ // this is not fully correct, but lets also look for localized waypoint types
+ for (WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN) {
+ final String localized = waypointType.getL10n();
+ if (StringUtils.isNotEmpty(localized)) {
+ if (localized.equalsIgnoreCase(sym)) {
+ return waypointType;
+ }
+ }
+ }
+ return WaypointType.WAYPOINT;
}
private void findGeoCode(final String input) {
diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
index 002511a..230bc91 100644
--- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java
+++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
@@ -3,7 +3,6 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.RunnableWithArgument;
@@ -35,11 +34,11 @@ public final class FilterUserInterface {
}
}
- private final IAbstractActivity activity;
+ private final Activity activity;
private final ArrayList<FactoryEntry> registry;
private final Resources res;
- public FilterUserInterface(final IAbstractActivity activity) {
+ public FilterUserInterface(final Activity activity) {
this.activity = activity;
this.res = cgeoapplication.getInstance().getResources();
@@ -73,10 +72,10 @@ public final class FilterUserInterface {
}
public void selectFilter(final RunnableWithArgument<IFilter> runAfterwards) {
- final AlertDialog.Builder builder = new AlertDialog.Builder((Activity) activity);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.caches_filter);
- final ArrayAdapter<FactoryEntry> adapter = new ArrayAdapter<FactoryEntry>((Activity) activity, android.R.layout.select_dialog_item, registry);
+ final ArrayAdapter<FactoryEntry> adapter = new ArrayAdapter<FactoryEntry>(activity, android.R.layout.select_dialog_item, registry);
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
@@ -107,10 +106,10 @@ public final class FilterUserInterface {
return;
}
- final AlertDialog.Builder builder = new AlertDialog.Builder((Activity) activity);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(menuTitle);
- final ArrayAdapter<IFilter> adapter = new ArrayAdapter<IFilter>((Activity) activity, android.R.layout.select_dialog_item, filters);
+ final ArrayAdapter<IFilter> adapter = new ArrayAdapter<IFilter>(activity, android.R.layout.select_dialog_item, filters);
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
diff --git a/main/src/cgeo/geocaching/geopoint/HumanDistance.java b/main/src/cgeo/geocaching/geopoint/HumanDistance.java
deleted file mode 100644
index 25d1bb7..0000000
--- a/main/src/cgeo/geocaching/geopoint/HumanDistance.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cgeo.geocaching.geopoint;
-
-import cgeo.geocaching.Settings;
-
-import org.apache.commons.lang3.tuple.ImmutablePair;
-
-public class HumanDistance {
-
- public static ImmutablePair<Double, String> scaleUnit(final double distanceKilometers) {
- double distance;
- String units;
- if (Settings.isUseMetricUnits()) {
- if (distanceKilometers >= 1) {
- distance = distanceKilometers;
- units = "km";
- } else {
- distance = distanceKilometers * 1000;
- units = "m";
- }
- } else {
- distance = distanceKilometers / IConversion.MILES_TO_KILOMETER;
- if (distance >= 0.1) {
- units = "mi";
- } else {
- distance *= 5280;
- units = "ft";
- }
- }
- return new ImmutablePair<Double, String>(distance, units);
- }
-
- public static String getHumanDistance(final Float distanceKilometers) {
- if (distanceKilometers == null) {
- return "?";
- }
-
- final ImmutablePair<Double, String> scaled = scaleUnit(distanceKilometers);
- String formatString;
- if (scaled.left >= 100) {
- formatString = "%.0f";
- } else if (scaled.left >= 10) {
- formatString = "%.1f";
- } else {
- formatString = "%.2f";
- }
-
- return String.format(formatString + " %s", scaled.left, scaled.right);
- }
-}
diff --git a/main/src/cgeo/geocaching/geopoint/Units.java b/main/src/cgeo/geocaching/geopoint/Units.java
new file mode 100644
index 0000000..3da3ad9
--- /dev/null
+++ b/main/src/cgeo/geocaching/geopoint/Units.java
@@ -0,0 +1,73 @@
+package cgeo.geocaching.geopoint;
+
+import cgeo.geocaching.Settings;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+
+public class Units {
+
+ public static ImmutablePair<Double, String> scaleDistance(final double distanceKilometers) {
+ double distance;
+ String units;
+ if (Settings.isUseMetricUnits()) {
+ if (distanceKilometers >= 1) {
+ distance = distanceKilometers;
+ units = "km";
+ } else {
+ distance = distanceKilometers * 1000;
+ units = "m";
+ }
+ } else {
+ distance = distanceKilometers / IConversion.MILES_TO_KILOMETER;
+ if (distance >= 0.1) {
+ units = "mi";
+ } else {
+ distance *= 5280;
+ units = "ft";
+ }
+ }
+ return new ImmutablePair<Double, String>(distance, units);
+ }
+
+ public static String getDistanceFromKilometers(final Float distanceKilometers) {
+ if (distanceKilometers == null) {
+ return "?";
+ }
+
+ final ImmutablePair<Double, String> scaled = scaleDistance(distanceKilometers);
+ String formatString;
+ if (scaled.left >= 100) {
+ formatString = "%.0f";
+ } else if (scaled.left >= 10) {
+ formatString = "%.1f";
+ } else {
+ formatString = "%.2f";
+ }
+
+ return String.format(formatString + " %s", scaled.left, scaled.right);
+ }
+
+ /**
+ * Get human readable elevation, depending on settings for metric units.
+ * Result is rounded to full meters/feet, as the sensors don't have that precision anyway.
+ *
+ * @param meters
+ * @return
+ */
+ public static String getElevation(float meters) {
+ final ImmutablePair<Double, String> scaled = scaleDistance(meters / 1000f);
+ return (meters >= 0 ? "↥ " : "↧ ") + String.format("%d %s", Math.abs(Math.round(scaled.left)), scaled.right);
+ }
+
+ public static String getDistanceFromMeters(float meters) {
+ return getDistanceFromKilometers(meters / 1000f);
+ }
+
+ public static String getSpeed(float kilometersPerHour) {
+ final String speed = getDistanceFromKilometers(kilometersPerHour);
+ if (speed.endsWith("mi")) {
+ return speed.substring(0, speed.length() - 2) + "mph";
+ }
+ return speed + (Settings.isUseMetricUnits() ? "/h" : "ph");
+ }
+}
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index ce9d4e4..cf90430 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -85,6 +85,19 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
/** max. number of caches displayed in the Live Map */
public static final int MAX_CACHES = 500;
+ /**Controls the behaviour of the map*/
+ public enum MapMode {
+ /** Live Map where caches are loaded from online */
+ LIVE_ONLINE,
+ /** Live Map where caches are loaded only from database */
+ LIVE_OFFLINE,
+ /** Map around some coordinates */
+ COORDS,
+ /** Map with a single cache (no reload on move) */
+ SINGLE,
+ /** Map with a list of caches (no reload on move) */
+ LIST
+ }
/** Handler Messages */
private static final int HIDE_PROGRESS = 0;
private static final int SHOW_PROGRESS = 1;
@@ -99,6 +112,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static final String EXTRAS_WPTTYPE = "wpttype";
private static final String EXTRAS_MAPSTATE = "mapstate";
private static final String EXTRAS_SEARCH = "search";
+ private static final String EXTRAS_MAP_MODE = "map_mode";
+
private static final int MENU_SELECT_MAPVIEW = 1;
private static final int MENU_MAP_LIVE = 2;
private static final int MENU_STORE_CACHES = 3;
@@ -129,7 +144,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private WaypointType waypointTypeIntent = null;
private int[] mapStateIntent = null;
// status data
- private SearchResult search = null;
+ /** Last search result used for displaying header */
+ private SearchResult lastSearchResult = null;
private String[] tokens = null;
private boolean noMapTokenShowed = false;
// map status data
@@ -160,7 +176,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private static final int[][] INSET_USERMODIFIEDCOORDS = { { 21, 28, 0, 0 }, { 19, 25, 0, 0 } }; // bottom right, 12x12 / 26x26
private static final int[][] INSET_PERSONALNOTE = { { 0, 28, 21, 0 }, { 0, 25, 19, 0 } }; // bottom left, 12x12 / 26x26
- private static SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
+ private SparseArray<LayerDrawable> overlaysCache = new SparseArray<LayerDrawable>();
private int cachesCnt = 0;
/** List of caches in the viewport */
private LeastRecentlyUsedSet<cgCache> caches = null;
@@ -173,8 +189,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
private long detailProgressTime = 0L;
// views
private ImageSwitcher myLocSwitch = null;
+
+ /**Controls the map behaviour*/
+ private MapMode mapMode = null;
// other things
- private boolean live = true; // live map (live, dead) or rest (displaying caches on map)
+ // private boolean live = true; // live map (live, dead) or rest (displaying caches on map)
private boolean liveChanged = false; // previous state for loadTimer
private boolean centered = false; // if map is already centered
private boolean alreadyCentered = false; // -""- for setting my location
@@ -205,7 +224,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// set title
final StringBuilder title = new StringBuilder();
- if (live) {
+ if (mapMode == MapMode.LIVE_ONLINE) {
title.append(res.getString(R.string.map_live));
} else {
title.append(mapTitle);
@@ -220,8 +239,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
title.append(']');
}
- if (Settings.isDebug() && search != null && StringUtils.isNotBlank(search.getUrl())) {
- title.append('[').append(search.getUrl()).append(']');
+ if (Settings.isDebug() && lastSearchResult != null && StringUtils.isNotBlank(lastSearchResult.getUrl())) {
+ title.append('[').append(lastSearchResult.getUrl()).append(']');
}
ActivityMixin.setTitle(activity, title.toString());
@@ -363,6 +382,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// Get parameters from the intent
final Bundle extras = activity.getIntent().getExtras();
if (extras != null) {
+ mapMode = (MapMode) extras.get(EXTRAS_MAP_MODE);
searchIntent = (SearchResult) extras.getParcelable(EXTRAS_SEARCH);
geocodeIntent = extras.getString(EXTRAS_GEOCODE);
coordsIntent = (Geopoint) extras.getParcelable(EXTRAS_COORDS);
@@ -370,6 +390,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE);
mapTitle = extras.getString(EXTRAS_MAP_TITLE);
}
+ else {
+ mapMode = Settings.isLiveMap() ? MapMode.LIVE_ONLINE : MapMode.LIVE_OFFLINE;
+ }
if (StringUtils.isBlank(mapTitle)) {
mapTitle = res.getString(R.string.map_map);
}
@@ -429,11 +452,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapView.getMapController().setZoom(Settings.getMapZoom());
mapView.getMapController().setCenter(Settings.getMapCenter());
- // live map, if no arguments are given
- live = (searchIntent == null && geocodeIntent == null && coordsIntent == null);
-
if (null == mapStateIntent) {
- followMyLocation = live;
+ followMyLocation = mapMode == MapMode.LIVE_OFFLINE || mapMode == MapMode.LIVE_ONLINE;
} else {
followMyLocation = 1 == mapStateIntent[3];
if ((overlayCaches.getCircles() ? 1 : 0) != mapStateIntent[4]) {
@@ -523,6 +543,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
mapView.destroyDrawingCache();
}
+ overlaysCache.clear();
+
super.onPause();
}
@@ -579,19 +601,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
item = menu.findItem(MENU_MAP_LIVE); // live map
- if (live) {
- if (Settings.isLiveMap()) {
- item.setTitle(res.getString(R.string.map_live_disable));
- } else {
- item.setTitle(res.getString(R.string.map_live_enable));
- }
+ if (mapMode == MapMode.LIVE_ONLINE) {
+ item.setTitle(res.getString(R.string.map_live_disable));
} else {
- item.setEnabled(false);
item.setTitle(res.getString(R.string.map_live_enable));
}
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
- menu.findItem(MENU_STORE_CACHES).setEnabled(live && !isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && app.hasUnsavedCaches(new SearchResult(geocodesInViewport)));
+ menu.findItem(MENU_STORE_CACHES).setEnabled(isLiveMode() && !isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && app.hasUnsavedCaches(new SearchResult(geocodesInViewport)));
item = menu.findItem(MENU_CIRCLE_MODE); // show circles
if (overlayCaches != null && overlayCaches.getCircles()) {
@@ -601,9 +618,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
item = menu.findItem(MENU_AS_LIST);
- item.setEnabled(live && !isLoading());
+ item.setEnabled(isLiveMode() && !isLoading());
- menu.findItem(SUBMENU_STRATEGY).setEnabled(live);
+ menu.findItem(SUBMENU_STRATEGY).setEnabled(isLiveMode());
} catch (Exception e) {
Log.e("cgeomap.onPrepareOptionsMenu: " + e.toString());
}
@@ -611,6 +628,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return true;
}
+ private boolean isLiveMode() {
+ return mapMode == MapMode.LIVE_OFFLINE || mapMode == MapMode.LIVE_ONLINE;
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
final int id = item.getItemId();
@@ -621,8 +642,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return true;
case MENU_MAP_LIVE:
Settings.setLiveMap(!Settings.isLiveMap());
+ mapMode = Settings.isLiveMap() ? MapMode.LIVE_ONLINE : MapMode.LIVE_OFFLINE;
liveChanged = true;
- search = null;
+ lastSearchResult = null;
searchIntent = null;
ActivityMixin.invalidateOptionsMenu(activity);
return true;
@@ -797,6 +819,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
mapIntent.putExtra(EXTRAS_WPTTYPE, waypointTypeIntent != null ? waypointTypeIntent.id : null);
mapIntent.putExtra(EXTRAS_MAP_TITLE, mapTitle);
+ mapIntent.putExtra(EXTRAS_MAP_MODE, mapMode);
final int[] mapState = currentMapState();
if (mapState != null) {
@@ -1013,7 +1036,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (liveChanged) {
moved = true;
- } else if (live && Settings.isLiveMap() && !downloaded) {
+ } else if (mapMode == MapMode.LIVE_ONLINE && !downloaded) {
moved = true;
} else if (viewport == null) {
moved = true;
@@ -1124,38 +1147,31 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
@Override
public void run() {
- /**
- * True if we are currently showing the live map or a single points through coordsIntent.
- */
- final boolean isLiveMapOrCoords = searchIntent == null && geocodeIntent == null;
-
try {
showProgressHandler.sendEmptyMessage(SHOW_PROGRESS);
loadThreadRun = System.currentTimeMillis();
+ SearchResult searchResult;
// stage 1 - pull and render from the DB only for live map
- if (isLiveMapOrCoords) {
- // live map
- if (!live || !Settings.isLiveMap()) {
- search = new SearchResult(app.getStoredInViewport(viewport, Settings.getCacheType()));
- } else {
- search = new SearchResult(app.getCachedInViewport(viewport, Settings.getCacheType()));
- }
+ if (mapMode == MapMode.LIVE_ONLINE) {
+ searchResult = new SearchResult(app.getCachedInViewport(viewport, Settings.getCacheType()));
+ } else if (mapMode == MapMode.LIVE_OFFLINE) {
+ searchResult = new SearchResult(app.getStoredInViewport(viewport, Settings.getCacheType()));
} else {
// map started from another activity
- search = new SearchResult(searchIntent);
+ searchResult = new SearchResult(searchIntent);
if (geocodeIntent != null) {
- search.addGeocode(geocodeIntent);
+ searchResult.addGeocode(geocodeIntent);
}
}
- if (search != null) {
- downloaded = true;
- Set<cgCache> cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
- caches.addAll(cachesFromSearchResult);
- }
+ downloaded = true;
+ Set<cgCache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
+ // to update the caches they have to be removed first
+ caches.removeAll(cachesFromSearchResult);
+ caches.addAll(cachesFromSearchResult);
- if (live) {
+ if (isLiveMode()) {
final boolean excludeMine = Settings.isExcludeMyCaches();
final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
@@ -1170,8 +1186,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
countVisibleCaches();
if (cachesCnt < Settings.getWayPointsThreshold() || geocodeIntent != null) {
waypoints.clear();
- if (isLiveMapOrCoords) {
+ if (isLiveMode() || mapMode == MapMode.COORDS) {
//All visible waypoints
+ //FIXME apply type filter
waypoints.addAll(app.getWaypointsInViewport(viewport, Settings.isExcludeMyCaches(), Settings.isExcludeDisabledCaches()));
} else {
//All waypoints from the viewed caches
@@ -1184,9 +1201,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
//render
displayExecutor.execute(new DisplayRunnable(viewport));
- if (live && Settings.isLiveMap()) {
+ if (mapMode == MapMode.LIVE_ONLINE) {
downloadExecutor.execute(new DownloadRunnable(viewport));
}
+ lastSearchResult = searchResult;
} finally {
showProgressHandler.sendEmptyMessage(HIDE_PROGRESS); // hide progress
}
@@ -1210,6 +1228,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
showProgressHandler.sendEmptyMessage(SHOW_PROGRESS); // show progress
int count = 0;
+ SearchResult searchResult;
do {
if (tokens == null) {
@@ -1219,10 +1238,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
- search = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
- if (search != null) {
+ searchResult = ConnectorFactory.searchByViewport(viewport.resize(0.8), tokens);
+ if (searchResult != null) {
downloaded = true;
- if (search.getError() == StatusCode.NOT_LOGGED_IN) {
+ if (searchResult.getError() == StatusCode.NOT_LOGGED_IN) {
Login.login();
tokens = null;
} else {
@@ -1233,11 +1252,12 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
} while (count < 2);
- if (search != null) {
- Set<cgCache> result = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ if (searchResult != null) {
+ Set<cgCache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
// to update the caches they have to be removed first
caches.removeAll(result);
caches.addAll(result);
+ lastSearchResult = searchResult;
}
//render
@@ -1277,7 +1297,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (!cachesToDisplay.isEmpty()) {
// Only show waypoints for single view or setting
// when less than showWaypointsthreshold Caches shown
- if (cachesToDisplay.size() == 1 || (cachesCnt < Settings.getWayPointsThreshold())) {
+ if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) {
for (cgWaypoint waypoint : waypointsToDisplay) {
if (waypoint == null || waypoint.getCoords() == null) {
@@ -1642,6 +1662,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
public static void startActivitySearch(final Activity fromActivity, final SearchResult search, final String title) {
final Intent mapIntent = newIntent(fromActivity);
mapIntent.putExtra(EXTRAS_SEARCH, search);
+ mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.LIST);
if (StringUtils.isNotBlank(title)) {
mapIntent.putExtra(CGeoMap.EXTRAS_MAP_TITLE, title);
}
@@ -1649,11 +1670,14 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
public static void startActivityLiveMap(final Activity fromActivity) {
- fromActivity.startActivity(newIntent(fromActivity));
+ final Intent mapIntent = newIntent(fromActivity);
+ mapIntent.putExtra(EXTRAS_MAP_MODE, Settings.isLiveMap() ? MapMode.LIVE_ONLINE : MapMode.LIVE_OFFLINE);
+ fromActivity.startActivity(mapIntent);
}
public static void startActivityCoords(final Activity fromActivity, final Geopoint coords, final WaypointType type, final String title) {
final Intent mapIntent = newIntent(fromActivity);
+ mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.COORDS);
mapIntent.putExtra(EXTRAS_COORDS, coords);
if (type != null) {
mapIntent.putExtra(EXTRAS_WPTTYPE, type.id);
@@ -1666,6 +1690,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
public static void startActivityGeoCode(final Activity fromActivity, final String geocode) {
final Intent mapIntent = newIntent(fromActivity);
+ mapIntent.putExtra(EXTRAS_MAP_MODE, MapMode.SINGLE);
mapIntent.putExtra(EXTRAS_GEOCODE, geocode);
mapIntent.putExtra(EXTRAS_MAP_TITLE, geocode);
fromActivity.startActivity(mapIntent);
@@ -1705,7 +1730,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
.append(cache.getListId() > 0)
.toHashCode();
- final LayerDrawable ldFromCache = CGeoMap.overlaysCache.get(hashcode);
+ final LayerDrawable ldFromCache = overlaysCache.get(hashcode);
if (ldFromCache != null) {
item.setMarker(ldFromCache);
return item;
@@ -1763,7 +1788,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
ld.setLayerInset(index++, inset[0], inset[1], inset[2], inset[3]);
}
- CGeoMap.overlaysCache.put(hashcode, ld);
+ overlaysCache.put(hashcode, ld);
item.setMarker(ld);
return item;
diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
index 3fb6ed0..7c0c8e5 100644
--- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java
+++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
@@ -15,12 +15,10 @@ public class MapProviderFactory {
private final static int GOOGLEMAP_BASEID = 30;
private final static int MFMAP_BASEID = 40;
- private static MapProviderFactory instance = null;
+ private final static MapProvider[] mapProviders;
+ private final static SortedMap<Integer, MapSource> mapSources;
- private final MapProvider[] mapProviders;
- private SortedMap<Integer, MapSource> mapSources;
-
- private MapProviderFactory() {
+ static {
// add GoogleMapProvider only if google api is available in order to support x86 android emulator
if (isGoogleMapsInstalled()) {
mapProviders = new MapProvider[] { new GoogleMapProvider(GOOGLEMAP_BASEID), new MapsforgeMapProvider(MFMAP_BASEID) };
@@ -45,29 +43,16 @@ public class MapProviderFactory {
return googleMaps;
}
- private static synchronized void initInstance() {
- if (null == instance) {
- instance = new MapProviderFactory();
- }
- }
-
- private static MapProviderFactory getInstance() {
- if (null == instance) {
- initInstance();
- }
- return instance;
- }
-
public static SortedMap<Integer, MapSource> getMapSources() {
- return getInstance().mapSources;
+ return mapSources;
}
public static boolean isValidSourceId(int sourceId) {
- return getInstance().mapSources.containsKey(sourceId);
+ return mapSources.containsKey(sourceId);
}
public static boolean isSameActivity(int sourceId1, int sourceId2) {
- for (MapProvider mp : getInstance().mapProviders) {
+ for (MapProvider mp : mapProviders) {
if (mp.isMySource(sourceId1) && mp.isMySource(sourceId2)) {
return mp.isSameActivity(sourceId1, sourceId2);
}
@@ -76,17 +61,17 @@ public class MapProviderFactory {
}
public static MapProvider getMapProvider(int sourceId) {
- for (MapProvider mp : getInstance().mapProviders) {
+ for (MapProvider mp : mapProviders) {
if (mp.isMySource(sourceId)) {
return mp;
}
}
- return getInstance().mapProviders[0];
+ return mapProviders[0];
}
public static int getSourceOrdinalFromId(int sourceId) {
int sourceOrdinal = 0;
- for (int key : getInstance().mapSources.keySet()) {
+ for (int key : mapSources.keySet()) {
if (sourceId == key) {
return sourceOrdinal;
}
@@ -97,20 +82,18 @@ public class MapProviderFactory {
public static int getSourceIdFromOrdinal(int sourceOrdinal) {
int count = 0;
- for (int key : getInstance().mapSources.keySet()) {
+ for (int key : mapSources.keySet()) {
if (sourceOrdinal == count) {
return key;
}
count++;
}
- return getInstance().mapSources.firstKey();
+ return mapSources.firstKey();
}
public static void addMapviewMenuItems(Menu parentMenu, int groupId, int currentSource) {
- SortedMap<Integer, MapSource> mapSources = getInstance().mapSources;
-
- for (int key : mapSources.keySet()) {
- parentMenu.add(groupId, key, 0, mapSources.get(key).getName()).setCheckable(true).setChecked(key == currentSource);
+ for (Integer key : mapSources.keySet()) {
+ parentMenu.add(groupId, key, 0, mapSources.get(key).getName()).setCheckable(true).setChecked(key.intValue() == currentSource);
}
}
@@ -119,6 +102,6 @@ public class MapProviderFactory {
}
public static MapSource getMapSource(int sourceId) {
- return getInstance().mapSources.get(sourceId);
+ return mapSources.get(Integer.valueOf(sourceId));
}
}
diff --git a/main/src/cgeo/geocaching/maps/ScaleOverlay.java b/main/src/cgeo/geocaching/maps/ScaleOverlay.java
index 321624d..bee6acf 100644
--- a/main/src/cgeo/geocaching/maps/ScaleOverlay.java
+++ b/main/src/cgeo/geocaching/maps/ScaleOverlay.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.maps;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
+import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.interfaces.GeneralOverlay;
import cgeo.geocaching.maps.interfaces.GeoPointImpl;
import cgeo.geocaching.maps.interfaces.MapProjectionImpl;
@@ -62,7 +62,7 @@ public class ScaleOverlay implements GeneralOverlay {
final Geopoint leftCoords = new Geopoint(center.getLatitudeE6() / 1e6, center.getLongitudeE6() / 1e6 - span / 2);
final Geopoint rightCoords = new Geopoint(center.getLatitudeE6() / 1e6, center.getLongitudeE6() / 1e6 + span / 2);
- final ImmutablePair<Double, String> scaled = HumanDistance.scaleUnit(leftCoords.distanceTo(rightCoords) * SCALE_WIDTH_FACTOR);
+ final ImmutablePair<Double, String> scaled = Units.scaleDistance(leftCoords.distanceTo(rightCoords) * SCALE_WIDTH_FACTOR);
final double distanceRound = keepSignificantDigit(scaled.left);
final double pixels = Math.round((mapView.getWidth() * SCALE_WIDTH_FACTOR / scaled.left) * distanceRound);
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index eac7063..288336d 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -9,6 +9,7 @@ import cgeo.geocaching.utils.ImageHelper;
import cgeo.geocaching.utils.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
+
import org.apache.commons.lang3.StringUtils;
import android.content.Context;
@@ -37,7 +38,10 @@ public class HtmlImage implements Html.ImageGetter {
"flagcounter.com",
"compteur-blog.net",
"counter.digits.com",
- "andyhoppe"
+ "andyhoppe",
+ "besucherzaehler-homepage.de",
+ "hitwebcounter.com",
+ "kostenloser-counter.eu"
};
final private String geocode;
diff --git a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
new file mode 100644
index 0000000..bc63ef6
--- /dev/null
+++ b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
@@ -0,0 +1,118 @@
+package cgeo.geocaching.sorting;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RunnableWithArgument;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class ComparatorUserInterface {
+ private final Activity activity;
+ private final ArrayList<ComparatorEntry> registry;
+ private final Resources res;
+
+ private static final class ComparatorEntry {
+ private final String name;
+ private final Class<? extends CacheComparator> cacheComparator;
+
+ public ComparatorEntry(final String name, final Class<? extends CacheComparator> cacheComparator) {
+ this.name = name;
+ this.cacheComparator = cacheComparator;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ public ComparatorUserInterface(final Activity activity) {
+ this.activity = activity;
+ res = activity.getResources();
+
+ registry = new ArrayList<ComparatorUserInterface.ComparatorEntry>(20);
+
+ register(R.string.caches_sort_distance, null);
+ register(R.string.caches_sort_date_hidden, DateComparator.class);
+ register(R.string.caches_sort_difficulty, DifficultyComparator.class);
+ register(R.string.caches_sort_finds, FindsComparator.class);
+ register(R.string.caches_sort_gccode, GeocodeComparator.class);
+ register(R.string.caches_sort_inventory, InventoryComparator.class);
+ register(R.string.caches_sort_name, NameComparator.class);
+ register(R.string.caches_sort_favorites, PopularityComparator.class);
+ register(R.string.caches_sort_rating, RatingComparator.class);
+ register(R.string.caches_sort_size, SizeComparator.class);
+ register(R.string.caches_sort_state, StateComparator.class);
+ register(R.string.caches_sort_storage, StorageTimeComparator.class);
+ register(R.string.caches_sort_terrain, TerrainComparator.class);
+ register(R.string.caches_sort_date_logged, VisitComparator.class);
+ register(R.string.caches_sort_vote, VoteComparator.class);
+
+ // sort the menu labels alphabetically for easier reading
+ Collections.sort(registry, new Comparator<ComparatorEntry>() {
+
+ @Override
+ public int compare(ComparatorEntry lhs, ComparatorEntry rhs) {
+ return lhs.name.compareToIgnoreCase(rhs.name);
+ }
+ });
+ }
+
+ private void register(final int resourceId, Class<? extends CacheComparator> comparatorClass) {
+ registry.add(new ComparatorEntry(res.getString(resourceId), comparatorClass));
+ }
+
+ public void selectComparator(final CacheComparator current, final RunnableWithArgument<CacheComparator> runAfterwards) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(R.string.caches_sort_title);
+
+ // adapter doesn't work correctly here, therefore using the string array based method
+ final String[] items = new String[registry.size()];
+ for (int i = 0; i < items.length; i++) {
+ items[i] = registry.get(i).name;
+ }
+ builder.setSingleChoiceItems(items, getCurrentIndex(current), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int itemIndex) {
+ ComparatorEntry entry = registry.get(itemIndex);
+ try {
+ if (entry.cacheComparator == null) {
+ runAfterwards.run(null);
+ }
+ else {
+ CacheComparator comparator = entry.cacheComparator.newInstance();
+ runAfterwards.run(comparator);
+ }
+ } catch (Exception e) {
+ Log.e("selectComparator", e);
+ }
+ dialog.dismiss();
+ }
+ });
+
+ builder.create().show();
+ }
+
+ private int getCurrentIndex(final CacheComparator current) {
+ for (int index = 0; index < registry.size(); index++) {
+ final ComparatorEntry entry = registry.get(index);
+ if (current == null) {
+ if (entry.cacheComparator == null) {
+ return index;
+ }
+ }
+ else if (current.getClass().equals(entry.cacheComparator)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java
index 7129905..3136d47 100644
--- a/main/src/cgeo/geocaching/sorting/DateComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DateComparator.java
@@ -1,7 +1,9 @@
package cgeo.geocaching.sorting;
import cgeo.geocaching.cgCache;
+import cgeo.geocaching.cgeoapplication;
+import java.util.ArrayList;
import java.util.Date;
/**
@@ -16,10 +18,19 @@ public class DateComparator extends AbstractCacheComparator {
@Override
protected int compareCaches(cgCache cache1, cgCache cache2) {
- Date date1 = cache1.getHiddenDate();
- Date date2 = cache2.getHiddenDate();
+ final Date date1 = cache1.getHiddenDate();
+ final Date date2 = cache2.getHiddenDate();
if (date1 != null && date2 != null) {
- return date1.compareTo(date2);
+ final int dateDifference = date1.compareTo(date2);
+ // for equal dates, sort by distance
+ if (dateDifference == 0) {
+ final ArrayList<cgCache> list = new ArrayList<cgCache>();
+ list.add(cache1);
+ list.add(cache2);
+ final DistanceComparator distanceComparator = new DistanceComparator(cgeoapplication.getInstance().currentGeo().getCoords(), list);
+ return distanceComparator.compare(cache1, cache2);
+ }
+ return dateDifference;
}
if (date1 != null) {
return -1;
diff --git a/main/src/cgeo/geocaching/sorting/FindsComparator.java b/main/src/cgeo/geocaching/sorting/FindsComparator.java
index ad72ea3..6407b11 100644
--- a/main/src/cgeo/geocaching/sorting/FindsComparator.java
+++ b/main/src/cgeo/geocaching/sorting/FindsComparator.java
@@ -6,11 +6,7 @@ import cgeo.geocaching.enumerations.LogType;
public class FindsComparator extends AbstractCacheComparator {
- private cgeoapplication app;
-
- public FindsComparator(cgeoapplication app) {
- this.app = app;
- }
+ private final cgeoapplication app = cgeoapplication.getInstance();
@Override
protected boolean canCompare(cgCache cache1, cgCache cache2) {
@@ -25,15 +21,14 @@ public class FindsComparator extends AbstractCacheComparator {
}
private int getFindsCount(cgCache cache) {
- int finds = 0;
if (cache.getLogCounts().isEmpty()) {
cache.setLogCounts(app.loadLogCounts(cache.getGeocode()));
}
Integer logged = cache.getLogCounts().get(LogType.FOUND_IT);
if (logged != null) {
- finds = logged;
+ return logged;
}
- return finds;
+ return 0;
}
}
diff --git a/main/src/cgeo/geocaching/sorting/VisitComparator.java b/main/src/cgeo/geocaching/sorting/VisitComparator.java
index 548ec7a..46d8c58 100644
--- a/main/src/cgeo/geocaching/sorting/VisitComparator.java
+++ b/main/src/cgeo/geocaching/sorting/VisitComparator.java
@@ -10,7 +10,7 @@ public class VisitComparator extends AbstractCacheComparator {
@Override
protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
- return cache1.getVisitedDate() > 0 && cache2.getVisitedDate() > 0;
+ return true;
}
@Override
diff --git a/main/src/cgeo/geocaching/ui/AbstractUIFactory.java b/main/src/cgeo/geocaching/ui/AbstractUIFactory.java
new file mode 100644
index 0000000..2351383
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/AbstractUIFactory.java
@@ -0,0 +1,9 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.cgeoapplication;
+
+import android.content.res.Resources;
+
+public class AbstractUIFactory {
+ protected final static Resources res = cgeoapplication.getInstance().getResources();
+}
diff --git a/main/src/cgeo/geocaching/ui/AddressListAdapter.java b/main/src/cgeo/geocaching/ui/AddressListAdapter.java
index 17a9289..eb8b516 100644
--- a/main/src/cgeo/geocaching/ui/AddressListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/AddressListAdapter.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.cgeocaches;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
+import cgeo.geocaching.geopoint.Units;
import org.apache.commons.lang3.StringUtils;
@@ -73,7 +73,7 @@ public class AddressListAdapter extends ArrayAdapter<Address> {
private CharSequence getDistanceText(final Address address) {
if (location != null && address.hasLatitude() && address.hasLongitude()) {
- return HumanDistance.getHumanDistance(location.distanceTo(new Geopoint(address.getLatitude(), address.getLongitude())));
+ return Units.getDistanceFromKilometers(location.distanceTo(new Geopoint(address.getLatitude(), address.getLongitude())));
}
return "";
diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
index 70fc2bb..2a83ddc 100644
--- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
+++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
@@ -4,7 +4,7 @@ import cgeo.geocaching.R;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
+import cgeo.geocaching.geopoint.Units;
import org.apache.commons.lang3.StringUtils;
@@ -148,7 +148,7 @@ public final class CacheDetailsCreator {
}
String text = "--";
if (distance != null) {
- text = HumanDistance.getHumanDistance(distance);
+ text = Units.getDistanceFromKilometers(distance);
}
else if (cacheDistanceView != null) {
// if there is already a distance in cacheDistance, use it instead of resetting to default.
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index fcb4e54..65d3fbc 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -7,7 +7,6 @@ import cgeo.geocaching.Settings;
import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheListType;
-import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.geopoint.Geopoint;
@@ -18,7 +17,6 @@ import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import android.app.Activity;
@@ -29,6 +27,7 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.text.Spannable;
import android.text.Spanned;
+import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;
import android.util.SparseArray;
import android.view.GestureDetector;
@@ -264,19 +263,15 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
notifyDataSetChanged();
}
- public void setActualCoordinates(final Geopoint coordsIn) {
- if (coordsIn == null) {
- return;
- }
-
- coords = coordsIn;
+ public void setActualCoordinates(final Geopoint coords) {
+ this.coords = coords;
updateSortByDistance();
for (final DistanceView distance : distances) {
- distance.update(coordsIn);
+ distance.update(coords);
}
for (final CompassMiniView compass : compasses) {
- compass.updateCurrentCoords(coordsIn);
+ compass.updateCurrentCoords(coords);
}
}
@@ -296,7 +291,13 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
if (coords == null) {
return;
}
+ final ArrayList<cgCache> oldList = new ArrayList<cgCache>(list);
Collections.sort(list, new DistanceComparator(coords, list));
+
+ // avoid an update if the list has not changed due to location update
+ if (list.equals(oldList)) {
+ return;
+ }
notifyDataSetChanged();
lastSort = System.currentTimeMillis();
}
@@ -311,7 +312,6 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
}
azimuth = direction;
-
for (final CompassMiniView compass : compasses) {
compass.updateAzimuth(azimuth);
}
@@ -395,6 +395,9 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
if (cache.isDisabled() || cache.isArchived()) { // strike
cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
+ if (cache.isArchived()) {
+ cache.getNameSp().setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
}
holder.text.setText(cache.getNameSp(), TextView.BufferType.SPANNABLE);
@@ -497,37 +500,9 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
holder.favourite.setBackgroundResource(favoriteBack);
if (cacheListType == CacheListType.HISTORY && cache.getVisitedDate() > 0) {
- final ArrayList<String> infos = new ArrayList<String>();
- infos.add(StringUtils.upperCase(cache.getGeocode()));
- infos.add(Formatter.formatDate(cache.getVisitedDate()));
- infos.add(Formatter.formatTime(cache.getVisitedDate()));
- holder.info.setText(StringUtils.join(infos, Formatter.SEPARATOR));
+ holder.info.setText(Formatter.formatCacheInfoHistory(cache));
} else {
- final ArrayList<String> infos = new ArrayList<String>();
- if (StringUtils.isNotBlank(cache.getGeocode())) {
- infos.add(cache.getGeocode());
- }
- if (cache.hasDifficulty()) {
- infos.add("D " + String.format("%.1f", cache.getDifficulty()));
- }
- if (cache.hasTerrain()) {
- infos.add("T " + String.format("%.1f", cache.getTerrain()));
- }
-
- // don't show "not chosen" for events and virtuals, that should be the normal case
- if (cache.getSize() != CacheSize.UNKNOWN && cache.showSize()) {
- infos.add(cache.getSize().getL10n());
- } else if (cache.isEventCache() && cache.getHiddenDate() != null) {
- infos.add(Formatter.formatShortDate(cache.getHiddenDate().getTime()));
- }
-
- if (cache.isPremiumMembersOnly()) {
- infos.add(res.getString(R.string.cache_premium));
- }
- if (cacheListType != CacheListType.OFFLINE && cacheListType != CacheListType.HISTORY && cache.getListId() > 0) {
- infos.add(res.getString(R.string.cache_offline));
- }
- holder.info.setText(StringUtils.join(infos, Formatter.SEPARATOR));
+ holder.info.setText(Formatter.formatCacheInfoLong(cache, cacheListType));
}
return v;
diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java
index b328527..048e280 100644
--- a/main/src/cgeo/geocaching/ui/CompassView.java
+++ b/main/src/cgeo/geocaching/ui/CompassView.java
@@ -11,6 +11,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.util.AttributeSet;
+import android.util.FloatMath;
import android.view.View;
public class CompassView extends View {
@@ -136,9 +137,9 @@ public class CompassView extends View {
// If the difference is smaller than 1 degree, do nothing as it
// causes the arrow to vibrate. Round away from 0.
if (diff > 1.0) {
- offset = (float) Math.ceil(diff / 10.0); // for larger angles, rotate faster
+ offset = FloatMath.ceil(diff / 10.0f); // for larger angles, rotate faster
} else if (diff < 1.0) {
- offset = (float) Math.floor(diff / 10.0);
+ offset = FloatMath.floor(diff / 10.0f);
}
return AngleUtils.normalize(actual + offset);
@@ -200,16 +201,16 @@ public class CompassView extends View {
marginLeftTemp = (getWidth() - compassRoseWidth) / 2;
marginTopTemp = (getHeight() - compassRoseHeight) / 2;
- canvas.rotate((float) -azimuthTemp, canvasCenterX, canvasCenterY);
+ canvas.rotate(-azimuthTemp, canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassRose, marginLeftTemp, marginTopTemp, null);
- canvas.rotate((float) azimuthTemp, canvasCenterX, canvasCenterY);
+ canvas.rotate(azimuthTemp, canvasCenterX, canvasCenterY);
marginLeftTemp = (getWidth() - compassArrowWidth) / 2;
marginTopTemp = (getHeight() - compassArrowHeight) / 2;
- canvas.rotate((float) -azimuthRelative, canvasCenterX, canvasCenterY);
+ canvas.rotate(-azimuthRelative, canvasCenterX, canvasCenterY);
canvas.drawBitmap(compassArrow, marginLeftTemp, marginTopTemp, null);
- canvas.rotate((float) azimuthRelative, canvasCenterX, canvasCenterY);
+ canvas.rotate(azimuthRelative, canvasCenterX, canvasCenterY);
marginLeftTemp = (getWidth() - compassOverlayWidth) / 2;
marginTopTemp = (getHeight() - compassOverlayHeight) / 2;
@@ -260,4 +261,4 @@ public class CompassView extends View {
return result;
}
-} \ No newline at end of file
+}
diff --git a/main/src/cgeo/geocaching/ui/DistanceView.java b/main/src/cgeo/geocaching/ui/DistanceView.java
index 83de4aa..9611511 100644
--- a/main/src/cgeo/geocaching/ui/DistanceView.java
+++ b/main/src/cgeo/geocaching/ui/DistanceView.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.ui;
import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.HumanDistance;
+import cgeo.geocaching.geopoint.Units;
import android.content.Context;
import android.util.AttributeSet;
@@ -30,11 +30,11 @@ public class DistanceView extends TextView {
if (cacheCoords == null || coords == null) {
return;
}
- setText(HumanDistance.getHumanDistance(coords.distanceTo(cacheCoords)));
+ setText(Units.getDistanceFromKilometers(coords.distanceTo(cacheCoords)));
}
public void setDistance(Float distance) {
- setText("~" + HumanDistance.getHumanDistance(distance));
+ setText("~" + Units.getDistanceFromKilometers(distance));
}
public void clear() {
diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java
index 6ee1a65..53a7276 100644
--- a/main/src/cgeo/geocaching/ui/Formatter.java
+++ b/main/src/cgeo/geocaching/ui/Formatter.java
@@ -1,10 +1,21 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.cgWaypoint;
import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.enumerations.CacheListType;
+import cgeo.geocaching.enumerations.CacheSize;
+import cgeo.geocaching.enumerations.WaypointType;
+
+import org.apache.commons.lang3.StringUtils;
import android.content.Context;
import android.text.format.DateUtils;
+import java.util.ArrayList;
+import java.util.List;
+
public abstract class Formatter {
/** Text separator used for formatting texts */
@@ -64,6 +75,26 @@ public abstract class Formatter {
}
/**
+ * Generate a numeric date string according to system-wide settings (locale, date format)
+ * such as "10/20/2010". Today and yesterday will be presented as strings "today" and "yesterday".
+ *
+ * @param date
+ * milliseconds since the epoch
+ * @return the formatted string
+ */
+ public static String formatShortDateVerbally(long date) {
+ int diff = cgeo.geocaching.utils.DateUtils.daysSince(date);
+ switch (diff) {
+ case 0:
+ return cgeoapplication.getInstance().getString(R.string.log_today);
+ case 1:
+ return cgeoapplication.getInstance().getString(R.string.log_yesterday);
+ default:
+ return formatShortDate(date);
+ }
+ }
+
+ /**
* Generate a numeric date and time string according to system-wide settings (locale,
* date format) such as "7 sept. at 12:35".
*
@@ -77,4 +108,64 @@ public abstract class Formatter {
return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL);
}
+ public static String formatCacheInfoLong(cgCache cache, CacheListType cacheListType) {
+ final ArrayList<String> infos = new ArrayList<String>();
+ if (StringUtils.isNotBlank(cache.getGeocode())) {
+ infos.add(cache.getGeocode());
+ }
+
+ infos.add(Formatter.formatCacheInfoShort(cache));
+
+ if (cache.isPremiumMembersOnly()) {
+ infos.add(cgeoapplication.getInstance().getString(R.string.cache_premium));
+ }
+ if (cacheListType != CacheListType.OFFLINE && cacheListType != CacheListType.HISTORY && cache.getListId() > 0) {
+ infos.add(cgeoapplication.getInstance().getString(R.string.cache_offline));
+ }
+ return StringUtils.join(infos, Formatter.SEPARATOR);
+ }
+
+ public static String formatCacheInfoShort(cgCache cache) {
+ final ArrayList<String> infos = new ArrayList<String>();
+ if (cache.hasDifficulty()) {
+ infos.add("D " + String.format("%.1f", cache.getDifficulty()));
+ }
+ if (cache.hasTerrain()) {
+ infos.add("T " + String.format("%.1f", cache.getTerrain()));
+ }
+
+ // don't show "not chosen" for events and virtuals, that should be the normal case
+ if (cache.getSize() != CacheSize.UNKNOWN && cache.showSize()) {
+ infos.add(cache.getSize().getL10n());
+ } else if (cache.isEventCache() && cache.getHiddenDate() != null) {
+ infos.add(Formatter.formatShortDate(cache.getHiddenDate().getTime()));
+ }
+ return StringUtils.join(infos, Formatter.SEPARATOR);
+ }
+
+ public static String formatCacheInfoHistory(cgCache cache) {
+ final ArrayList<String> infos = new ArrayList<String>(3);
+ infos.add(StringUtils.upperCase(cache.getGeocode()));
+ infos.add(Formatter.formatDate(cache.getVisitedDate()));
+ infos.add(Formatter.formatTime(cache.getVisitedDate()));
+ return StringUtils.join(infos, Formatter.SEPARATOR);
+ }
+
+ public static String formatWaypointInfo(cgWaypoint waypoint) {
+ final List<String> infos = new ArrayList<String>(3);
+ if (WaypointType.ALL_TYPES_EXCEPT_OWN.contains(waypoint.getWaypointType())) {
+ infos.add(waypoint.getWaypointType().getL10n());
+ }
+ if (cgWaypoint.PREFIX_OWN.equalsIgnoreCase(waypoint.getPrefix())) {
+ infos.add(cgeoapplication.getInstance().getString(R.string.waypoint_custom));
+ } else {
+ if (StringUtils.isNotBlank(waypoint.getPrefix())) {
+ infos.add(waypoint.getPrefix());
+ }
+ if (StringUtils.isNotBlank(waypoint.getLookup())) {
+ infos.add(waypoint.getLookup());
+ }
+ }
+ return StringUtils.join(infos, Formatter.SEPARATOR);
+ }
}
diff --git a/main/src/cgeo/geocaching/ui/LoggingUI.java b/main/src/cgeo/geocaching/ui/LoggingUI.java
new file mode 100644
index 0000000..0e048c3
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/LoggingUI.java
@@ -0,0 +1,144 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.cgCache;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.activity.IAbstractActivity;
+import cgeo.geocaching.enumerations.LogType;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.ArrayAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LoggingUI extends AbstractUIFactory {
+ public static class LogTypeEntry {
+ private final LogType logType;
+ private final SpecialLogType specialLogType;
+ private final boolean isActive;
+
+ public LogTypeEntry(final LogType logType, final SpecialLogType specialLogType, final boolean isActive) {
+ this.logType = logType;
+ this.specialLogType = specialLogType;
+ this.isActive = isActive;
+ }
+
+ @Override
+ public String toString() {
+ if (logType == null) {
+ return specialLogType.getL10n();
+ }
+
+ String text = logType.getL10n();
+
+ if (isActive) {
+ text += " ✔";
+ }
+
+ return text;
+ }
+ }
+
+ private enum SpecialLogType {
+ LOG_CACHE(R.string.cache_menu_visit),
+ CLEAR_LOG(R.string.log_clear);
+
+ private final int stringId;
+
+ private SpecialLogType(final int stringId) {
+ this.stringId = stringId;
+ }
+
+ public final String getL10n() {
+ return res.getString(stringId);
+ }
+ }
+
+ private static final int MENU_ICON_LOG_VISIT = R.drawable.ic_menu_edit;
+ private static final int MENU_LOG_VISIT = 100;
+ private static final int MENU_LOG_VISIT_OFFLINE = 101;
+
+ public static void addMenuItems(final Menu menu, final cgCache cache) {
+ if (cache == null) {
+ return;
+ }
+ if (!cache.supportsLogging()) {
+ return;
+ }
+ if (Settings.getLogOffline()) {
+ menu.add(0, MENU_LOG_VISIT_OFFLINE, 0, res.getString(R.string.cache_menu_visit_offline)).setIcon(MENU_ICON_LOG_VISIT);
+ }
+ else {
+ menu.add(0, MENU_LOG_VISIT, 0, res.getString(R.string.cache_menu_visit)).setIcon(MENU_ICON_LOG_VISIT);
+ }
+ }
+
+ public static boolean onMenuItemSelected(final MenuItem item, IAbstractActivity activity, cgCache cache) {
+ switch (item.getItemId()) {
+ case MENU_LOG_VISIT:
+ cache.logVisit(activity);
+ return true;
+ case MENU_LOG_VISIT_OFFLINE:
+ showOfflineMenu(cache, (Activity) activity);
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static void showOfflineMenu(final cgCache cache, final Activity activity) {
+ final LogEntry currentLog = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode());
+ final LogType currentLogType = currentLog == null ? null : currentLog.type;
+
+ final List<LogType> logTypes = cache.getPossibleLogTypes();
+ final ArrayList<LogTypeEntry> list = new ArrayList<LogTypeEntry>();
+ for (LogType logType : logTypes) {
+ list.add(new LogTypeEntry(logType, null, logType == currentLogType));
+ }
+ if (cache.isLogOffline()) {
+ list.add(new LogTypeEntry(null, SpecialLogType.CLEAR_LOG, false));
+ }
+ list.add(new LogTypeEntry(null, SpecialLogType.LOG_CACHE, false));
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(R.string.cache_menu_visit_offline);
+
+ final ArrayAdapter<LogTypeEntry> adapter = new ArrayAdapter<LogTypeEntry>(activity, android.R.layout.select_dialog_item, list);
+
+ builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int item) {
+ final LogTypeEntry logTypeEntry = adapter.getItem(item);
+ if (logTypeEntry.logType == null) {
+ switch (logTypeEntry.specialLogType) {
+ case LOG_CACHE:
+ cache.logVisit((IAbstractActivity) activity);
+ break;
+
+ case CLEAR_LOG:
+ cgeoapplication.getInstance().clearLogOffline(cache.getGeocode());
+ }
+ } else {
+ cache.logOffline(activity, logTypeEntry.logType);
+ }
+ }
+ });
+
+ builder.create().show();
+
+ }
+
+ public static void onPrepareOptionsMenu(Menu menu) {
+ final MenuItem item = menu.findItem(MENU_LOG_VISIT);
+ if (item != null) {
+ item.setEnabled(Settings.isLogin());
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/utils/DateUtils.java b/main/src/cgeo/geocaching/utils/DateUtils.java
new file mode 100644
index 0000000..3004bdb
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/DateUtils.java
@@ -0,0 +1,18 @@
+package cgeo.geocaching.utils;
+
+import java.util.Calendar;
+
+public class DateUtils {
+ public static int daysSince(long date) {
+ final Calendar logDate = Calendar.getInstance();
+ logDate.setTimeInMillis(date);
+ logDate.set(Calendar.SECOND, 0);
+ logDate.set(Calendar.MINUTE, 0);
+ logDate.set(Calendar.HOUR, 0);
+ final Calendar today = Calendar.getInstance();
+ today.set(Calendar.SECOND, 0);
+ today.set(Calendar.MINUTE, 0);
+ today.set(Calendar.HOUR, 0);
+ return (int) Math.round((today.getTimeInMillis() - logDate.getTimeInMillis()) / 86400000d);
+ }
+}
diff --git a/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java b/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java
index 149605d..68bdb1f 100644
--- a/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java
+++ b/main/src/cgeo/geocaching/utils/UnknownTagsHandler.java
@@ -12,7 +12,7 @@ public class UnknownTagsHandler implements TagHandler {
private static final int UNDEFINED_POSITION = -1;
private static int countCells = 0;
int strikePos = UNDEFINED_POSITION;
- private boolean tableDetected = false;
+ private boolean problematicDetected = false;
@Override
public void handleTag(boolean opening, String tag, Editable output,
@@ -20,11 +20,13 @@ public class UnknownTagsHandler implements TagHandler {
if (tag.equalsIgnoreCase("strike") || tag.equals("s")) {
handleStrike(opening, output);
} else if (tag.equalsIgnoreCase("table")) {
- handleTable();
+ handleProblematic();
} else if (tag.equalsIgnoreCase("td")) {
handleTd(opening, output);
} else if (tag.equalsIgnoreCase("tr")) {
handleTr(opening, output);
+ } else if (tag.equalsIgnoreCase("pre")) {
+ handleProblematic();
}
}
@@ -40,12 +42,12 @@ public class UnknownTagsHandler implements TagHandler {
}
}
- public boolean isTableDetected() {
- return tableDetected;
+ public boolean isProblematicDetected() {
+ return problematicDetected;
}
- private void handleTable() {
- tableDetected = true;
+ private void handleProblematic() {
+ problematicDetected = true;
}
private static void handleTd(boolean opening, Editable output) {