aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/CacheDetailActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/cgeo/geocaching/CacheDetailActivity.java')
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java1161
1 files changed, 582 insertions, 579 deletions
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 0eb13c9..f35d599 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -1,10 +1,10 @@
package cgeo.geocaching;
import cgeo.calendar.ICalendar;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
-import cgeo.geocaching.apps.cache.GeneralAppsFactory;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
+import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.gc.GCConnector;
@@ -12,18 +12,22 @@ 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.Units;
import cgeo.geocaching.network.HtmlImage;
+import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.DecryptTextClickListener;
-import cgeo.geocaching.ui.EditorDialog;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.ImagesList;
import cgeo.geocaching.ui.ImagesList.ImageType;
import cgeo.geocaching.ui.LoggingUI;
+import cgeo.geocaching.ui.WeakReferenceHandler;
+import cgeo.geocaching.ui.dialog.EditorDialog;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.ClipboardUtils;
@@ -32,23 +36,26 @@ import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.ImageHelper;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.RunnableWithArgument;
import cgeo.geocaching.utils.TranslationUtils;
import cgeo.geocaching.utils.UnknownTagsHandler;
-import com.viewpagerindicator.TitlePageIndicator;
-import com.viewpagerindicator.TitleProvider;
-
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
import android.R.color;
import android.app.AlertDialog;
+import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
@@ -58,10 +65,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.Parcelable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
@@ -76,11 +79,11 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
-import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
@@ -93,17 +96,14 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.TextView.BufferType;
-import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -111,9 +111,8 @@ import java.util.regex.Pattern;
*
* e.g. details, description, logs, waypoints, inventory...
*/
-public class CacheDetailActivity extends AbstractActivity {
+public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> {
- private static final String EXTRAS_PAGE = "page";
private static final int MENU_FIELD_COPY = 1;
private static final int MENU_FIELD_TRANSLATE = 2;
private static final int MENU_FIELD_TRANSLATE_EN = 3;
@@ -130,10 +129,12 @@ public class CacheDetailActivity extends AbstractActivity {
private static final int CONTEXT_MENU_WAYPOINT_NAVIGATE = 1238;
private static final int CONTEXT_MENU_WAYPOINT_CACHES_AROUND = 1239;
private static final int CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION = 1240;
+ private static final int CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES = 1241;
private static final Pattern DARK_COLOR_PATTERN = Pattern.compile(Pattern.quote("color=\"#") + "(0[0-9]){3}" + "\"");
+ public static final String STATE_PAGE_INDEX = "cgeo.geocaching.pageIndex";
- private cgCache cache;
+ private Geocache cache;
private final Progress progress = new Progress();
private SearchResult search;
@@ -170,33 +171,6 @@ public class CacheDetailActivity extends AbstractActivity {
private int contextMenuWPIndex = -1;
/**
- * A {@link List} of all available pages.
- *
- * TODO Move to adapter
- */
- private final List<Page> pageOrder = new ArrayList<Page>();
-
- /**
- * Instances of all {@link PageViewCreator}.
- */
- private final Map<Page, PageViewCreator> viewCreators = new HashMap<Page, PageViewCreator>();
-
- /**
- * The {@link ViewPager} for this activity.
- */
- private ViewPager viewPager;
-
- /**
- * The {@link ViewPagerAdapter} for this activity.
- */
- private ViewPagerAdapter viewPagerAdapter;
-
- /**
- * The {@link TitlePageIndicator} for this activity.
- */
- private TitlePageIndicator titleIndicator;
-
- /**
* If another activity is called and can modify the data of this activity, we refresh it on resume.
*/
private boolean refreshOnResume = false;
@@ -227,8 +201,6 @@ public class CacheDetailActivity extends AbstractActivity {
setTitle(res.getString(R.string.cache));
String geocode = null;
- String guid = null;
- String name = null;
// TODO Why can it happen that search is not null? onCreate should be called only once and it is not set before.
if (search != null) {
@@ -243,16 +215,18 @@ public class CacheDetailActivity extends AbstractActivity {
final Uri uri = getIntent().getData();
// try to get data from extras
+ String name = null;
+ String guid = null;
if (geocode == null && extras != null) {
- geocode = extras.getString("geocode");
- name = extras.getString("name");
- guid = extras.getString("guid");
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
+ name = extras.getString(Intents.EXTRA_NAME);
+ guid = extras.getString(Intents.EXTRA_GUID);
}
// try to get data from URI
if (geocode == null && guid == null && uri != null) {
- String uriHost = uri.getHost().toLowerCase();
- String uriPath = uri.getPath().toLowerCase();
+ String uriHost = uri.getHost().toLowerCase(Locale.US);
+ String uriPath = uri.getPath().toLowerCase(Locale.US);
String uriQuery = uri.getQuery();
if (uriQuery != null) {
@@ -266,11 +240,11 @@ public class CacheDetailActivity extends AbstractActivity {
guid = uri.getQueryParameter("guid");
if (StringUtils.isNotBlank(geocode)) {
- geocode = geocode.toUpperCase();
+ geocode = geocode.toUpperCase(Locale.US);
guid = null;
} else if (StringUtils.isNotBlank(guid)) {
geocode = null;
- guid = guid.toLowerCase();
+ guid = guid.toLowerCase(Locale.US);
} else {
showToast(res.getString(R.string.err_detail_open));
finish();
@@ -278,7 +252,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
} else if (uriHost.contains("coord.info")) {
if (uriPath != null && uriPath.startsWith("/gc")) {
- geocode = uriPath.substring(1).toUpperCase();
+ geocode = uriPath.substring(1).toUpperCase(Locale.US);
} else {
showToast(res.getString(R.string.err_detail_open));
finish();
@@ -301,7 +275,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (StringUtils.isNotBlank(name)) {
title = name;
} else if (null != geocode && StringUtils.isNotBlank(geocode)) { // can't be null, but the compiler doesn't understand StringUtils.isNotBlank()
- title = geocode.toUpperCase();
+ title = geocode;
}
progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, loadCacheHandler.cancelMessage());
} catch (Exception e) {
@@ -317,55 +291,34 @@ public class CacheDetailActivity extends AbstractActivity {
}
});
- // initialize ViewPager
- viewPager = (ViewPager) findViewById(R.id.viewpager);
- viewPagerAdapter = new ViewPagerAdapter();
- viewPager.setAdapter(viewPagerAdapter);
+ final int pageToOpen = savedInstanceState != null ?
+ savedInstanceState.getInt(STATE_PAGE_INDEX, 0) :
+ Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1;
+ createViewPager(pageToOpen, new OnPageSelectedListener() {
- titleIndicator = (TitlePageIndicator) findViewById(R.id.pager_indicator);
- titleIndicator.setViewPager(viewPager);
- titleIndicator.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
if (Settings.isOpenLastDetailsPage()) {
Settings.setLastDetailsPage(position);
}
// lazy loading of cache images
- if (pageOrder.get(position) == Page.IMAGES) {
+ if (getPage(position) == Page.IMAGES) {
loadCacheImages();
}
}
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- }
});
- // switch to entry page (last used or 2)
- int entryPageIndex;
- if (extras != null && extras.get(EXTRAS_PAGE) != null) {
- entryPageIndex = extras.getInt(EXTRAS_PAGE);
- }
- else {
- entryPageIndex = Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1;
- }
- if (viewPagerAdapter.getCount() < entryPageIndex) {
- for (int i = 0; i <= entryPageIndex; i++) {
- // we can't switch to a page that is out of bounds, so we add null-pages
- pageOrder.add(null);
- }
- }
- viewPager.setCurrentItem(entryPageIndex, false);
-
// Initialization done. Let's load the data with the given information.
new LoadCacheThread(geocode, guid, loadCacheHandler).start();
}
@Override
+ public void onSaveInstanceState(final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_PAGE_INDEX, getCurrentItem());
+ }
+
+ @Override
public void onResume() {
super.onResume();
@@ -396,9 +349,10 @@ public class CacheDetailActivity extends AbstractActivity {
final int viewId = view.getId();
contextMenuWPIndex = -1;
switch (viewId) {
- case R.id.value: // coordinates
+ case R.id.value: // coordinates, gc-code, name
clickedItemText = ((TextView) view).getText();
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_coordinates), true);
+ String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
+ buildOptionsContextmenu(menu, viewId, itemTitle, true);
break;
case R.id.shortdesc:
clickedItemText = ((TextView) view).getText();
@@ -432,15 +386,19 @@ public class CacheDetailActivity extends AbstractActivity {
final ViewGroup parent = ((ViewGroup) view.getParent());
for (int i = 0; i < parent.getChildCount(); i++) {
if (parent.getChildAt(i) == view) {
- final List<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.getWaypoints());
+ final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints());
Collections.sort(sortedWaypoints);
- final cgWaypoint waypoint = sortedWaypoints.get(i);
+ final Waypoint waypoint = sortedWaypoints.get(i);
final int index = cache.getWaypoints().indexOf(waypoint);
menu.setHeaderTitle(res.getString(R.string.waypoint));
- menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit);
- menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate);
+ if (waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) {
+ menu.add(CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES, index, 0, R.string.waypoint_reset_cache_coords);
+ } else {
+ menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit);
+ menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate);
+ }
contextMenuWPIndex = index;
- if (waypoint.isUserDefined()) {
+ if (waypoint.isUserDefined() && !waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) {
menu.add(CONTEXT_MENU_WAYPOINT_DELETE, index, 0, R.string.waypoint_delete);
}
if (waypoint.getCoords() != null) {
@@ -512,54 +470,63 @@ public class CacheDetailActivity extends AbstractActivity {
}
break;
- case CONTEXT_MENU_WAYPOINT_EDIT: {
- final cgWaypoint waypoint = cache.getWaypoint(index);
- if (waypoint != null) {
- EditWaypointActivity.startActivityEditWaypoint(this, waypoint.getId());
+ case CONTEXT_MENU_WAYPOINT_EDIT:
+ final Waypoint waypointEdit = cache.getWaypoint(index);
+ if (waypointEdit != null) {
+ EditWaypointActivity.startActivityEditWaypoint(this, waypointEdit.getId());
refreshOnResume = true;
}
break;
- }
case CONTEXT_MENU_WAYPOINT_DUPLICATE:
- if (cache.duplicateWaypoint(index)) {
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ final Waypoint waypointDuplicate = cache.getWaypoint(index);
+ if (cache.duplicateWaypoint(waypointDuplicate)) {
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
break;
case CONTEXT_MENU_WAYPOINT_DELETE:
- if (cache.deleteWaypoint(index)) {
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ final Waypoint waypointDelete = cache.getWaypoint(index);
+ if (cache.deleteWaypoint(waypointDelete)) {
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
break;
- case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION: {
- final cgWaypoint waypoint = cache.getWaypoint(index);
- if (waypoint != null) {
- NavigationAppFactory.startDefaultNavigationApplication(1, this, waypoint);
+ case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION:
+ final Waypoint waypointNavigation = cache.getWaypoint(index);
+ if (waypointNavigation != null) {
+ NavigationAppFactory.startDefaultNavigationApplication(1, this, waypointNavigation);
}
- }
break;
- case CONTEXT_MENU_WAYPOINT_NAVIGATE: {
- final cgWaypoint waypoint = cache.getWaypoint(contextMenuWPIndex);
- if (waypoint != null) {
- NavigationAppFactory.showNavigationMenu(this, null, waypoint, null);
+ case CONTEXT_MENU_WAYPOINT_NAVIGATE:
+ final Waypoint waypointNav = cache.getWaypoint(contextMenuWPIndex);
+ if (waypointNav != null) {
+ NavigationAppFactory.showNavigationMenu(this, null, waypointNav, null);
}
- }
break;
- case CONTEXT_MENU_WAYPOINT_CACHES_AROUND: {
- final cgWaypoint waypoint = cache.getWaypoint(index);
- if (waypoint != null) {
- cgeocaches.startActivityCoordinates(this, waypoint.getCoords());
+ case CONTEXT_MENU_WAYPOINT_CACHES_AROUND:
+ final Waypoint waypointAround = cache.getWaypoint(index);
+ if (waypointAround != null) {
+ cgeocaches.startActivityCoordinates(this, waypointAround.getCoords());
}
- }
break;
- default: {
+
+ case CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES:
+ final Waypoint waypointReset = cache.getWaypoint(index);
+ if (ConnectorFactory.getConnector(cache).supportsOwnCoordinates()) {
+ createResetCacheCoordinatesDialog(cache, waypointReset).show();
+ }
+ else {
+ final ProgressDialog progressDialog = ProgressDialog.show(this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
+ final HandlerResetCoordinates handler = new HandlerResetCoordinates(this, progressDialog, false);
+ new ResetCoordsThread(cache, handler, waypointReset, true, false, progressDialog).start();
+ }
+ break;
+
+ default:
if (imagesList != null && imagesList.onContextItemSelected(item)) {
return true;
}
-
return onOptionsItemSelected(item);
- }
}
return false;
}
@@ -571,7 +538,6 @@ public class CacheDetailActivity extends AbstractActivity {
final SubMenu subMenu = menu.addSubMenu(0, 0, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
NavigationAppFactory.addMenuItems(subMenu, cache);
- GeneralAppsFactory.addMenuItems(subMenu, cache);
menu.add(0, MENU_CALENDAR, 0, res.getString(R.string.cache_menu_event)).setIcon(R.drawable.ic_menu_agenda); // add event to calendar
LoggingUI.addMenuItems(menu, cache);
@@ -584,10 +550,12 @@ public class CacheDetailActivity extends AbstractActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords());
- menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar());
- menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
- menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
+ if (cache != null) {
+ menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords());
+ menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar());
+ menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
+ menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
+ }
return super.onPrepareOptionsMenu(menu);
}
@@ -595,7 +563,7 @@ public class CacheDetailActivity extends AbstractActivity {
public boolean onOptionsItemSelected(MenuItem item) {
final int menuItem = item.getItemId();
- switch(menuItem) {
+ switch (menuItem) {
case 0:
// no menu selected, but a new sub menu shown
return false;
@@ -617,16 +585,14 @@ public class CacheDetailActivity extends AbstractActivity {
return true;
}
return false;
- }
- if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
- return true;
- }
- if (GeneralAppsFactory.onMenuItemSelected(item, this, cache)) {
- return true;
- }
- if (LoggingUI.onMenuItemSelected(item, this, cache)) {
- refreshOnResume = true;
- return true;
+ default:
+ if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ refreshOnResume = true;
+ return true;
+ }
}
return true;
@@ -641,6 +607,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (search == null) {
showToast(res.getString(R.string.err_dwld_details_failed));
+ progress.dismiss();
finish();
return;
}
@@ -648,6 +615,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (search.getError() != null) {
showToast(res.getString(R.string.err_dwld_details_failed) + " " + search.getError().getErrorString(res) + ".");
+ progress.dismiss();
finish();
return;
}
@@ -689,51 +657,18 @@ public class CacheDetailActivity extends AbstractActivity {
// allow cache to notify CacheDetailActivity when it changes so it can be reloaded
cache.setChangeNotificationHandler(cacheChangeNotificationHandler);
- // notify all creators that the data has changed
- for (PageViewCreator creator : viewCreators.values()) {
- creator.notifyDataSetChanged();
- }
-
- // action bar: title and icon (default: mystery icon)
+ // action bar: title and icon
if (StringUtils.isNotBlank(cache.getName())) {
- setTitle(cache.getName() + " (" + cache.getGeocode().toUpperCase() + ')');
+ setTitle(cache.getName() + " (" + cache.getGeocode() + ')');
} else {
- setTitle(cache.getGeocode().toUpperCase());
+ setTitle(cache.getGeocode());
}
((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(cache.getType().markerId), null, null, null);
- // add available pages (remove old pages first)
- pageOrder.clear();
-
- pageOrder.add(Page.WAYPOINTS);
- pageOrder.add(Page.DETAILS);
- final int detailsIndex = pageOrder.size() - 1;
- pageOrder.add(Page.DESCRIPTION);
- if (cache.getLogs().isNotEmpty()) {
- pageOrder.add(Page.LOGS);
- }
- if (CollectionUtils.isNotEmpty(cache.getFriendsLogs())) {
- pageOrder.add(Page.LOGSFRIENDS);
- }
- if (CollectionUtils.isNotEmpty(cache.getInventory())) {
- pageOrder.add(Page.INVENTORY);
- }
- if (CollectionUtils.isNotEmpty(cache.getImages())) {
- pageOrder.add(Page.IMAGES);
- }
-
- // switch to details page, if we're out of bounds
- if (viewPager.getCurrentItem() < 0 || viewPager.getCurrentItem() >= viewPagerAdapter.getCount()) {
- viewPager.setCurrentItem(detailsIndex, false);
- }
-
- // notify the adapter that the data has changed
- viewPagerAdapter.notifyDataSetChanged();
-
- // notify the indicator that the data has changed
- titleIndicator.notifyDataSetChanged();
+ reinitializeViewPager();
// rendering done! remove progress popup if any there
+ invalidateOptionsMenuCompatible();
progress.dismiss();
}
@@ -752,6 +687,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) {
showToast(res.getString(R.string.err_detail_cache_forgot));
+ progress.dismiss();
finish();
return;
}
@@ -762,7 +698,7 @@ public class CacheDetailActivity extends AbstractActivity {
@Override
public void run() {
- search = cgCache.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler);
+ search = Geocache.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler);
handler.sendMessage(Message.obtain());
}
}
@@ -842,14 +778,14 @@ public class CacheDetailActivity extends AbstractActivity {
}
/**
- * Tries to navigate to the {@link cgCache} of this activity.
+ * Tries to navigate to the {@link Geocache} of this activity.
*/
private void startDefaultNavigation() {
NavigationAppFactory.startDefaultNavigationApplication(1, this, cache);
}
/**
- * Tries to navigate to the {@link cgCache} of this activity.
+ * Tries to navigate to the {@link Geocache} of this activity.
*/
private void startDefaultNavigation2() {
NavigationAppFactory.startDefaultNavigationApplication(2, this, cache);
@@ -918,7 +854,8 @@ public class CacheDetailActivity extends AbstractActivity {
private void showUserActionsDialog(final CharSequence name) {
final CharSequence[] items = { res.getString(R.string.user_menu_view_hidden),
res.getString(R.string.user_menu_view_found),
- res.getString(R.string.user_menu_open_browser)
+ res.getString(R.string.user_menu_open_browser),
+ res.getString(R.string.user_menu_send_message)
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -934,7 +871,10 @@ public class CacheDetailActivity extends AbstractActivity {
cgeocaches.startActivityUserName(CacheDetailActivity.this, name.toString());
return;
case 2:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + URLEncoder.encode(name.toString()))));
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(name.toString()))));
+ return;
+ case 3:
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(name.toString()))));
return;
default:
break;
@@ -949,7 +889,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (imagesList != null) {
return;
}
- PageViewCreator creator = viewCreators.get(Page.IMAGES);
+ PageViewCreator creator = getViewCreator(Page.IMAGES);
if (creator == null) {
return;
}
@@ -957,139 +897,17 @@ public class CacheDetailActivity extends AbstractActivity {
if (imageView == null) {
return;
}
- imagesList = new ImagesList(CacheDetailActivity.this, cache.getGeocode());
+ imagesList = new ImagesList(this, cache.getGeocode());
imagesList.loadImages(imageView, cache.getImages(), ImageType.AllImages, false);
}
public static void startActivity(final Context context, final String geocode) {
final Intent detailIntent = new Intent(context, CacheDetailActivity.class);
- detailIntent.putExtra("geocode", geocode.toUpperCase());
- context.startActivity(detailIntent);
- }
-
- public static void startActivity(final Context context, final String geocode, final int page) {
- final Intent detailIntent = new Intent(context, CacheDetailActivity.class);
- detailIntent.putExtra("geocode", geocode.toUpperCase());
- detailIntent.putExtra(EXTRAS_PAGE, page);
+ detailIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
context.startActivity(detailIntent);
}
/**
- * The ViewPagerAdapter for scrolling through pages of the CacheDetailActivity.
- */
- private class ViewPagerAdapter extends PagerAdapter implements TitleProvider {
-
- @Override
- public void destroyItem(View container, int position, Object object) {
- ((ViewPager) container).removeView((View) object);
- }
-
- @Override
- public void finishUpdate(View container) {
- }
-
- @Override
- public int getCount() {
- return pageOrder.size();
- }
-
- @Override
- public Object instantiateItem(View container, int position) {
- final Page page = pageOrder.get(position);
-
- PageViewCreator creator = viewCreators.get(page);
-
- if (null == creator && null != page) {
- // The creator is not instantiated yet, let's do it.
- switch (page) {
- case DETAILS:
- creator = new DetailsViewCreator();
- break;
-
- case DESCRIPTION:
- creator = new DescriptionViewCreator();
- break;
-
- case LOGS:
- creator = new LogsViewCreator(true);
- break;
-
- case LOGSFRIENDS:
- creator = new LogsViewCreator(false);
- break;
-
- case WAYPOINTS:
- creator = new WaypointsViewCreator();
- break;
-
- case INVENTORY:
- creator = new InventoryViewCreator();
- break;
-
- case IMAGES:
- creator = new ImagesViewCreator();
- break;
- }
- viewCreators.put(page, creator);
- }
-
- View view = null;
-
- try {
- if (null != creator) {
- // Result from getView() is maybe cached, but it should be valid because the
- // creator should be informed about data-changes with notifyDataSetChanged()
- view = creator.getView();
- ((ViewPager) container).addView(view, 0);
- }
- } catch (Exception e) {
- Log.e("ViewPagerAdapter.instantiateItem ", e);
- }
-
- return view;
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return view == object;
- }
-
- @Override
- public void restoreState(Parcelable arg0, ClassLoader arg1) {
- }
-
- @Override
- public Parcelable saveState() {
- return null;
- }
-
- @Override
- public void startUpdate(View arg0) {
- }
-
- @Override
- public int getItemPosition(Object object) {
- // We are doing the caching. So pretend that the view is gone.
- // The ViewPager will get it back in instantiateItem()
- return POSITION_NONE;
- }
-
- @Override
- public String getTitle(int position) {
- final Page page = pageOrder.get(position);
- if (null == page) {
- return "";
- }
- // show number of waypoints directly in waypoint title
- if (page == Page.WAYPOINTS) {
- final int waypointCount = cache.getWaypoints().size();
- return res.getQuantityString(R.plurals.waypoints, waypointCount, waypointCount);
- }
- return res.getString(page.titleStringId);
- }
- }
-
- /**
* Enum of all possible pages with methods to get the view and a title.
*/
public enum Page {
@@ -1103,7 +921,7 @@ public class CacheDetailActivity extends AbstractActivity {
final private int titleStringId;
- private Page(final int titleStringId) {
+ Page(final int titleStringId) {
this.titleStringId = titleStringId;
}
}
@@ -1113,9 +931,7 @@ public class CacheDetailActivity extends AbstractActivity {
private ViewGroup attributeDescriptionsLayout; // layout for attribute descriptions
private boolean attributesShowAsIcons = true; // default: show icons
/**
- * True, if the cache was imported with an older version of c:geo.
- * These older versions parsed the attribute description from the tooltip in the web
- * page and put them into the DB. No icons can be matched for these.
+ * If the cache is from a non GC source, it might be without icons. Disable switching in those cases.
*/
private boolean noAttributeIconsFound = false;
private int attributeBoxMaxWidth;
@@ -1125,8 +941,7 @@ public class CacheDetailActivity extends AbstractActivity {
attributeBox.removeAllViews();
// maximum width for attribute icons is screen width - paddings of parents
- attributeBoxMaxWidth = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay().getWidth();
+ attributeBoxMaxWidth = Compatibility.getDisplayWidth();
ViewParent child = attributeBox;
do {
if (child instanceof View) {
@@ -1233,8 +1048,8 @@ public class CacheDetailActivity extends AbstractActivity {
}
final boolean strikethru = !CacheAttribute.isEnabled(attributeName);
- final CacheAttribute attrib = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attributeName));
- if (attrib != CacheAttribute.UNKNOWN) {
+ final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ if (attrib != null) {
noAttributeIconsFound = false;
Drawable d = res.getDrawable(attrib.drawableId);
iv.setImageDrawable(d);
@@ -1248,7 +1063,7 @@ public class CacheDetailActivity extends AbstractActivity {
fl.addView(strikethruImage);
}
} else {
- Drawable d = res.getDrawable(R.drawable.attribute_icon_not_found);
+ Drawable d = res.getDrawable(R.drawable.attribute_unknown);
iv.setImageDrawable(d);
}
@@ -1275,56 +1090,27 @@ public class CacheDetailActivity extends AbstractActivity {
for (String attributeName : cache.getAttributes()) {
final boolean enabled = CacheAttribute.isEnabled(attributeName);
// search for a translation of the attribute
- CacheAttribute attrib = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attributeName));
- if (attrib != CacheAttribute.UNKNOWN) {
- attributeName = attrib.getL10n(enabled);
+ CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ if (attrib == null) {
+ attrib = CacheAttribute.UNKNOWN;
}
+ attributeName = attrib.getL10n(enabled);
if (buffer.length() > 0) {
buffer.append('\n');
}
buffer.append(attributeName);
}
- if (noAttributeIconsFound) {
- buffer.append("\n\n").append(res.getString(R.string.cache_attributes_no_icons));
- }
-
attribView.setText(buffer);
return descriptions;
}
}
- private interface PageViewCreator {
- /**
- * Returns a validated view.
- *
- * @return
- */
- public View getDispatchedView();
-
- /**
- * Returns a (maybe cached) view.
- *
- * @return
- */
- public View getView();
-
- /**
- * Handles changed data-sets.
- */
- public void notifyDataSetChanged();
- }
-
/**
* Creator for details-view.
*/
- private class DetailsViewCreator implements PageViewCreator {
- /**
- * The main view for this creator
- */
- private ScrollView view;
-
+ private class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
/**
* Reference to the details list, so that the helper-method can access it without an additional argument
*/
@@ -1336,22 +1122,7 @@ public class CacheDetailActivity extends AbstractActivity {
private Thread watchlistThread;
@Override
- public void notifyDataSetChanged() {
- // There is a lot of data in this view, let's update everything
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ScrollView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ScrollView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -1376,10 +1147,10 @@ public class CacheDetailActivity extends AbstractActivity {
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);
+ registerForContextMenu(details.add(R.string.cache_name, span));
details.add(R.string.cache_type, cache.getType().getL10n());
details.addSize(cache);
- details.add(R.string.cache_geocode, cache.getGeocode().toUpperCase());
+ registerForContextMenu(details.add(R.string.cache_geocode, cache.getGeocode()));
details.addCacheState(cache);
details.addDistance(cache, cacheDistanceView);
@@ -1389,8 +1160,10 @@ public class CacheDetailActivity extends AbstractActivity {
details.addTerrain(cache);
details.addRating(cache);
- // favourite count
- details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ // favorite count
+ if (cache.getFavoritePoints() > 0) {
+ details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ }
// own rating
if (cache.getMyVote() > 0) {
@@ -1429,32 +1202,32 @@ public class CacheDetailActivity extends AbstractActivity {
if (cache.getCoords() != null) {
TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString());
valueView.setOnClickListener(new View.OnClickListener() {
- private int position = 0;
- private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] {
- GeopointFormatter.Format.LAT_LON_DECMINUTE,
- GeopointFormatter.Format.LAT_LON_DECSECOND,
- GeopointFormatter.Format.LAT_LON_DECDEGREE
- };
-
- // rotate coordinate formats on click
- @Override
- public void onClick(View view) {
- position = (position + 1) % availableFormats.length;
+ private int position = 0;
+ private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] {
+ GeopointFormatter.Format.LAT_LON_DECMINUTE,
+ GeopointFormatter.Format.LAT_LON_DECSECOND,
+ GeopointFormatter.Format.LAT_LON_DECDEGREE
+ };
+
+ // rotate coordinate formats on click
+ @Override
+ public void onClick(View view) {
+ position = (position + 1) % availableFormats.length;
- final TextView valueView = (TextView) view.findViewById(R.id.value);
- valueView.setText(cache.getCoords().format(availableFormats[position]));
- }
- });
+ final TextView valueView = (TextView) view.findViewById(R.id.value);
+ valueView.setText(cache.getCoords().format(availableFormats[position]));
+ }
+ });
registerForContextMenu(valueView);
}
// cache attributes
- if (cache.getAttributes().isNotEmpty()) {
+ if (!cache.getAttributes().isEmpty()) {
new AttributeViewBuilder().fillView((LinearLayout) view.findViewById(R.id.attributes_innerbox));
view.findViewById(R.id.attributes_box).setVisibility(View.VISIBLE);
}
- updateOfflineBox();
+ updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
// watchlist
Button buttonWatchlistAdd = (Button) view.findViewById(R.id.add_to_watchlist);
@@ -1466,23 +1239,15 @@ public class CacheDetailActivity extends AbstractActivity {
// favorite points
Button buttonFavPointAdd = (Button) view.findViewById(R.id.add_to_favpoint);
Button buttonFavPointRemove = (Button) view.findViewById(R.id.remove_from_favpoint);
- buttonFavPointAdd.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- GCConnector.addToFavorites(cache);
- updateFavPointBox();
- }
- });
- buttonFavPointRemove.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- GCConnector.removeFromFavorites(cache);
- updateFavPointBox();
- }
- });
-
+ buttonFavPointAdd.setOnClickListener(new FavoriteAddClickListener());
+ buttonFavPointRemove.setOnClickListener(new FavoriteRemoveClickListener());
updateFavPointBox();
+ // list
+ Button buttonChangeList = (Button) view.findViewById(R.id.change_list);
+ buttonChangeList.setOnClickListener(new ChangeListClickListener());
+ updateListBox();
+
// data license
IConnector connector = ConnectorFactory.getConnector(cache);
if (connector != null) {
@@ -1552,6 +1317,21 @@ public class CacheDetailActivity extends AbstractActivity {
return;
}
+ if (Settings.getChooseList()) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ storeCache(selectedListId);
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ storeCache(StoredList.TEMPORARY_LIST_ID);
+ }
+ }
+
+ protected void storeCache(int listId) {
final StoreCacheHandler storeCacheHandler = new StoreCacheHandler();
progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
@@ -1560,7 +1340,7 @@ public class CacheDetailActivity extends AbstractActivity {
storeThread.interrupt();
}
- storeThread = new StoreCacheThread(storeCacheHandler);
+ storeThread = new StoreCacheThread(listId, storeCacheHandler);
storeThread.start();
}
}
@@ -1587,15 +1367,17 @@ public class CacheDetailActivity extends AbstractActivity {
}
private class StoreCacheThread extends Thread {
+ final private int listId;
final private CancellableHandler handler;
- public StoreCacheThread(final CancellableHandler handler) {
+ public StoreCacheThread(final int listId, final CancellableHandler handler) {
+ this.listId = listId;
this.handler = handler;
}
@Override
public void run() {
- cache.store(handler);
+ cache.store(listId, handler);
}
}
@@ -1715,6 +1497,102 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
+ /** Thread to add this cache to the favourite list of the user */
+ private class FavoriteAddThread extends Thread {
+ private final Handler handler;
+
+ public FavoriteAddThread(Handler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public void run() {
+ handler.sendEmptyMessage(GCConnector.addToFavorites(cache) ? 1 : -1);
+ }
+ }
+
+ /** Thread to remove this cache to the favourite list of the user */
+ private class FavoriteRemoveThread extends Thread {
+ private final Handler handler;
+
+ public FavoriteRemoveThread(Handler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public void run() {
+ handler.sendEmptyMessage(GCConnector.removeFromFavorites(cache) ? 1 : -1);
+ }
+ }
+
+ private class FavoriteUpdateHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ progress.dismiss();
+ if (msg.what == -1) {
+ showToast(res.getString(R.string.err_favorite_failed));
+ } else {
+ CacheDetailActivity.this.notifyDataSetChanged(); // reload cache details
+ }
+ }
+ }
+
+ /**
+ * Listener for "add to favourites" button
+ */
+ private class FavoriteAddClickListener extends AbstractWatchlistClickListener {
+ @Override
+ public void onClick(View arg0) {
+ doExecute(R.string.cache_dialog_favourite_add_title,
+ R.string.cache_dialog_favourite_add_message,
+ new FavoriteAddThread(new FavoriteUpdateHandler()));
+ }
+ }
+
+ /**
+ * Listener for "remove from favourites" button
+ */
+ private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener {
+ @Override
+ public void onClick(View arg0) {
+ doExecute(R.string.cache_dialog_favourite_remove_title,
+ R.string.cache_dialog_favourite_remove_message,
+ new FavoriteRemoveThread(new FavoriteUpdateHandler()));
+ }
+ }
+
+ /**
+ * Listener for "change list" button
+ */
+ private class ChangeListClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(View view) {
+ new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ switchListById(selectedListId);
+ }
+ }, true, cache.getListId());
+ }
+ }
+
+ /**
+ * move cache to another list
+ *
+ * @param listId
+ * the ID of the list
+ */
+ public void switchListById(int listId) {
+ if (listId < 0) {
+ return;
+ }
+
+ Settings.saveLastList(listId);
+ cgData.moveToList(cache, listId);
+ updateListBox();
+ }
+
/**
* shows/hides buttons, sets text in watchlist box
*/
@@ -1729,7 +1607,7 @@ public class CacheDetailActivity extends AbstractActivity {
Button buttonRemove = (Button) view.findViewById(R.id.remove_from_watchlist);
TextView text = (TextView) view.findViewById(R.id.watchlist_text);
- if (cache.isOnWatchlist() || cache.isOwn()) {
+ if (cache.isOnWatchlist() || cache.isOwner()) {
buttonAdd.setVisibility(View.GONE);
buttonRemove.setVisibility(View.VISIBLE);
text.setText(R.string.cache_watchlist_on);
@@ -1740,7 +1618,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
// the owner of a cache has it always on his watchlist. Adding causes an error
- if (cache.isOwn()) {
+ if (cache.isOwner()) {
buttonAdd.setEnabled(false);
buttonAdd.setVisibility(View.GONE);
buttonRemove.setEnabled(false);
@@ -1756,7 +1634,7 @@ public class CacheDetailActivity extends AbstractActivity {
LinearLayout layout = (LinearLayout) view.findViewById(R.id.favpoint_box);
boolean supportsFavoritePoints = cache.supportsFavoritePoints();
layout.setVisibility(supportsFavoritePoints ? View.VISIBLE : View.GONE);
- if (!supportsFavoritePoints || cache.isOwn() || !Settings.isPremiumMember()) {
+ if (!supportsFavoritePoints || cache.isOwner() || !Settings.isPremiumMember()) {
return;
}
Button buttonAdd = (Button) view.findViewById(R.id.add_to_favpoint);
@@ -1783,6 +1661,31 @@ public class CacheDetailActivity extends AbstractActivity {
}
/**
+ * shows/hides/updates list box
+ */
+ private void updateListBox() {
+ View box = view.findViewById(R.id.list_box);
+
+ if (cache.isOffline()) {
+ // show box
+ box.setVisibility(View.VISIBLE);
+
+ // update text
+ TextView text = (TextView) view.findViewById(R.id.list_text);
+ StoredList list = cgData.getList(cache.getListId());
+ if (list != null) {
+ text.setText(res.getString(R.string.cache_list_text) + " " + list.title);
+ } else {
+ // this should not happen
+ text.setText(R.string.cache_list_unknown);
+ }
+ } else {
+ // hide box
+ box.setVisibility(View.GONE);
+ }
+ }
+
+ /**
* Handler, called when watchlist add or remove is done
*/
private class WatchlistHandler extends Handler {
@@ -1793,49 +1696,9 @@ public class CacheDetailActivity extends AbstractActivity {
if (msg.what == -1) {
showToast(res.getString(R.string.err_watchlist_failed));
} else {
- updateWatchlistBox();
- }
- }
- }
-
- private void updateOfflineBox() {
- // offline use
- final TextView offlineText = (TextView) view.findViewById(R.id.offline_text);
- final Button offlineRefresh = (Button) view.findViewById(R.id.offline_refresh);
- final Button offlineStore = (Button) view.findViewById(R.id.offline_store);
-
- if (cache.isOffline()) {
- long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
-
- String ago;
- if (diff < 15) {
- ago = res.getString(R.string.cache_offline_time_mins_few);
- } else if (diff < 50) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + diff + " " + res.getString(R.string.cache_offline_time_mins);
- } else if (diff < 90) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + res.getString(R.string.cache_offline_time_hour);
- } else if (diff < (48 * 60)) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / 60) + " " + res.getString(R.string.cache_offline_time_hours);
- } else {
- ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / (24 * 60)) + " " + res.getString(R.string.cache_offline_time_days);
+ CacheDetailActivity.this.notifyDataSetChanged(); // reload cache details
}
-
- offlineText.setText(res.getString(R.string.cache_offline_stored) + "\n" + ago);
- offlineRefresh.setOnClickListener(new RefreshCacheClickListener());
-
- offlineStore.setText(res.getString(R.string.cache_offline_drop));
- offlineStore.setClickable(true);
- offlineStore.setOnClickListener(new DropCacheClickListener());
- } else {
- offlineText.setText(res.getString(R.string.cache_offline_not_ready));
- offlineRefresh.setOnClickListener(new RefreshCacheClickListener());
-
- offlineStore.setText(res.getString(R.string.cache_offline_store));
- offlineStore.setClickable(true);
- offlineStore.setOnClickListener(new StoreCacheClickListener());
}
- offlineRefresh.setVisibility(cache.supportsRefresh() ? View.VISIBLE : View.GONE);
- offlineRefresh.setClickable(true);
}
private class PreviewMapTask extends AsyncTask<Void, Void, BitmapDrawable> {
@@ -1860,7 +1723,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private Bitmap decode(final cgCache cache) {
+ private Bitmap decode(final Geocache cache) {
return StaticMapsProvider.getPreviewMap(cache.getGeocode());
}
@@ -1870,38 +1733,26 @@ public class CacheDetailActivity extends AbstractActivity {
return;
}
- final Bitmap bitmap = image.getBitmap();
- if (bitmap == null || bitmap.getWidth() <= 10) {
- return;
- }
+ try {
+ final Bitmap bitmap = image.getBitmap();
+ if (bitmap == null || bitmap.getWidth() <= 10) {
+ return;
+ }
- ((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image);
- view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
+ ((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image);
+ view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
+ } catch (Exception e) {
+ Log.e("CacheDetailActivity.PreviewMapTask", e);
+ }
}
}
}
- private class DescriptionViewCreator implements PageViewCreator {
-
- private ScrollView view;
+ private class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ScrollView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ScrollView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -1948,7 +1799,7 @@ public class CacheDetailActivity extends AbstractActivity {
public void update(CharSequence editorText) {
cache.setPersonalNote(editorText.toString());
setPersonalNote(personalNoteView);
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
}
});
editor.show();
@@ -2086,7 +1937,9 @@ public class CacheDetailActivity extends AbstractActivity {
// sometimes technically incorrect.
if (unknownTagsHandler.isProblematicDetected() && descriptionView != null) {
final int startPos = description.length();
- ((Editable) description).append("\n\n").append(res.getString(R.string.cache_description_table_note));
+ final IConnector connector = ConnectorFactory.getConnector(cache);
+ final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>"));
+ ((Editable) description).append("\n\n").append(tableNote);
((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
publishProgress();
}
@@ -2135,7 +1988,7 @@ public class CacheDetailActivity extends AbstractActivity {
backcolor = color.darker_gray;
}
else {
- Matcher matcher = DARK_COLOR_PATTERN.matcher(text);
+ MatcherWrapper matcher = new MatcherWrapper(DARK_COLOR_PATTERN, text);
if (matcher.find()) {
backcolor = color.darker_gray;
}
@@ -2144,31 +1997,15 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class LogsViewCreator implements PageViewCreator {
- private ListView view;
- private boolean allLogs;
+ private class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> {
+ private final boolean allLogs;
LogsViewCreator(boolean allLogs) {
- super();
this.allLogs = allLogs;
}
@Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ListView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ListView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -2187,7 +2024,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- if (sortedLogCounts.size() > 0) {
+ if (!sortedLogCounts.isEmpty()) {
// 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>>() {
@@ -2208,7 +2045,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- final List<LogEntry> logs = allLogs ? cache.getLogs().asList() : cache.getFriendsLogs();
+ final List<LogEntry> logs = allLogs ? cache.getLogs() : cache.getFriendsLogs();
view.setAdapter(new ArrayAdapter<LogEntry>(CacheDetailActivity.this, R.layout.cacheview_logs_item, logs) {
final UserActionsClickListener userActionsClickListener = new UserActionsClickListener();
final DecryptTextClickListener decryptTextClickListener = new DecryptTextClickListener();
@@ -2241,7 +2078,7 @@ public class CacheDetailActivity extends AbstractActivity {
holder.count.setVisibility(View.VISIBLE);
if (log.found == -1) {
holder.count.setVisibility(View.GONE);
- } else {
+ } else {
holder.count.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found));
}
@@ -2262,7 +2099,7 @@ public class CacheDetailActivity extends AbstractActivity {
holder.images.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.getLogImages()));
+ ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<Image>(log.getLogImages()));
}
});
} else {
@@ -2270,23 +2107,12 @@ public class CacheDetailActivity extends AbstractActivity {
}
// colored marker
- holder.statusMarker.setVisibility(View.VISIBLE);
- if (log.type == LogType.FOUND_IT
- || log.type == LogType.WEBCAM_PHOTO_TAKEN
- || log.type == LogType.ATTENDED) {
- holder.statusMarker.setImageResource(R.drawable.mark_green);
- } else if (log.type == LogType.PUBLISH_LISTING
- || log.type == LogType.ENABLE_LISTING
- || log.type == LogType.OWNER_MAINTENANCE) {
- holder.statusMarker.setImageResource(R.drawable.mark_green_more);
- } else if (log.type == LogType.DIDNT_FIND_IT
- || log.type == LogType.NEEDS_MAINTENANCE
- || log.type == LogType.NEEDS_ARCHIVE) {
- holder.statusMarker.setImageResource(R.drawable.mark_red);
- } else if (log.type == LogType.TEMP_DISABLE_LISTING
- || log.type == LogType.ARCHIVE) {
- holder.statusMarker.setImageResource(R.drawable.mark_red_more);
- } else {
+ int marker = log.type.markerId;
+ if (marker != 0) {
+ holder.statusMarker.setVisibility(View.VISIBLE);
+ holder.statusMarker.setImageResource(marker);
+ }
+ else {
holder.statusMarker.setVisibility(View.GONE);
}
@@ -2326,26 +2152,10 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class WaypointsViewCreator implements PageViewCreator {
-
- private ScrollView view;
+ private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ScrollView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ScrollView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -2356,10 +2166,10 @@ public class CacheDetailActivity extends AbstractActivity {
final LinearLayout waypoints = (LinearLayout) view.findViewById(R.id.waypoints);
// sort waypoints: PP, Sx, FI, OWN
- final List<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.getWaypoints());
+ final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints());
Collections.sort(sortedWaypoints);
- for (final cgWaypoint wpt : sortedWaypoints) {
+ for (final Waypoint wpt : sortedWaypoints) {
final LinearLayout waypointView = (LinearLayout) getLayoutInflater().inflate(R.layout.waypoint_item, null);
// coordinates
@@ -2441,26 +2251,10 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class InventoryViewCreator implements PageViewCreator {
-
- private ListView view;
-
- @Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ListView) getDispatchedView();
- }
-
- return view;
- }
+ private class InventoryViewCreator extends AbstractCachingPageViewCreator<ListView> {
@Override
- public View getDispatchedView() {
+ public ListView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -2470,14 +2264,14 @@ public class CacheDetailActivity extends AbstractActivity {
// TODO: fix layout, then switch back to Android-resource and delete copied one
// this copy is modified to respect the text color
- view.setAdapter(new ArrayAdapter<cgTrackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory()));
+ view.setAdapter(new ArrayAdapter<Trackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory()));
view.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Object selection = arg0.getItemAtPosition(arg2);
- if (selection instanceof cgTrackable) {
- cgTrackable trackable = (cgTrackable) selection;
- cgeotrackable.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName());
+ if (selection instanceof Trackable) {
+ Trackable trackable = (Trackable) selection;
+ TrackableActivity.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName());
}
}
});
@@ -2486,23 +2280,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class ImagesViewCreator implements PageViewCreator {
-
- private View view;
-
- @Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = getDispatchedView();
- }
-
- return view;
- }
+ private class ImagesViewCreator extends AbstractCachingPageViewCreator<View> {
@Override
public View getDispatchedView() {
@@ -2511,7 +2289,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
view = getLayoutInflater().inflate(R.layout.caches_images, null);
- if (imagesList == null && viewPager.getCurrentItem() == pageOrder.indexOf(Page.IMAGES)) {
+ if (imagesList == null && isCurrentPage(Page.IMAGES)) {
loadCacheImages();
}
return view;
@@ -2520,15 +2298,240 @@ public class CacheDetailActivity extends AbstractActivity {
public static void startActivity(final Context context, final String geocode, final String cacheName) {
final Intent cachesIntent = new Intent(context, CacheDetailActivity.class);
- cachesIntent.putExtra("geocode", geocode);
- cachesIntent.putExtra("name", cacheName);
+ cachesIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
+ cachesIntent.putExtra(Intents.EXTRA_NAME, cacheName);
context.startActivity(cachesIntent);
}
public static void startActivityGuid(final Context context, final String guid, final String cacheName) {
final Intent cacheIntent = new Intent(context, CacheDetailActivity.class);
- cacheIntent.putExtra("guid", guid);
- cacheIntent.putExtra("name", cacheName);
+ cacheIntent.putExtra(Intents.EXTRA_GUID, guid);
+ cacheIntent.putExtra(Intents.EXTRA_NAME, cacheName);
context.startActivity(cacheIntent);
}
+
+ /**
+ * A dialog to allow the user to select reseting coordinates local/remote/both.
+ */
+ private AlertDialog createResetCacheCoordinatesDialog(final Geocache cache, final Waypoint wpt) {
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.waypoint_reset_cache_coords);
+
+ String[] items = new String[] {res.getString(R.string.waypoint_localy_reset_cache_coords), res.getString(R.string.waypoint_reset_local_and_remote_cache_coords)};
+ builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, final int which) {
+ dialog.dismiss();
+ final ProgressDialog progressDialog = ProgressDialog.show(CacheDetailActivity.this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
+ final HandlerResetCoordinates handler = new HandlerResetCoordinates(CacheDetailActivity.this, progressDialog, which == 1);
+ new ResetCoordsThread(cache, handler, wpt, which == 0 || which == 1, which == 1, progressDialog).start();
+ }
+ });
+ return builder.create();
+ }
+
+ private static class HandlerResetCoordinates extends WeakReferenceHandler<CacheDetailActivity> {
+ private boolean remoteFinished = false;
+ private boolean localFinished = false;
+ private final ProgressDialog progressDialog;
+ private final boolean resetRemote;
+
+ protected HandlerResetCoordinates(CacheDetailActivity activity, ProgressDialog progressDialog, boolean resetRemote) {
+ super(activity);
+ this.progressDialog = progressDialog;
+ this.resetRemote = resetRemote;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == ResetCoordsThread.LOCAL) {
+ localFinished = true;
+ } else {
+ remoteFinished = true;
+ }
+
+ if (localFinished && (remoteFinished || !resetRemote)) {
+ progressDialog.dismiss();
+ final CacheDetailActivity activity = getActivity();
+ if (activity != null) {
+ activity.notifyDataSetChanged();
+ }
+ }
+ }
+
+ }
+
+ private class ResetCoordsThread extends Thread {
+
+ private final Geocache cache;
+ private final Handler handler;
+ private final boolean local;
+ private final boolean remote;
+ private final Waypoint wpt;
+ private ProgressDialog progress;
+ public static final int LOCAL = 0;
+ public static final int ON_WEBSITE = 1;
+
+ public ResetCoordsThread(Geocache cache, Handler handler, final Waypoint wpt, boolean local, boolean remote, final ProgressDialog progress) {
+ this.cache = cache;
+ this.handler = handler;
+ this.local = local;
+ this.remote = remote;
+ this.wpt = wpt;
+ this.progress = progress;
+ }
+
+ @Override
+ public void run() {
+
+ if (local) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ progress.setMessage(res.getString(R.string.waypoint_reset_cache_coords));
+ }
+ });
+ cache.setCoords(wpt.getCoords());
+ cache.setUserModifiedCoords(false);
+ cache.deleteWaypointForce(wpt);
+ cgData.saveChangedCache(cache);
+ handler.sendEmptyMessage(LOCAL);
+ }
+
+ IConnector con = ConnectorFactory.getConnector(cache);
+ if (remote && con.supportsOwnCoordinates()) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ progress.setMessage(res.getString(R.string.waypoint_coordinates_being_reset_on_website));
+ }
+ });
+
+ final boolean result = con.deleteModifiedCoordinates(cache);
+
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (result) {
+ showToast(getString(R.string.waypoint_coordinates_has_been_reset_on_website));
+ } else {
+ showToast(getString(R.string.waypoint_coordinates_upload_error));
+ }
+ handler.sendEmptyMessage(ON_WEBSITE);
+ notifyDataSetChanged();
+ }
+
+ });
+
+ }
+ }
+ }
+
+ @Override
+ protected String getTitle(Page page) {
+ // show number of waypoints directly in waypoint title
+ if (page == Page.WAYPOINTS) {
+ final int waypointCount = cache.getWaypoints().size();
+ return res.getQuantityString(R.plurals.waypoints, waypointCount, waypointCount);
+ }
+ return res.getString(page.titleStringId);
+ }
+
+ @Override
+ protected Pair<List<? extends Page>, Integer> getOrderedPages() {
+ final ArrayList<Page> pages = new ArrayList<Page>();
+ pages.add(Page.WAYPOINTS);
+ pages.add(Page.DETAILS);
+ final int detailsIndex = pages.size() - 1;
+ pages.add(Page.DESCRIPTION);
+ if (!cache.getLogs().isEmpty()) {
+ pages.add(Page.LOGS);
+ }
+ if (CollectionUtils.isNotEmpty(cache.getFriendsLogs())) {
+ pages.add(Page.LOGSFRIENDS);
+ }
+ if (CollectionUtils.isNotEmpty(cache.getInventory())) {
+ pages.add(Page.INVENTORY);
+ }
+ if (CollectionUtils.isNotEmpty(cache.getImages())) {
+ pages.add(Page.IMAGES);
+ }
+ return new ImmutablePair<List<? extends Page>, Integer>(pages, detailsIndex);
+ }
+
+ @Override
+ protected AbstractViewPagerActivity.PageViewCreator createViewCreator(Page page) {
+ switch (page) {
+ case DETAILS:
+ return new DetailsViewCreator();
+
+ case DESCRIPTION:
+ return new DescriptionViewCreator();
+
+ case LOGS:
+ return new LogsViewCreator(true);
+
+ case LOGSFRIENDS:
+ return new LogsViewCreator(false);
+
+ case WAYPOINTS:
+ return new WaypointsViewCreator();
+
+ case INVENTORY:
+ return new InventoryViewCreator();
+
+ case IMAGES:
+ return new ImagesViewCreator();
+
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ static void updateOfflineBox(final View view, final Geocache cache, final Resources res,
+ final OnClickListener refreshCacheClickListener,
+ final OnClickListener dropCacheClickListener,
+ final OnClickListener storeCacheClickListener) {
+ // offline use
+ final TextView offlineText = (TextView) view.findViewById(R.id.offline_text);
+ final Button offlineRefresh = (Button) view.findViewById(R.id.offline_refresh);
+ final Button offlineStore = (Button) view.findViewById(R.id.offline_store);
+
+ if (cache.isOffline()) {
+ long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
+
+ String ago;
+ if (diff < 15) {
+ ago = res.getString(R.string.cache_offline_time_mins_few);
+ } else if (diff < 50) {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + diff + " " + res.getString(R.string.cache_offline_time_mins);
+ } else if (diff < 90) {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + res.getString(R.string.cache_offline_time_hour);
+ } else if (diff < (48 * 60)) {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / 60) + " " + res.getString(R.string.cache_offline_time_hours);
+ } else {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / (24 * 60)) + " " + res.getString(R.string.cache_offline_time_days);
+ }
+
+ offlineText.setText(res.getString(R.string.cache_offline_stored) + "\n" + ago);
+ offlineRefresh.setOnClickListener(refreshCacheClickListener);
+
+ offlineStore.setText(res.getString(R.string.cache_offline_drop));
+ offlineStore.setClickable(true);
+ offlineStore.setOnClickListener(dropCacheClickListener);
+ } else {
+ offlineText.setText(res.getString(R.string.cache_offline_not_ready));
+ offlineRefresh.setOnClickListener(refreshCacheClickListener);
+
+ offlineStore.setText(res.getString(R.string.cache_offline_store));
+ offlineStore.setClickable(true);
+ offlineStore.setOnClickListener(storeCacheClickListener);
+ }
+ offlineRefresh.setVisibility(cache.supportsRefresh() ? View.VISIBLE : View.GONE);
+ offlineRefresh.setClickable(true);
+ }
+
}