From 53bf82297323dc43ddb5eefc9a7e453a1013ab4a Mon Sep 17 00:00:00 2001 From: SammysHP Date: Mon, 25 Mar 2013 21:05:37 +0100 Subject: Remove unused translations --- main/res/values-cs/strings.xml | 2 -- 1 file changed, 2 deletions(-) (limited to 'main') diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index 5ea6fdd..caf0a17 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -409,7 +409,6 @@ Ukládat statické mapy k bodům trasy pro offline použití Ukládat obrázky z logů Používat imperiální jednotky vzdálenosti - Používat Google Navigaci Povolit Offline logování\n(Při logování nezobrazovat online logovací obrazovku a neodesílat Log na server) Ptát se na seznam pro uložení keše Zobrazovat směr v seznamu keší @@ -1062,7 +1061,6 @@ Facebook: Stránka c:geo Twitter: @android_GC Návod: c:geo v Nutshell - Služba Go 4 Cache zobrazuje ostatní geokačery na mapě (v c:geo nebo v prohlížeči) v reálném čase. Může zobrazovat - na příklad - jakou keš zrovna hledají. Připojením se k Go 4 Cache získá aplikace c:geo povolení zveřejňovat tvou polohu při geocachingu (pouze když je c:geo spuštěno). c:geo publikovat nový status na Twitteru vždy, když zaloguješ keš? Následující proces dovoluje aplikaci c:geo přístup na Twitter - pokud budeš souhlasit. Klepnutím na tlačítko \"Zahájit autorizaci\" bude proces zahájen. Tento proces otevře webový prohlížeč s Twitterem. Přihlaš se na této stránce a povol c:geu přístup k tvému účtu. Pokud je to povoleno, Twitter ti ukáže číselný PIN kód. Tento PIN kód musíš zadat do c:geo a potvrdit. To je vše. -- cgit v1.1 From d2500fe31f90a9aedcde5676f1b02da9f58e88ef Mon Sep 17 00:00:00 2001 From: Marco Jacob Date: Wed, 27 Mar 2013 20:48:27 +0100 Subject: more checks in static maps test --- main/src/cgeo/geocaching/StaticMapsProvider.java | 25 +++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index cd88071..8f89340 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -49,7 +49,7 @@ public class StaticMapsProvider { downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, edge, edge, waypoints); } - private static void downloadMap(String geocode, int zoom, String mapType, String markerUrl, String prefix, String shadow, String latlonMap, int width, int height, final Parameters waypoints) { + private static DownloadState downloadMap(String geocode, int zoom, String mapType, String markerUrl, String prefix, String shadow, String latlonMap, int width, int height, final Parameters waypoints) { final Parameters params = new Parameters( "center", latlonMap, "zoom", String.valueOf(zoom), @@ -64,11 +64,11 @@ public class StaticMapsProvider { if (httpResponse == null) { Log.e("StaticMapsProvider.downloadMap: httpResponse is null"); - return; + return DownloadState.REQUEST_FAILED; } if (httpResponse.getStatusLine().getStatusCode() != 200) { Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode()); - return; + return DownloadState.STATUS_CODE_NOK; } final File file = getMapFile(geocode, prefix, true); if (LocalStorage.saveEntityToFile(httpResponse, file)) { @@ -76,8 +76,11 @@ public class StaticMapsProvider { final long fileSize = file.length(); if (fileSize < MIN_MAP_IMAGE_BYTES) { file.delete(); + return DownloadState.FILE_TOO_SMALL; } + return DownloadState.OK; } + return DownloadState.NOT_SAVED; } public static void downloadMaps(Geocache cache) { @@ -166,10 +169,10 @@ public class StaticMapsProvider { downloadMaps(cache.getGeocode(), cacheMarkerUrl, "", latlonMap, edge, waypoints, waitForResult); } - public static void storeCachePreviewMap(final Geocache cache) { + public static DownloadState storeCachePreviewMap(final Geocache cache) { if (cache == null) { Log.e("storeCachePreviewMap - missing input parameter cache"); - return; + return DownloadState.FAILED; } final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); @@ -178,7 +181,8 @@ public class StaticMapsProvider { final int width = metrics.widthPixels; final int height = (int) (110 * metrics.density); final String markerUrl = MARKERS_URL + "my_location_mdpi.png"; - downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, width, height, null); + DownloadState state = downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, width, height, null); + return state; } private static int guessMaxDisplaySide() { @@ -245,7 +249,7 @@ public class StaticMapsProvider { /** * Check if at least one map file exists for the given cache. - * + * * @param cache * @return true if at least one map file exists; false otherwise */ @@ -268,7 +272,7 @@ public class StaticMapsProvider { /** * Checks if at least one map file exists for the given geocode and waypoint ID. - * + * * @param geocode * @param waypoint * @return true if at least one map file exists; false otherwise @@ -287,7 +291,7 @@ public class StaticMapsProvider { /** * Checks if all map files exist for the given geocode and waypoint ID. - * + * * @param geocode * @param waypoint * @return true if all map files exist; false otherwise @@ -327,4 +331,7 @@ public class StaticMapsProvider { return null; } + public enum DownloadState { + OK, REQUEST_FAILED, STATUS_CODE_NOK, FILE_TOO_SMALL, NOT_SAVED, FAILED + } } -- cgit v1.1 From 016ac19e28f8cd672f7b9f512fe9b55c766a08e0 Mon Sep 17 00:00:00 2001 From: Marco Jacob Date: Wed, 27 Mar 2013 21:03:42 +0100 Subject: remove StaticMapsProvider changes --- main/src/cgeo/geocaching/StaticMapsProvider.java | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 8f89340..69f5cc4 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -49,7 +49,7 @@ public class StaticMapsProvider { downloadMap(geocode, 11, ROADMAP, markerUrl, prefix + '5', "", latlonMap, edge, edge, waypoints); } - private static DownloadState downloadMap(String geocode, int zoom, String mapType, String markerUrl, String prefix, String shadow, String latlonMap, int width, int height, final Parameters waypoints) { + private static void downloadMap(String geocode, int zoom, String mapType, String markerUrl, String prefix, String shadow, String latlonMap, int width, int height, final Parameters waypoints) { final Parameters params = new Parameters( "center", latlonMap, "zoom", String.valueOf(zoom), @@ -64,11 +64,11 @@ public class StaticMapsProvider { if (httpResponse == null) { Log.e("StaticMapsProvider.downloadMap: httpResponse is null"); - return DownloadState.REQUEST_FAILED; + return; } if (httpResponse.getStatusLine().getStatusCode() != 200) { Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode()); - return DownloadState.STATUS_CODE_NOK; + return; } final File file = getMapFile(geocode, prefix, true); if (LocalStorage.saveEntityToFile(httpResponse, file)) { @@ -76,11 +76,11 @@ public class StaticMapsProvider { final long fileSize = file.length(); if (fileSize < MIN_MAP_IMAGE_BYTES) { file.delete(); - return DownloadState.FILE_TOO_SMALL; + return; } - return DownloadState.OK; + return; } - return DownloadState.NOT_SAVED; + return; } public static void downloadMaps(Geocache cache) { @@ -169,10 +169,10 @@ public class StaticMapsProvider { downloadMaps(cache.getGeocode(), cacheMarkerUrl, "", latlonMap, edge, waypoints, waitForResult); } - public static DownloadState storeCachePreviewMap(final Geocache cache) { + public static void storeCachePreviewMap(final Geocache cache) { if (cache == null) { Log.e("storeCachePreviewMap - missing input parameter cache"); - return DownloadState.FAILED; + return; } final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); @@ -181,8 +181,7 @@ public class StaticMapsProvider { final int width = metrics.widthPixels; final int height = (int) (110 * metrics.density); final String markerUrl = MARKERS_URL + "my_location_mdpi.png"; - DownloadState state = downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, width, height, null); - return state; + downloadMap(cache.getGeocode(), 15, ROADMAP, markerUrl, PREFIX_PREVIEW, "shadow:false|", latlonMap, width, height, null); } private static int guessMaxDisplaySide() { @@ -330,8 +329,4 @@ public class StaticMapsProvider { } return null; } - - public enum DownloadState { - OK, REQUEST_FAILED, STATUS_CODE_NOK, FILE_TOO_SMALL, NOT_SAVED, FAILED - } } -- cgit v1.1 From b3c74231b10ad15ed00b4107cf9f456c74978d51 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Thu, 28 Mar 2013 21:46:09 +0100 Subject: fix #2583: coordinates format switching for waypoints --- main/src/cgeo/geocaching/CacheDetailActivity.java | 20 ++---------- .../geocaching/ui/CoordinatesFormatSwitcher.java | 38 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 main/src/cgeo/geocaching/ui/CoordinatesFormatSwitcher.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 43ce65f..ea8794f 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -21,6 +21,7 @@ import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; import cgeo.geocaching.ui.CacheDetailsCreator; +import cgeo.geocaching.ui.CoordinatesFormatSwitcher; import cgeo.geocaching.ui.DecryptTextClickListener; import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.ui.ImagesList; @@ -1202,23 +1203,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity Date: Fri, 29 Mar 2013 10:02:08 +0100 Subject: #1798: refactoring, extract common asynctask with progress --- .../src/cgeo/geocaching/export/AbstractExport.java | 7 +- .../cgeo/geocaching/export/FieldnoteExport.java | 23 ++----- main/src/cgeo/geocaching/export/GpxExport.java | 25 ++----- .../geocaching/utils/AsyncTaskWithProgress.java | 80 ++++++++++++++++++++++ 4 files changed, 98 insertions(+), 37 deletions(-) create mode 100644 main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java (limited to 'main') diff --git a/main/src/cgeo/geocaching/export/AbstractExport.java b/main/src/cgeo/geocaching/export/AbstractExport.java index 72ea544..e4ba5f0 100644 --- a/main/src/cgeo/geocaching/export/AbstractExport.java +++ b/main/src/cgeo/geocaching/export/AbstractExport.java @@ -1,5 +1,6 @@ package cgeo.geocaching.export; +import cgeo.geocaching.R; import cgeo.geocaching.cgeoapplication; abstract class AbstractExport implements Export { @@ -27,7 +28,7 @@ abstract class AbstractExport implements Export { /** * Generates a localized string from a resource id. - * + * * @param resourceId * the resource id of the string * @param params @@ -43,4 +44,8 @@ abstract class AbstractExport implements Export { // used in the array adapter of the dialog showing the exports return getName(); } + + protected String getProgressTitle() { + return getString(R.string.export) + ": " + getName(); + } } diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java index 5e1805a..eadcb77 100644 --- a/main/src/cgeo/geocaching/export/FieldnoteExport.java +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -5,11 +5,11 @@ import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.cgData; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.activity.Progress; import cgeo.geocaching.connector.gc.Login; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; +import cgeo.geocaching.utils.AsyncTaskWithProgress; import cgeo.geocaching.utils.IOUtils; import cgeo.geocaching.utils.Log; @@ -20,7 +20,6 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; -import android.os.AsyncTask; import android.os.Environment; import android.view.ContextThemeWrapper; import android.view.View; @@ -102,18 +101,17 @@ class FieldnoteExport extends AbstractExport { return builder.create(); } - private class ExportTask extends AsyncTask { + private class ExportTask extends AsyncTaskWithProgress { private final List caches; private final Activity activity; private final boolean upload; private final boolean onlyNew; - private final Progress progress = new Progress(); private File exportFile; private static final int STATUS_UPLOAD = -1; /** - * Instantiates and configurates the task for exporting field notes. + * Instantiates and configures the task for exporting field notes. * * @param caches * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported @@ -125,6 +123,7 @@ class FieldnoteExport extends AbstractExport { * Upload/export only new logs since last export */ public ExportTask(final List caches, final Activity activity, final boolean upload, final boolean onlyNew) { + super(activity, getProgressTitle(), getString(R.string.export_fieldnotes_creating)); this.caches = caches; this.activity = activity; this.upload = upload; @@ -132,13 +131,6 @@ class FieldnoteExport extends AbstractExport { } @Override - protected void onPreExecute() { - if (null != activity) { - progress.show(activity, getString(R.string.export) + ": " + getName(), getString(R.string.export_fieldnotes_creating), true, null); - } - } - - @Override protected Boolean doInBackground(Void... params) { final StringBuilder fieldNoteBuffer = new StringBuilder(); try { @@ -228,9 +220,8 @@ class FieldnoteExport extends AbstractExport { @Override protected void onPostExecute(Boolean result) { + super.onPostExecute(result); if (null != activity) { - progress.dismiss(); - if (result) { // if (onlyNew) { // // update last export time in settings when doing it ourself (currently we use the date check from gc.com) @@ -251,9 +242,9 @@ class FieldnoteExport extends AbstractExport { protected void onProgressUpdate(Integer... status) { if (null != activity) { if (STATUS_UPLOAD == status[0]) { - progress.setMessage(getString(R.string.export_fieldnotes_uploading)); + setMessage(getString(R.string.export_fieldnotes_uploading)); } else { - progress.setMessage(getString(R.string.export_fieldnotes_creating) + " (" + status[0] + ')'); + setMessage(getString(R.string.export_fieldnotes_creating) + " (" + status[0] + ')'); } } } diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index c4060fe..0ae9037 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -6,11 +6,12 @@ import cgeo.geocaching.R; import cgeo.geocaching.Settings; import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgData; +import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.activity.ActivityMixin; -import cgeo.geocaching.activity.Progress; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.utils.AsyncTaskWithProgress; import cgeo.geocaching.utils.BaseUtils; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.XmlUtils; @@ -21,11 +22,9 @@ import org.xmlpull.v1.XmlSerializer; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; -import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; -import android.os.AsyncTask; import android.os.Environment; import android.util.Xml; import android.view.ContextThemeWrapper; @@ -98,10 +97,9 @@ class GpxExport extends AbstractExport { return builder.create(); } - private class ExportTask extends AsyncTask { + private class ExportTask extends AsyncTaskWithProgress { private final List caches; private final Activity activity; - private final Progress progress = new Progress(); /** * Instantiates and configures the task for exporting field notes. @@ -112,19 +110,12 @@ class GpxExport extends AbstractExport { * optional: Show a progress bar and toasts */ public ExportTask(final List caches, final Activity activity) { + super(activity, caches.size(), getProgressTitle(), cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, caches.size(), caches.size())); this.caches = caches; this.activity = activity; } @Override - protected void onPreExecute() { - if (null != activity) { - progress.show(activity, null, getString(R.string.export) + ": " + getName(), ProgressDialog.STYLE_HORIZONTAL, null); - progress.setMaxProgressAndReset(caches.size()); - } - } - - @Override protected File doInBackground(Void... params) { // quick check for being able to write the GPX file if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { @@ -344,8 +335,8 @@ class GpxExport extends AbstractExport { @Override protected void onPostExecute(final File exportFile) { + super.onPostExecute(exportFile); if (null != activity) { - progress.dismiss(); if (exportFile != null) { ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString()); if (Settings.getShareAfterExport()) { @@ -361,11 +352,5 @@ class GpxExport extends AbstractExport { } } - @Override - protected void onProgressUpdate(Integer... status) { - if (null != activity) { - progress.setProgress(status[0]); - } - } } } diff --git a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java new file mode 100644 index 0000000..b23fa9d --- /dev/null +++ b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java @@ -0,0 +1,80 @@ +package cgeo.geocaching.utils; + +import cgeo.geocaching.activity.Progress; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.os.AsyncTask; + +/** + * AsyncTask which automatically shows a progress dialog. Use it like the {@code AsyncTask} class, but leave away the + * middle template parameter. + * + * @param + * @param + */ +public abstract class AsyncTaskWithProgress extends AsyncTask { + + private final Progress progress = new Progress(); + private final Activity activity; + private final int maxProgress; + private final String progressTitle; + private final String progressMessage; + + /** + * Creates an AsyncTask with progress dialog, where the maximum is set to the given maxProgress. + * + * @param activity + * @param maxProgress + * @param progressTitle + * @param progressMessage + */ + public AsyncTaskWithProgress(final Activity activity, final int maxProgress, final String progressTitle, final String progressMessage) { + this.activity = activity; + this.maxProgress = maxProgress; + this.progressTitle = progressTitle; + this.progressMessage = progressMessage; + } + + /** + * Creates an AsyncTask with progress dialog, where the maximum is set to indeterminate. + * + * @param activity + * @param progressTitle + * @param progressMessage + */ + public AsyncTaskWithProgress(final Activity activity, final String progressTitle, final String progressMessage) { + this(activity, 0, progressTitle, progressMessage); + } + + @Override + protected void onPreExecute() { + if (null != activity) { + if (maxProgress <= 0) { + progress.show(activity, progressTitle, progressMessage, true, null); + } + else { + progress.show(activity, progressTitle, progressMessage, ProgressDialog.STYLE_HORIZONTAL, null); + } + progress.setMaxProgressAndReset(maxProgress); + } + } + + @Override + protected void onPostExecute(Result result) { + if (null != activity) { + progress.dismiss(); + } + } + + @Override + protected void onProgressUpdate(Integer... status) { + if (null != activity) { + progress.setProgress(status[0]); + } + } + + protected void setMessage(final String message) { + progress.setMessage(message); + } +} -- cgit v1.1 From 163cd60d56714f853790a89918e0a2804d1e5b47 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Fri, 29 Mar 2013 19:48:29 +0100 Subject: refactoring: improve performance of GPX export * load batches of caches instead of single caches * do not load all caches to avoid huge memory usage --- main/src/cgeo/geocaching/export/GpxExport.java | 146 +++++++++++++++---------- 1 file changed, 88 insertions(+), 58 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index 36c8ca7..19b8518 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -38,8 +38,11 @@ import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Set; class GpxExport extends AbstractExport { private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); @@ -47,6 +50,11 @@ class GpxExport extends AbstractExport { public static final String PREFIX_GPX = "http://www.topografix.com/GPX/1/0"; public static final String PREFIX_GROUNDSPEAK = "http://www.groundspeak.com/cache/1/0"; + /** + * During the export, only this number of geocaches is fully loaded into memory. + */ + public static final int CACHES_PER_BATCH = 100; + protected GpxExport() { super(getString(R.string.export_gpx)); } @@ -98,8 +106,9 @@ class GpxExport extends AbstractExport { } private class ExportTask extends AsyncTaskWithProgress { - private final List caches; + private final Set allGeocodes = new HashSet(); private final Activity activity; + private int countExported = 0; /** * Instantiates and configures the task for exporting field notes. @@ -111,7 +120,11 @@ class GpxExport extends AbstractExport { */ public ExportTask(final List caches, final Activity activity) { super(activity, caches.size(), getProgressTitle(), cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, caches.size(), caches.size())); - this.caches = caches; + + // get rid of the (half loaded) caches, we will reload them as full caches during the export + for (Geocache geocache : caches) { + allGeocodes.add(geocache.getGeocode()); + } this.activity = activity; } @@ -144,68 +157,24 @@ class GpxExport extends AbstractExport { PREFIX_GPX + " http://www.topografix.com/GPX/1/0/gpx.xsd " + PREFIX_GROUNDSPEAK + " http://www.groundspeak.com/cache/1/0/1/cache.xsd"); - for (int i = 0; i < caches.size(); i++) { - final Geocache cache = cgData.loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY); + // Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because + // we don't load all caches fully into memory) and speed (because we don't query each cache separately). - gpx.startTag(PREFIX_GPX, "wpt"); - gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude())); - gpx.attribute("", "lon", Double.toString(cache.getCoords().getLongitude())); - - final Date hiddenDate = cache.getHiddenDate(); - if (hiddenDate != null) { - XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate)); + while (!allGeocodes.isEmpty()) { + int cachesInBatch = 0; + HashSet geocodesOfBatch = new HashSet(CACHES_PER_BATCH); + for (Iterator iterator = allGeocodes.iterator(); iterator.hasNext() && cachesInBatch < CACHES_PER_BATCH;) { + final String geocode = iterator.next(); + geocodesOfBatch.add(geocode); + cachesInBatch++; } - - XmlUtils.multipleTexts(gpx, PREFIX_GPX, - "name", cache.getGeocode(), - "desc", cache.getName(), - "url", cache.getUrl(), - "urlname", cache.getName(), - "sym", cache.isFound() ? "Geocache Found" : "Geocache", - "type", "Geocache|" + cache.getType().pattern); - - gpx.startTag(PREFIX_GROUNDSPEAK, "cache"); - gpx.attribute("", "id", cache.getCacheId()); - gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False"); - gpx.attribute("", "archives", cache.isArchived() ? "True" : "False"); - - XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK, - "name", cache.getName(), - "placed_by", cache.getOwnerDisplayName(), - "owner", cache.getOwnerUserId(), - "type", cache.getType().pattern, - "container", cache.getSize().id, - "difficulty", Float.toString(cache.getDifficulty()), - "terrain", Float.toString(cache.getTerrain()), - "country", cache.getLocation(), - "state", "", - "encoded_hints", cache.getHint()); - - writeAttributes(gpx, cache); - - gpx.startTag(PREFIX_GROUNDSPEAK, "short_description"); - gpx.attribute("", "html", BaseUtils.containsHtml(cache.getShortDescription()) ? "True" : "False"); - gpx.text(cache.getShortDescription()); - gpx.endTag(PREFIX_GROUNDSPEAK, "short_description"); - - gpx.startTag(PREFIX_GROUNDSPEAK, "long_description"); - gpx.attribute("", "html", BaseUtils.containsHtml(cache.getDescription()) ? "True" : "False"); - gpx.text(cache.getDescription()); - gpx.endTag(PREFIX_GROUNDSPEAK, "long_description"); - - writeLogs(gpx, cache); - - gpx.endTag(PREFIX_GROUNDSPEAK, "cache"); - gpx.endTag(PREFIX_GPX, "wpt"); - - writeWaypoints(gpx, cache); - - publishProgress(i + 1); + allGeocodes.removeAll(geocodesOfBatch); + exportBatch(gpx, geocodesOfBatch); } gpx.endTag(PREFIX_GPX, "gpx"); gpx.endDocument(); - } catch (final IOException e) { + } catch (final Exception e) { Log.e("GpxExport.ExportTask export", e); if (writer != null) { @@ -226,6 +195,67 @@ class GpxExport extends AbstractExport { return exportFile; } + private void exportBatch(final XmlSerializer gpx, HashSet geocodesOfBatch) throws IOException { + Set caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY); + for (Geocache cache : caches) { + gpx.startTag(PREFIX_GPX, "wpt"); + gpx.attribute("", "lat", Double.toString(cache.getCoords().getLatitude())); + gpx.attribute("", "lon", Double.toString(cache.getCoords().getLongitude())); + + final Date hiddenDate = cache.getHiddenDate(); + if (hiddenDate != null) { + XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate)); + } + + XmlUtils.multipleTexts(gpx, PREFIX_GPX, + "name", cache.getGeocode(), + "desc", cache.getName(), + "url", cache.getUrl(), + "urlname", cache.getName(), + "sym", cache.isFound() ? "Geocache Found" : "Geocache", + "type", "Geocache|" + cache.getType().pattern); + + gpx.startTag(PREFIX_GROUNDSPEAK, "cache"); + gpx.attribute("", "id", cache.getCacheId()); + gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False"); + gpx.attribute("", "archives", cache.isArchived() ? "True" : "False"); + + XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK, + "name", cache.getName(), + "placed_by", cache.getOwnerDisplayName(), + "owner", cache.getOwnerUserId(), + "type", cache.getType().pattern, + "container", cache.getSize().id, + "difficulty", Float.toString(cache.getDifficulty()), + "terrain", Float.toString(cache.getTerrain()), + "country", cache.getLocation(), + "state", "", + "encoded_hints", cache.getHint()); + + writeAttributes(gpx, cache); + + gpx.startTag(PREFIX_GROUNDSPEAK, "short_description"); + gpx.attribute("", "html", BaseUtils.containsHtml(cache.getShortDescription()) ? "True" : "False"); + gpx.text(cache.getShortDescription()); + gpx.endTag(PREFIX_GROUNDSPEAK, "short_description"); + + gpx.startTag(PREFIX_GROUNDSPEAK, "long_description"); + gpx.attribute("", "html", BaseUtils.containsHtml(cache.getDescription()) ? "True" : "False"); + gpx.text(cache.getDescription()); + gpx.endTag(PREFIX_GROUNDSPEAK, "long_description"); + + writeLogs(gpx, cache); + + gpx.endTag(PREFIX_GROUNDSPEAK, "cache"); + gpx.endTag(PREFIX_GPX, "wpt"); + + writeWaypoints(gpx, cache); + + countExported++; + publishProgress(countExported); + } + } + private void writeWaypoints(final XmlSerializer gpx, final Geocache cache) throws IOException { List waypoints = cache.getWaypoints(); List ownWaypoints = new ArrayList(waypoints.size()); -- cgit v1.1 From bd66d5eeb4ea95325630dae58aaf7f1043085781 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 30 Mar 2013 09:26:49 +0100 Subject: #2613: log error if image cannot be decoded --- main/src/cgeo/geocaching/network/HtmlImage.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index a409750..b08d36d 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -193,7 +193,11 @@ public class HtmlImage implements Html.ImageGetter { if (file.exists()) { if (listId >= StoredList.STANDARD_LIST_ID || file.lastModified() > (new Date().getTime() - (24 * 60 * 60 * 1000)) || forceKeep) { setSampleSize(file); - return BitmapFactory.decodeFile(file.getPath(), bfOptions); + final Bitmap image = BitmapFactory.decodeFile(file.getPath(), bfOptions); + if (image == null) { + Log.e("Cannot decode bitmap from " + file.getPath()); + } + return image; } } return null; -- cgit v1.1 From 32460d132a0906fd39e92c1ce1c5088920ddf23c Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 30 Mar 2013 20:21:01 +0100 Subject: refactoring of cache logging code * simplify control flow * move sanity checks into GCVote and twitter methods --- main/src/cgeo/geocaching/VisitCacheActivity.java | 32 ++++++++-------------- .../src/cgeo/geocaching/connector/gc/GCParser.java | 5 ++++ main/src/cgeo/geocaching/gcvote/GCVote.java | 7 +++-- main/src/cgeo/geocaching/twitter/Twitter.java | 6 ++++ 4 files changed, 28 insertions(+), 22 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index d95f6df..8f47606 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -571,18 +571,16 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } public StatusCode postLogFn(String log) { - StatusCode result = StatusCode.LOG_POST_ERROR; try { - final ImmutablePair logResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, + final ImmutablePair postResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log, trackables); + result = postResult.left; - result = logResult.left; - - if (logResult.left == StatusCode.NO_ERROR) { + if (result == StatusCode.NO_ERROR) { final LogEntry logNow = new LogEntry(date, typeSelected, log); cache.getLogs().add(0, logNow); @@ -592,24 +590,18 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } cgData.saveChangedCache(cache); - } - - if (logResult.left == StatusCode.NO_ERROR) { cgData.clearLogOffline(geocode); - } - if (logResult.left == StatusCode.NO_ERROR && typeSelected == LogType.FOUND_IT && Settings.isUseTwitter() - && Settings.isTwitterLoginValid() - && tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) { - Twitter.postTweetCache(geocode); - } - - if (logResult.left == StatusCode.NO_ERROR && typeSelected == LogType.FOUND_IT && Settings.isGCvoteLogin()) { - GCVote.setRating(cache, rating); - } + if (typeSelected == LogType.FOUND_IT) { + if (tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) { + Twitter.postTweetCache(geocode); + } + GCVote.setRating(cache, rating); + } - if (logResult.left == StatusCode.NO_ERROR && StringUtils.isNotBlank(imageUri.getPath())) { - result = GCParser.uploadLogImage(logResult.right, imageCaption, imageDescription, imageUri); + if (StringUtils.isNotBlank(imageUri.getPath())) { + result = GCParser.uploadLogImage(postResult.right, imageCaption, imageDescription, imageUri); + } } return result; diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 9af9953..76351c1 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -1100,6 +1100,11 @@ public abstract class GCParser { return StatusCode.LOGIMAGE_POST_ERROR; } + /** + * Post a log to GC.com. + * + * @return status code of the upload and ID of the log + */ public static StatusCode postLogTrackable(final String tbid, final String trackingCode, final String[] viewstates, final LogType logType, final int year, final int month, final int day, final String log) { if (Login.isEmpty(viewstates)) { diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java index a053f31..f6cfb84 100644 --- a/main/src/cgeo/geocaching/gcvote/GCVote.java +++ b/main/src/cgeo/geocaching/gcvote/GCVote.java @@ -173,12 +173,15 @@ public final class GCVote { /** * Transmit user vote to gcvote.com - * + * * @param cache * @param vote - * @return + * @return {@code true} if the rating was submitted successfully */ public static boolean setRating(Geocache cache, double vote) { + if (!Settings.isGCvoteLogin()) { + return false; + } if (!cache.supportsGCVote()) { return false; } diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index f30830e..d3b2718 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -56,6 +56,12 @@ public final class Twitter { } public static void postTweetCache(String geocode) { + if (!Settings.isUseTwitter()) { + return; + } + if (!Settings.isTwitterLoginValid()) { + return; + } final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); String status; final String url = cache.getUrl(); -- cgit v1.1 From e70deaf2c8a5ffbee0bfdd4caea78c7e795f287b Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 30 Mar 2013 21:31:11 +0100 Subject: fix #2532: attach log image to log entry locally --- main/src/cgeo/geocaching/VisitCacheActivity.java | 8 +++++++- main/src/cgeo/geocaching/connector/gc/GCConstants.java | 2 +- main/src/cgeo/geocaching/connector/gc/GCParser.java | 14 +++++++------- 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index 8f47606..b4eb82a 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -600,7 +600,13 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } if (StringUtils.isNotBlank(imageUri.getPath())) { - result = GCParser.uploadLogImage(postResult.right, imageCaption, imageDescription, imageUri); + ImmutablePair imageResult = GCParser.uploadLogImage(postResult.right, imageCaption, imageDescription, imageUri); + final String uploadedImageUrl = imageResult.right; + if (StringUtils.isNotEmpty(uploadedImageUrl)) { + logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription)); + cgData.saveChangedCache(cache); + } + result = imageResult.left; } } diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java index 4d27617..d8711cf 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java +++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java @@ -149,7 +149,7 @@ public final class GCConstants { public final static Pattern PATTERN_MAINTENANCE = Pattern.compile("]*>([^<]*]*>)?([^<]+)([^<]*)?", Pattern.CASE_INSENSITIVE); public final static Pattern PATTERN_OK1 = Pattern.compile("]*>[^<]*]*>[^<]*[^<]*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_OK2 = Pattern.compile("
", Pattern.CASE_INSENSITIVE); - public final static Pattern PATTERN_OK_IMAGEUPLOAD = Pattern.compile("
", Pattern.CASE_INSENSITIVE); + public final static Pattern PATTERN_IMAGE_UPLOAD_URL = Pattern.compile("title=\"Click for Larger Image\"\\s*src=\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_VIEWSTATEFIELDCOUNT = Pattern.compile("id=\"__VIEWSTATEFIELDCOUNT\"[^(value)]+value=\"(\\d+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_VIEWSTATES = Pattern.compile("id=\"__VIEWSTATE(\\d*)\"[^(value)]+value=\"([^\"]+)\"[^>]+>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); public final static Pattern PATTERN_USERTOKEN = Pattern.compile("userToken\\s*=\\s*'([^']+)'"); diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 76351c1..4b5d7b9 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -1059,7 +1059,7 @@ public abstract class GCParser { * the URI for the image to be uploaded * @return status code to indicate success or failure */ - public static StatusCode uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) { + public static ImmutablePair uploadLogImage(final String logId, final String caption, final String description, final Uri imageUri) { final String uri = new Uri.Builder().scheme("http").authority("www.geocaching.com").path("/seek/upload.aspx").encodedQuery("LID=" + logId).build().toString(); String page = Network.getResponseData(Network.getRequest(uri)); @@ -1071,7 +1071,7 @@ public abstract class GCParser { page = Network.getResponseData(Network.getRequest(uri)); } else { Log.e("Image upload: No login (error: " + loginState + ')'); - return StatusCode.NOT_LOGGED_IN; + return ImmutablePair.of(StatusCode.NOT_LOGGED_IN, null); } } @@ -1088,16 +1088,16 @@ public abstract class GCParser { final File image = new File(imageUri.getPath()); final String response = Network.getResponseData(Network.postRequest(uri, uploadParams, "ctl00$ContentBody$ImageUploadControl1$uxFileUpload", "image/jpeg", image)); - MatcherWrapper matcherOK = new MatcherWrapper(GCConstants.PATTERN_OK_IMAGEUPLOAD, response); + MatcherWrapper matcherUrl = new MatcherWrapper(GCConstants.PATTERN_IMAGE_UPLOAD_URL, response); - if (matcherOK.find()) { + if (matcherUrl.find()) { Log.i("Logimage successfully uploaded."); - - return StatusCode.NO_ERROR; + final String uploadedImageUrl = matcherUrl.group(1); + return ImmutablePair.of(StatusCode.NO_ERROR, uploadedImageUrl); } Log.e("GCParser.uploadLogIMage: Failed to upload image because of unknown error"); - return StatusCode.LOGIMAGE_POST_ERROR; + return ImmutablePair.of(StatusCode.LOGIMAGE_POST_ERROR, null); } /** -- cgit v1.1 From ce094d31c0b234648cf38d1fa8d360cfed37a4f7 Mon Sep 17 00:00:00 2001 From: TriakCZ Date: Sun, 31 Mar 2013 20:40:16 +0200 Subject: Displaying distance to waypoint on map popup --- main/src/cgeo/geocaching/AbstractPopupActivity.java | 5 +++++ main/src/cgeo/geocaching/WaypointPopup.java | 12 ++++++++++++ .../src/cgeo/geocaching/ui/CacheDetailsCreator.java | 21 +++++++++++++++++++++ 3 files changed, 38 insertions(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java index f903d00..a7d1107 100644 --- a/main/src/cgeo/geocaching/AbstractPopupActivity.java +++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java @@ -67,12 +67,17 @@ public abstract class AbstractPopupActivity extends AbstractActivity { cacheDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(cache.getCoords()))); cacheDistance.bringToFront(); } + onUpdateGeoData(geo); } catch (Exception e) { Log.w("Failed to UpdateLocation location."); } } }; + public void onUpdateGeoData(final IGeoData geo) { + + } + protected AbstractPopupActivity(String helpTopic, int layout) { super(helpTopic); this.layout = layout; diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java index 766d43d..9ccad48 100644 --- a/main/src/cgeo/geocaching/WaypointPopup.java +++ b/main/src/cgeo/geocaching/WaypointPopup.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.geopoint.Units; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.utils.Log; @@ -19,6 +20,7 @@ import android.widget.TextView; public class WaypointPopup extends AbstractPopupActivity { private int waypointId = 0; private Waypoint waypoint = null; + private TextView waypointDistance = null; public WaypointPopup() { super("c:geo-waypoint-info", R.layout.waypoint_popup); @@ -35,6 +37,14 @@ public class WaypointPopup extends AbstractPopupActivity { } @Override + public void onUpdateGeoData(IGeoData geo) { + if (geo.getCoords() != null && waypoint != null && waypoint.getCoords() != null) { + waypointDistance.setText(Units.getDistanceFromKilometers(geo.getCoords().distanceTo(waypoint.getCoords()))); + waypointDistance.bringToFront(); + } + } + + @Override protected void init() { super.init(); waypoint = cgData.loadWaypoint(waypointId); @@ -53,6 +63,8 @@ public class WaypointPopup extends AbstractPopupActivity { //Waypoint geocode details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2)); + details.addDistance(waypoint, waypointDistance); + waypointDistance = details.getValueView(); // Edit Button final Button buttonEdit = (Button) findViewById(R.id.edit); diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java index e98bd77..80f01e2 100644 --- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java +++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java @@ -2,6 +2,7 @@ package cgeo.geocaching.ui; import cgeo.geocaching.Geocache; import cgeo.geocaching.R; +import cgeo.geocaching.Waypoint; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.geopoint.Geopoint; import cgeo.geocaching.geopoint.Units; @@ -154,4 +155,24 @@ public final class CacheDetailsCreator { } add(R.string.cache_distance, text); } + + public void addDistance(final Waypoint wpt, final TextView waypointDistanceView) { + Float distance = null; + if (wpt.getCoords() != null) { + final Geopoint currentCoords = cgeoapplication.getInstance().currentGeo().getCoords(); + if (currentCoords != null) { + distance = currentCoords.distanceTo(wpt); + } + } + String text = "--"; + if (distance != null) { + text = Units.getDistanceFromKilometers(distance); + } + else if (waypointDistanceView != null) { + // if there is already a distance in waypointDistance, use it instead of resetting to default. + // this prevents displaying "--" while waiting for a new position update (See bug #1468) + text = waypointDistanceView.getText().toString(); + } + add(R.string.cache_distance, text); + } } -- cgit v1.1 From 9a36d2207c8ef09f4294b638685280bd6f4de719 Mon Sep 17 00:00:00 2001 From: TriakCZ Date: Sun, 31 Mar 2013 20:44:48 +0200 Subject: Displaying note of waypoint on wpt popup --- main/src/cgeo/geocaching/WaypointPopup.java | 1 + 1 file changed, 1 insertion(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java index 9ccad48..43a758f 100644 --- a/main/src/cgeo/geocaching/WaypointPopup.java +++ b/main/src/cgeo/geocaching/WaypointPopup.java @@ -65,6 +65,7 @@ public class WaypointPopup extends AbstractPopupActivity { details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2)); details.addDistance(waypoint, waypointDistance); waypointDistance = details.getValueView(); + details.add(R.string.waypoint_note, waypoint.getNote()); // Edit Button final Button buttonEdit = (Button) findViewById(R.id.edit); -- cgit v1.1 From e9b425637d12d682c365ec511d68f2f79538e0c7 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 1 Apr 2013 19:36:13 +0200 Subject: fix #2619: Clicking link in log decrypts log --- main/src/cgeo/geocaching/ui/DecryptTextClickListener.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java index 4ba88ae..f10e13a 100644 --- a/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java +++ b/main/src/cgeo/geocaching/ui/DecryptTextClickListener.java @@ -16,6 +16,12 @@ public class DecryptTextClickListener implements View.OnClickListener { try { final TextView logView = (TextView) view; + + // do not run the click listener if a link was clicked + if (logView.getSelectionStart() != -1 || logView.getSelectionEnd() != -1) { + return; + } + CharSequence text = logView.getText(); if (text instanceof Spannable) { Spannable span = (Spannable) text; -- cgit v1.1 From e703540659c2ba6480583d9819d96120d7b95a06 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 1 Apr 2013 20:13:10 +0200 Subject: improve display of log texts for OC * remove even more unneeded whitespace --- .../geocaching/connector/oc/OC11XMLParser.java | 26 ++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java index 621032f..d03062f 100644 --- a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java +++ b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java @@ -48,6 +48,8 @@ public class OC11XMLParser { private static Pattern LOCAL_URL = Pattern.compile("href=\"(.*)\""); private static final int CACHE_PARSE_LIMIT = 250; private static final Resources res = cgeoapplication.getInstance().getResources(); + private static final Pattern WHITESPACE = Pattern.compile("

(\\s| )*

"); + private static ImageHolder imageHolder = null; @@ -513,7 +515,7 @@ public class OC11XMLParser { @Override public void end(String body) { final String content = body.trim(); - descHolder.shortDesc = linkify(stripMarkup(content)); + descHolder.shortDesc = linkify(stripEmptyText(content)); } }); @@ -523,7 +525,7 @@ public class OC11XMLParser { @Override public void end(String body) { final String content = body.trim(); - descHolder.desc = linkify(stripMarkup(content)); + descHolder.desc = linkify(stripEmptyText(content)); } }); @@ -626,7 +628,7 @@ public class OC11XMLParser { @Override public void end(String logText) { - logHolder.logEntry.log = stripMarkup(logText); + logHolder.logEntry.log = stripEmptyText(logText); } }); @@ -728,14 +730,20 @@ public class OC11XMLParser { } /** - * Removes unneeded markup. Log texts are typically encapsulated in paragraph tags which lead to more empty space on - * rendering. + * Removes some unneeded markup and whitespace. Log texts are typically encapsulated in paragraph tags which lead to + * more empty space on rendering. */ - protected static String stripMarkup(String input) { - if (!StringUtils.startsWith(input, "<")) { - return input; + protected static String stripEmptyText(String input) { + final Matcher matcher = WHITESPACE.matcher(input); + String result = matcher.replaceAll("").trim(); + if (!StringUtils.startsWith(result, "<")) { + return result; } - String result = input.trim(); + return stripMarkup(result); + } + + private static String stripMarkup(final String input) { + String result = input; for (String tagName : MARKUP) { final String startTag = "<" + tagName + ">"; if (StringUtils.startsWith(result, startTag)) { -- cgit v1.1 From 1f98bf8a77a25510aefdf4219814d9a432f04810 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 1 Apr 2013 22:19:48 +0300 Subject: Change log reset (master only) --- main/res/values/strings_not_translatable.xml | 33 +++++----------------------- 1 file changed, 6 insertions(+), 27 deletions(-) (limited to 'main') diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml index b082e39..8de1483 100644 --- a/main/res/values/strings_not_translatable.xml +++ b/main/res/values/strings_not_translatable.xml @@ -82,36 +82,15 @@ \n Next release\n\n New Features/Functions:\n - · Support of attaching pictures to logs\n - · Support of opencaching.de online API in live map and nearby search\n - · Support for searching opencaching.nl caches\n - · Alphabetical sorting of OSM:Offline maps in map selection\n - · Color markers also in trackable logbook\n - · Edit cache type filter by clicking on filter bar\n - · Inverse sorting of cache lists (hit the same menu again)\n - · View pager for trackable activity\n - · Menu item to delete past events\n - · Settings: Option to ask for list to store caches\n - · Change list in cache details\n - · Ability to select \"All\" list from main screen\n - · Default log type for event caches will be \"Attended\" if \"Will attend\" was logged before\n - · Improved and extended cache type detection on live map\n - · Waypoints can be marked as visited\n - · Possibility to delete offline logs in lists\n - · Support of language specific characters in log text equally to the website\n + · ...\n \n Bugfixing:\n - · Final flag icon lost when updating cache with self defined final\n - · Bad selection in directory chooser\n - · Log type \"Retract Listing\" now parsed correctly\n - · Active cache detail page now remembered when rotating device\n - · Replaced the term \"GC-Code\" by \"Geocode\"\n - · Improvements for light theme\n - · Share function uses short URL again\n - · Offline log marker now shown after autosave of log\n - · GPX export no longer exports waypoints without coordinates\n + · Do not apply encryption/decryption when clicking on a link in a log\n + · Also show a picture attached to a log locally after sending the log\n + · Improved display of log text for OC-caches\n + · Improved performance of GPX exports\n \n - Detailed list of all changes\n + Detailed list of all changes\n \n Known Limitations/Bugs:\n · Live map:\n -- cgit v1.1 From 05e241cd5741c5c5baec64c7c3fbdb7e2c07844d Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Tue, 2 Apr 2013 22:18:06 +0200 Subject: #556: refactor to prepare customization of twitter text --- main/src/cgeo/geocaching/twitter/Twitter.java | 60 ++++++++++++++------------- 1 file changed, 31 insertions(+), 29 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index d3b2718..6b427e0 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -15,7 +15,10 @@ import cgeo.geocaching.utils.Log; import ch.boye.httpclientandroidlib.HttpResponse; +import org.apache.commons.lang3.StringUtils; + public final class Twitter { + private static final String HASH_PREFIX_WITH_BLANK = " #"; public static final int MAX_TWEET_SIZE = 140; public static void postTweet(final cgeoapplication app, final String status, final Geopoint coords) { @@ -47,12 +50,10 @@ public final class Twitter { } } - public static String appendHashTag(final String status, final String tag) { - String result = status; - if (result.length() + 2 + tag.length() <= 140) { - result += " #" + tag; + public static void appendHashTag(final StringBuilder status, final String tag) { + if (status.length() + HASH_PREFIX_WITH_BLANK.length() + tag.length() <= MAX_TWEET_SIZE) { + status.append(HASH_PREFIX_WITH_BLANK).append(tag); } - return result; } public static void postTweetCache(String geocode) { @@ -63,39 +64,40 @@ public final class Twitter { return; } final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB); - String status; - final String url = cache.getUrl(); - if (url.length() >= 100) { - status = "I found " + url; - } - else { - String name = cache.getName(); - status = "I found " + name + " (" + url + ")"; - if (status.length() > MAX_TWEET_SIZE) { - name = name.substring(0, name.length() - (status.length() - MAX_TWEET_SIZE) - 1) + '…'; + postTweet(cgeoapplication.getInstance(), getStatusMessage(cache), null); + } + + static String getStatusMessage(Geocache cache) { + String name = cache.getName(); + if (name.length() > 100) { + name = name.substring(0, 100) + '…'; } - status = "I found " + name + " (" + url + ")"; - status = appendHashTag(status, "cgeo"); - status = appendHashTag(status, "geocaching"); - } + final String url = StringUtils.defaultString(cache.getUrl()); + String status = "I found [NAME] ([URL])"; + return fillTemplate(status, name, url); + } - postTweet(cgeoapplication.getInstance(), status, null); + private static String fillTemplate(String template, String name, final String url) { + String result = StringUtils.replace(template, "[NAME]", name); + result = StringUtils.replace(result, "[URL]", url); + StringBuilder builder = new StringBuilder(result); + appendHashTag(builder, "cgeo"); + appendHashTag(builder, "geocaching"); + return builder.toString(); } public static void postTweetTrackable(String geocode) { final Trackable trackable = cgData.loadTrackable(geocode); + postTweet(cgeoapplication.getInstance(), getStatusMessage(trackable), null); + } + + static String getStatusMessage(Trackable trackable) { String name = trackable.getName(); if (name.length() > 82) { name = name.substring(0, 81) + '…'; } - StringBuilder builder = new StringBuilder("I touched "); - builder.append(name); - if (trackable.getUrl() != null) { - builder.append(" (").append(trackable.getUrl()).append(')'); - } - builder.append('!'); - String status = appendHashTag(builder.toString(), "cgeo"); - status = appendHashTag(status, "geocaching"); - postTweet(cgeoapplication.getInstance(), status, null); + String url = StringUtils.defaultString(trackable.getUrl()); + String status = "I touched [NAME] ([URL])!"; + return fillTemplate(status, name, url); } } -- cgit v1.1 From 10110e6b83850b449ae559d06220e1d1faab3745 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Thu, 4 Apr 2013 20:16:17 +0200 Subject: #556: avoid duplicate tags when appending our tags --- main/src/cgeo/geocaching/Settings.java | 15 +++++++++++++++ main/src/cgeo/geocaching/twitter/Twitter.java | 10 ++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 0c157e1..93bfa9b 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -149,6 +149,7 @@ public final class Settings { // maps private static MapProvider mapProvider = null; + private static String cacheTwitterMessage = "I found [NAME] ([URL])"; private Settings() { // this class is not to be instantiated; @@ -1424,4 +1425,18 @@ public final class Settings { } }); } + + public static String getCacheTwitterMessage() { + // TODO make customizable from UI + return cacheTwitterMessage; + } + + public static String getTrackableTwitterMessage() { + // TODO make customizable from UI + return "I touched [NAME] ([URL])!"; + } + + public static void setCacheTwitterMessage(final String message) { + cacheTwitterMessage = message; + } } diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java index 6b427e0..e3d3f77 100644 --- a/main/src/cgeo/geocaching/twitter/Twitter.java +++ b/main/src/cgeo/geocaching/twitter/Twitter.java @@ -52,7 +52,10 @@ public final class Twitter { public static void appendHashTag(final StringBuilder status, final String tag) { if (status.length() + HASH_PREFIX_WITH_BLANK.length() + tag.length() <= MAX_TWEET_SIZE) { - status.append(HASH_PREFIX_WITH_BLANK).append(tag); + final String tagWithPrefix = HASH_PREFIX_WITH_BLANK + tag; + if (status.indexOf(tagWithPrefix, 0) == -1) { + status.append(tagWithPrefix); + } } } @@ -73,8 +76,7 @@ public final class Twitter { name = name.substring(0, 100) + '…'; } final String url = StringUtils.defaultString(cache.getUrl()); - String status = "I found [NAME] ([URL])"; - return fillTemplate(status, name, url); + return fillTemplate(Settings.getCacheTwitterMessage(), name, url); } private static String fillTemplate(String template, String name, final String url) { @@ -97,7 +99,7 @@ public final class Twitter { name = name.substring(0, 81) + '…'; } String url = StringUtils.defaultString(trackable.getUrl()); - String status = "I touched [NAME] ([URL])!"; + String status = Settings.getTrackableTwitterMessage(); return fillTemplate(status, name, url); } } -- cgit v1.1 From 0856587453f4df9379cda95891b9a785f3673095 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 6 Apr 2013 15:43:28 +0200 Subject: fix #2555: try to detect waypoint type in personal note --- main/src/cgeo/geocaching/Geocache.java | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index 9a8325d..96bb2fe 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -49,6 +49,7 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; @@ -1360,6 +1361,9 @@ public class Geocache implements ICache, IWaypoint { return null; } + /** + * Detect coordinates in the personal note and convert them to user defined waypoints. Works by rule of thumb. + */ public void parseWaypointsFromNote() { try { if (StringUtils.isBlank(getPersonalNote())) { @@ -1375,7 +1379,8 @@ public class Geocache implements ICache, IWaypoint { // coords must have non zero latitude and longitude and at least one part shall have fractional degrees if (point.getLatitudeE6() != 0 && point.getLongitudeE6() != 0 && ((point.getLatitudeE6() % 1000) != 0 || (point.getLongitudeE6() % 1000) != 0)) { final String name = cgeoapplication.getInstance().getString(R.string.cache_personal_note) + " " + count; - final Waypoint waypoint = new Waypoint(name, WaypointType.WAYPOINT, false); + final String potentialWaypointType = note.substring(Math.max(0, matcher.start() - 15)); + final Waypoint waypoint = new Waypoint(name, parseWaypointType(potentialWaypointType), false); waypoint.setCoords(point); addOrChangeWaypoint(waypoint, false); count++; @@ -1392,6 +1397,25 @@ public class Geocache implements ICache, IWaypoint { } } + /** + * Detect waypoint types in the personal note text. It works by rule of thumb only. + */ + private static WaypointType parseWaypointType(final String input) { + final String lowerInput = StringUtils.substring(input, 0, 20).toLowerCase(Locale.getDefault()); + for (WaypointType wpType : WaypointType.values()) { + if (lowerInput.contains(wpType.getL10n().toLowerCase(Locale.getDefault()))) { + return wpType; + } + if (lowerInput.contains(wpType.id)) { + return wpType; + } + if (lowerInput.contains(wpType.name().toLowerCase(Locale.US))) { + return wpType; + } + } + return WaypointType.WAYPOINT; + } + /* * For working in the debugger * (non-Javadoc) -- cgit v1.1 From e46b4a46ff6c3ab07ad3172f3c39c8c98202ed46 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 16:22:40 +0200 Subject: fix #2598: personal note editing layout problem --- main/res/layout/fragment_edit_note.xml | 15 +++++ main/src/cgeo/geocaching/CacheDetailActivity.java | 37 +++++++----- main/src/cgeo/geocaching/ui/EditNoteDialog.java | 65 ++++++++++++++++++++++ .../cgeo/geocaching/ui/dialog/EditorDialog.java | 60 -------------------- 4 files changed, 102 insertions(+), 75 deletions(-) create mode 100644 main/res/layout/fragment_edit_note.xml create mode 100644 main/src/cgeo/geocaching/ui/EditNoteDialog.java delete mode 100644 main/src/cgeo/geocaching/ui/dialog/EditorDialog.java (limited to 'main') diff --git a/main/res/layout/fragment_edit_note.xml b/main/res/layout/fragment_edit_note.xml new file mode 100644 index 0000000..68e2b2c --- /dev/null +++ b/main/res/layout/fragment_edit_note.xml @@ -0,0 +1,15 @@ + + + + diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 43ce65f..a521ab9 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -22,12 +22,13 @@ import cgeo.geocaching.ui.AbstractCachingPageViewCreator; import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod; import cgeo.geocaching.ui.CacheDetailsCreator; import cgeo.geocaching.ui.DecryptTextClickListener; +import cgeo.geocaching.ui.EditNoteDialog; +import cgeo.geocaching.ui.EditNoteDialog.EditNoteDialogListener; 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; @@ -65,6 +66,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.support.v4.app.FragmentManager; import android.text.Editable; import android.text.Html; import android.text.Spannable; @@ -112,7 +114,8 @@ import java.util.regex.Pattern; * * e.g. details, description, logs, waypoints, inventory... */ -public class CacheDetailActivity extends AbstractViewPagerActivity { +public class CacheDetailActivity extends AbstractViewPagerActivity + implements EditNoteDialogListener { private static final int MENU_FIELD_COPY = 1; private static final int MENU_FIELD_TRANSLATE = 2; @@ -139,6 +142,8 @@ public class CacheDetailActivity extends AbstractViewPagerActivity Date: Sat, 6 Apr 2013 16:50:05 +0200 Subject: refactoring: do not create explicit arrays to call varargs methods --- main/src/cgeo/geocaching/CacheDetailActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 9347db9..daeb14e 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -2087,7 +2087,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity 0) { // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview LogImageLoader loader = new LogImageLoader(holder); - loader.execute(new String[] { logText }); + loader.execute(logText); } } else { -- cgit v1.1 From f322663f075021cdaf5b28229a8a4d053fc4e4f9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 16:50:55 +0200 Subject: refactoring: use Java-style array declaration --- main/src/cgeo/geocaching/cgeocaches.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 61a32f1..1006628 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -1144,7 +1144,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity public void removeFromHistory() { final List caches = adapter.getCheckedOrAllCaches(); - final String geocodes[] = new String[caches.size()]; + final String[] geocodes = new String[caches.size()]; for (int i = 0; i < geocodes.length; i++) { geocodes[i] = caches.get(i).getGeocode(); } -- cgit v1.1 From 62cd11e0d4a3c557eda4c010b7bc3d66c70a00a8 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 16:51:55 +0200 Subject: refactoring: simplify expression --- main/src/cgeo/geocaching/Waypoint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/Waypoint.java b/main/src/cgeo/geocaching/Waypoint.java index 48c9bc5..6112986 100644 --- a/main/src/cgeo/geocaching/Waypoint.java +++ b/main/src/cgeo/geocaching/Waypoint.java @@ -275,7 +275,7 @@ public class Waypoint implements IWaypoint, Comparable { if (coords != null) { hash = coords.hashCode(); } - hash = hash ^ waypointType.markerId; + hash ^= waypointType.markerId; return (int) hash; } } -- cgit v1.1 From 7211a93bef651f37f58cfa0049d4762272195d95 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:19:30 +0200 Subject: refactoring: narrow scope of variable --- main/src/cgeo/geocaching/cgeocaches.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 1006628..a8e798f 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -1725,11 +1725,11 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public Loader onCreateLoader(int type, Bundle extras) { - AbstractSearchLoader loader = null; if (type >= CacheListLoaderType.values().length) { throw new IllegalArgumentException("invalid loader type " + type); } CacheListLoaderType enumType = CacheListLoaderType.values()[type]; + AbstractSearchLoader loader = null; switch (enumType) { case OFFLINE: listId = Settings.getLastList(); -- cgit v1.1 From 7b8bc42e0ab05a2dbe5cbea64c16d325f04a8b16 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:20:00 +0200 Subject: refactoring: simplify data flow --- main/src/cgeo/geocaching/VisitCacheActivity.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index b4eb82a..f8232af 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -571,16 +571,12 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } public StatusCode postLogFn(String log) { - StatusCode result = StatusCode.LOG_POST_ERROR; - try { - final ImmutablePair postResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), log, trackables); - result = postResult.left; - if (result == StatusCode.NO_ERROR) { + if (postResult.left == StatusCode.NO_ERROR) { final LogEntry logNow = new LogEntry(date, typeSelected, log); cache.getLogs().add(0, logNow); @@ -606,11 +602,11 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription)); cgData.saveChangedCache(cache); } - result = imageResult.left; + return imageResult.left; } } - return result; + return postResult.left; } catch (Exception e) { Log.e("cgeovisit.postLogFn", e); } -- cgit v1.1 From 60a9cc4e0c29c8728c310dd08d4368b171859ca4 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:24:47 +0200 Subject: refactoring: remove redundant return statements --- main/src/cgeo/geocaching/StaticMapsProvider.java | 3 --- 1 file changed, 3 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 69f5cc4..18ecf27 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -76,11 +76,8 @@ public class StaticMapsProvider { final long fileSize = file.length(); if (fileSize < MIN_MAP_IMAGE_BYTES) { file.delete(); - return; } - return; } - return; } public static void downloadMaps(Geocache cache) { -- cgit v1.1 From f09e2a09ad31f2190d6184fd8fd441fa8c95d6ca Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:09:52 +0200 Subject: refactoring: simplify batch export of geocaches By using list-backed sublists, the code to export geocaches in batch can be simplified. Also, there are places where a more generic Collection type can be used in formal parameters to avoid influencing the type of actual arguments. --- main/src/cgeo/geocaching/cgData.java | 3 ++- main/src/cgeo/geocaching/export/GpxExport.java | 25 +++++++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index 28485a5..86821fb 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -33,6 +33,7 @@ import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.EnumSet; @@ -1396,7 +1397,7 @@ public class cgData { * @param geocodes * @return Set of loaded caches. Never null. */ - public static Set loadCaches(final Set geocodes, final EnumSet loadFlags) { + public static Set loadCaches(final Collection geocodes, final EnumSet loadFlags) { if (CollectionUtils.isEmpty(geocodes)) { return new HashSet(); } diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index 19b8518..4c5d1e2 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -5,9 +5,9 @@ import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.Settings; import cgeo.geocaching.Waypoint; +import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; -import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.geopoint.Geopoint; @@ -37,9 +37,8 @@ import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Set; @@ -106,7 +105,7 @@ class GpxExport extends AbstractExport { } private class ExportTask extends AsyncTaskWithProgress { - private final Set allGeocodes = new HashSet(); + private final List allGeocodes; private final Activity activity; private int countExported = 0; @@ -122,7 +121,8 @@ class GpxExport extends AbstractExport { super(activity, caches.size(), getProgressTitle(), cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, caches.size(), caches.size())); // get rid of the (half loaded) caches, we will reload them as full caches during the export - for (Geocache geocache : caches) { + allGeocodes = new ArrayList(caches.size()); + for (final Geocache geocache : caches) { allGeocodes.add(geocache.getGeocode()); } this.activity = activity; @@ -159,17 +159,10 @@ class GpxExport extends AbstractExport { // Split the overall set of geocodes into small chunks. That is a compromise between memory efficiency (because // we don't load all caches fully into memory) and speed (because we don't query each cache separately). - while (!allGeocodes.isEmpty()) { - int cachesInBatch = 0; - HashSet geocodesOfBatch = new HashSet(CACHES_PER_BATCH); - for (Iterator iterator = allGeocodes.iterator(); iterator.hasNext() && cachesInBatch < CACHES_PER_BATCH;) { - final String geocode = iterator.next(); - geocodesOfBatch.add(geocode); - cachesInBatch++; - } - allGeocodes.removeAll(geocodesOfBatch); - exportBatch(gpx, geocodesOfBatch); + final List batch = allGeocodes.subList(0, Math.min(CACHES_PER_BATCH, allGeocodes.size())); + exportBatch(gpx, batch); + batch.clear(); } gpx.endTag(PREFIX_GPX, "gpx"); @@ -195,7 +188,7 @@ class GpxExport extends AbstractExport { return exportFile; } - private void exportBatch(final XmlSerializer gpx, HashSet geocodesOfBatch) throws IOException { + private void exportBatch(final XmlSerializer gpx, Collection geocodesOfBatch) throws IOException { Set caches = cgData.loadCaches(geocodesOfBatch, LoadFlags.LOAD_ALL_DB_ONLY); for (Geocache cache : caches) { gpx.startTag(PREFIX_GPX, "wpt"); -- cgit v1.1 From 953905039962a657b678fb043dbe56d3c8649e43 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:53:31 +0200 Subject: refactoring: make sure downloadMaps doesn't get a null cache If downloadMaps cannot get a null cache in the first place, the null check is no longer needed. --- main/src/cgeo/geocaching/StaticMapsProvider.java | 4 ---- main/src/cgeo/geocaching/files/GPXImporter.java | 12 ++++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 18ecf27..48f1e48 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -81,10 +81,6 @@ public class StaticMapsProvider { } public static void downloadMaps(Geocache cache) { - if (cache == null) { - Log.e("downloadMaps - missing input parameter cache"); - return; - } if ((!Settings.isStoreOfflineMaps() && !Settings.isStoreOfflineWpMaps()) || StringUtils.isBlank(cache.getGeocode())) { return; } diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index b8dcbb3..6329b64 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -171,10 +171,14 @@ public class GPXImporter { private boolean importStaticMaps(final SearchResult importedCaches) { int storedCacheMaps = 0; - for (String geocode : importedCaches.getGeocodes()) { - Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); - Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode); - StaticMapsProvider.downloadMaps(cache); + for (final String geocode : importedCaches.getGeocodes()) { + final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + if (cache != null) { + Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode); + StaticMapsProvider.downloadMaps(cache); + } else { + Log.d("GPXImporter.ImportThread.importStaticMaps: no data found for " + geocode); + } storedCacheMaps++; if (progressHandler.isCancelled()) { return false; -- cgit v1.1 From 596f9711b739ab74d19516a4466d288f90e220f9 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:54:52 +0200 Subject: refactoring: use Unix line ending --- main/src/cgeo/geocaching/files/GPXImporter.java | 924 ++++++++++++------------ 1 file changed, 462 insertions(+), 462 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java index 6329b64..ff81fe1 100644 --- a/main/src/cgeo/geocaching/files/GPXImporter.java +++ b/main/src/cgeo/geocaching/files/GPXImporter.java @@ -1,462 +1,462 @@ -package cgeo.geocaching.files; - -import cgeo.geocaching.Geocache; -import cgeo.geocaching.R; -import cgeo.geocaching.SearchResult; -import cgeo.geocaching.Settings; -import cgeo.geocaching.StaticMapsProvider; -import cgeo.geocaching.cgData; -import cgeo.geocaching.activity.IAbstractActivity; -import cgeo.geocaching.activity.Progress; -import cgeo.geocaching.enumerations.LoadFlags; -import cgeo.geocaching.utils.CancellableHandler; -import cgeo.geocaching.utils.Log; - -import org.apache.commons.lang3.StringUtils; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.net.Uri; -import android.os.Handler; -import android.os.Message; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CancellationException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -public class GPXImporter { - static final int IMPORT_STEP_START = 0; - static final int IMPORT_STEP_READ_FILE = 1; - static final int IMPORT_STEP_READ_WPT_FILE = 2; - static final int IMPORT_STEP_STORE_STATIC_MAPS = 4; - static final int IMPORT_STEP_FINISHED = 5; - static final int IMPORT_STEP_FINISHED_WITH_ERROR = 6; - static final int IMPORT_STEP_CANCEL = 7; - static final int IMPORT_STEP_CANCELED = 8; - static final int IMPORT_STEP_STATIC_MAPS_SKIPPED = 9; - - public static final String GPX_FILE_EXTENSION = ".gpx"; - public static final String ZIP_FILE_EXTENSION = ".zip"; - public static final String WAYPOINTS_FILE_SUFFIX = "-wpts"; - public static final String WAYPOINTS_FILE_SUFFIX_AND_EXTENSION = WAYPOINTS_FILE_SUFFIX + GPX_FILE_EXTENSION; - - private static final List GPX_MIME_TYPES = Arrays.asList("text/xml", "application/xml"); - private static final List ZIP_MIME_TYPES = Arrays.asList("application/zip", "application/x-compressed", "application/x-zip-compressed", "application/x-zip", "application/octet-stream"); - - private Progress progress = new Progress(true); - - private Resources res; - private int listId; - private IAbstractActivity fromActivity; - private Handler importFinishedHandler; - - public GPXImporter(final IAbstractActivity fromActivity, final int listId, final Handler importFinishedHandler) { - this.listId = listId; - this.fromActivity = fromActivity; - res = ((Activity) fromActivity).getResources(); - this.importFinishedHandler = importFinishedHandler; - } - - /** - * Import GPX file. Currently supports *.gpx, *.zip (containing gpx files, e.g. PQ queries) or *.loc files. - * - * @param file - * the file to import - */ - public void importGPX(final File file) { - if (StringUtils.endsWithIgnoreCase(file.getName(), GPX_FILE_EXTENSION)) { - new ImportGpxFileThread(file, listId, importStepHandler, progressHandler).start(); - } else if (StringUtils.endsWithIgnoreCase(file.getName(), ZIP_FILE_EXTENSION)) { - new ImportGpxZipFileThread(file, listId, importStepHandler, progressHandler).start(); - } else { - new ImportLocFileThread(file, listId, importStepHandler, progressHandler).start(); - } - } - - /** - * Import GPX provided via intent of activity that instantiated this GPXImporter. - */ - public void importGPX() { - final ContentResolver contentResolver = ((Activity) fromActivity).getContentResolver(); - final Intent intent = ((Activity) fromActivity).getIntent(); - final Uri uri = intent.getData(); - - String mimeType = intent.getType(); - // if mimetype can't be determined (e.g. for emulators email app), derive it from uri file extension - // contentResolver.getType(uri) doesn't help but throws exception for emulators email app - // Permission Denial: reading com.android.email.provider.EmailProvider uri - // Google search says: there is no solution for this problem - // Gmail doesn't work at all, see #967 - if (mimeType == null) { - if (StringUtils.endsWithIgnoreCase(uri.getPath(), GPX_FILE_EXTENSION)) { - mimeType = "application/xml"; - } else { - // if we can't determine a better type, default to zip import - // emulator email sends e.g. content://com.android.email.attachmentprovider/1/1/RAW, mimetype=null - mimeType = "application/zip"; - } - } - - Log.i("importGPX: " + uri + ", mimetype=" + mimeType); - if (GPX_MIME_TYPES.contains(mimeType)) { - new ImportGpxAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start(); - } else if (ZIP_MIME_TYPES.contains(mimeType)) { - new ImportGpxZipAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start(); - } else { - importFinished(); - } - } - - static abstract class ImportThread extends Thread { - final int listId; - final Handler importStepHandler; - final CancellableHandler progressHandler; - - protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { - this.listId = listId; - this.importStepHandler = importStepHandler; - this.progressHandler = progressHandler; - } - - @Override - public void run() { - try { - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_START)); - final Collection caches = doImport(); - Log.i("Imported successfully " + caches.size() + " caches."); - - final SearchResult search = new SearchResult(); - for (Geocache cache : caches) { - search.addCache(cache); - } - - if (Settings.isStoreOfflineMaps() || Settings.isStoreOfflineWpMaps()) { - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_STATIC_MAPS, R.string.gpx_import_store_static_maps, search.getCount())); - boolean finishedWithoutCancel = importStaticMaps(search); - // Skip last message if static maps where canceled - if (!finishedWithoutCancel) { - return; - } - } - - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED, search.getCount(), 0, search)); - } catch (IOException e) { - Log.i("Importing caches failed - error reading data: " + e.getMessage()); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_io, 0, e.getLocalizedMessage())); - } catch (ParserException e) { - Log.i("Importing caches failed - data format error" + e.getMessage()); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage())); - } catch (CancellationException e) { - Log.i("Importing caches canceled"); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED)); - } catch (Exception e) { - Log.e("Importing caches failed - unknown error: ", e); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_unexpected, 0, e.getLocalizedMessage())); - } - } - - protected abstract Collection doImport() throws IOException, ParserException; - - private boolean importStaticMaps(final SearchResult importedCaches) { - int storedCacheMaps = 0; - for (final String geocode : importedCaches.getGeocodes()) { - final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); - if (cache != null) { - Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode); - StaticMapsProvider.downloadMaps(cache); - } else { - Log.d("GPXImporter.ImportThread.importStaticMaps: no data found for " + geocode); - } - storedCacheMaps++; - if (progressHandler.isCancelled()) { - return false; - } - progressHandler.sendMessage(progressHandler.obtainMessage(0, storedCacheMaps, 0)); - } - return true; - } - } - - static class ImportLocFileThread extends ImportThread { - private final File file; - - public ImportLocFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - this.file = file; - } - - @Override - protected Collection doImport() throws IOException, ParserException { - Log.i("Import LOC file: " + file.getAbsolutePath()); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) file.length())); - LocParser parser = new LocParser(listId); - return parser.parse(file, progressHandler); - } - } - - static abstract class ImportGpxThread extends ImportThread { - - protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - } - - @Override - protected Collection doImport() throws IOException, ParserException { - try { - // try to parse cache file as GPX 10 - return doImport(new GPX10Parser(listId)); - } catch (ParserException pe) { - // didn't work -> lets try GPX11 - return doImport(new GPX11Parser(listId)); - } - } - - protected abstract Collection doImport(GPXParser parser) throws IOException, ParserException; - } - - static class ImportGpxFileThread extends ImportGpxThread { - private final File cacheFile; - - public ImportGpxFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - this.cacheFile = file; - } - - @Override - protected Collection doImport(GPXParser parser) throws IOException, ParserException { - Log.i("Import GPX file: " + cacheFile.getAbsolutePath()); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) cacheFile.length())); - Collection caches = parser.parse(cacheFile, progressHandler); - - final String wptsFilename = getWaypointsFileNameForGpxFile(cacheFile); - if (wptsFilename != null) { - final File wptsFile = new File(cacheFile.getParentFile(), wptsFilename); - if (wptsFile.canRead()) { - Log.i("Import GPX waypoint file: " + wptsFile.getAbsolutePath()); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) wptsFile.length())); - caches = parser.parse(wptsFile, progressHandler); - } - } - return caches; - } - } - - static class ImportGpxAttachmentThread extends ImportGpxThread { - private final Uri uri; - private ContentResolver contentResolver; - - public ImportGpxAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - this.uri = uri; - this.contentResolver = contentResolver; - } - - @Override - protected Collection doImport(GPXParser parser) throws IOException, ParserException { - Log.i("Import GPX from uri: " + uri); - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1)); - InputStream is = contentResolver.openInputStream(uri); - try { - return parser.parse(is, progressHandler); - } finally { - is.close(); - } - } - } - - static abstract class ImportGpxZipThread extends ImportGpxThread { - - protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - } - - @Override - protected Collection doImport(GPXParser parser) throws IOException, ParserException { - Collection caches = Collections.emptySet(); - // can't assume that GPX file comes before waypoint file in zip -> so we need two passes - // 1. parse GPX files - ZipInputStream zis = new ZipInputStream(getInputStream()); - try { - for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) { - if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), GPX_FILE_EXTENSION)) { - if (!StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) { - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) zipEntry.getSize())); - caches = parser.parse(new NoCloseInputStream(zis), progressHandler); - } - } else { - throw new ParserException("Imported zip is not a GPX zip file."); - } - zis.closeEntry(); - } - } finally { - zis.close(); - } - - // 2. parse waypoint files - zis = new ZipInputStream(getInputStream()); - try { - for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) { - if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) { - importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) zipEntry.getSize())); - caches = parser.parse(new NoCloseInputStream(zis), progressHandler); - } - zis.closeEntry(); - } - } finally { - zis.close(); - } - - return caches; - } - - protected abstract InputStream getInputStream() throws IOException; - } - - static class ImportGpxZipFileThread extends ImportGpxZipThread { - private final File cacheFile; - - public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - this.cacheFile = file; - Log.i("Import zipped GPX: " + file); - } - - @Override - protected InputStream getInputStream() throws IOException { - return new FileInputStream(cacheFile); - } - } - - static class ImportGpxZipAttachmentThread extends ImportGpxZipThread { - private final Uri uri; - private ContentResolver contentResolver; - - public ImportGpxZipAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { - super(listId, importStepHandler, progressHandler); - this.uri = uri; - this.contentResolver = contentResolver; - Log.i("Import zipped GPX from uri: " + uri); - } - - @Override - protected InputStream getInputStream() throws IOException { - return contentResolver.openInputStream(uri); - } - } - - final private CancellableHandler progressHandler = new CancellableHandler() { - @Override - public void handleRegularMessage(Message msg) { - progress.setProgress(msg.arg1); - } - }; - - final private Handler importStepHandler = new Handler() { - private boolean showProgressAfterCancel = false; - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case IMPORT_STEP_START: - Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL); - progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_reading_file), res.getString(R.string.gpx_import_loading_caches), ProgressDialog.STYLE_HORIZONTAL, cancelMessage); - break; - - case IMPORT_STEP_READ_FILE: - case IMPORT_STEP_READ_WPT_FILE: - progress.setMessage(res.getString(msg.arg1)); - progress.setMaxProgressAndReset(msg.arg2); - break; - - case IMPORT_STEP_STORE_STATIC_MAPS: - progress.dismiss(); - Message skipMessage = importStepHandler.obtainMessage(IMPORT_STEP_STATIC_MAPS_SKIPPED, msg.arg2, 0); - progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_static_maps), res.getString(R.string.gpx_import_store_static_maps), ProgressDialog.STYLE_HORIZONTAL, skipMessage); - progress.setMaxProgressAndReset(msg.arg2); - break; - - case IMPORT_STEP_STATIC_MAPS_SKIPPED: - progress.dismiss(); - progressHandler.cancel(); - StringBuilder bufferSkipped = new StringBuilder(20); - bufferSkipped.append(res.getString(R.string.gpx_import_static_maps_skipped)).append(", ").append(msg.arg1).append(' ').append(res.getString(R.string.gpx_import_caches_imported)); - fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), bufferSkipped.toString()); - importFinished(); - break; - - case IMPORT_STEP_FINISHED: - progress.dismiss(); - fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), msg.arg1 + " " + res.getString(R.string.gpx_import_caches_imported)); - importFinished(); - break; - - case IMPORT_STEP_FINISHED_WITH_ERROR: - progress.dismiss(); - fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_import_failed), res.getString(msg.arg1) + "\n\n" + msg.obj); - importFinished(); - break; - - case IMPORT_STEP_CANCEL: - progress.dismiss(); - progressHandler.cancel(); - break; - - case IMPORT_STEP_CANCELED: - StringBuilder bufferCanceled = new StringBuilder(20); - bufferCanceled.append(res.getString(R.string.gpx_import_canceled)); - if (showProgressAfterCancel) { - bufferCanceled.append(", ").append(progress.getProgress()).append(' ').append(res.getString(R.string.gpx_import_caches_imported)); - } - fromActivity.showShortToast(bufferCanceled.toString()); - importFinished(); - break; - - default: - break; - } - } - }; - - /** - * @param gpxfile - * the gpx file - * @return the expected file name of the waypoints file - */ - static String getWaypointsFileNameForGpxFile(final File gpxfile) { - if (gpxfile == null || !gpxfile.canRead()) { - return null; - } - final String gpxFileName = gpxfile.getName(); - File dir = gpxfile.getParentFile(); - String[] filenameList = dir.list(); - for (String filename : filenameList) { - if (!StringUtils.containsIgnoreCase(filename, WAYPOINTS_FILE_SUFFIX)) { - continue; - } - String expectedGpxFileName = StringUtils.substringBeforeLast(filename, WAYPOINTS_FILE_SUFFIX) - + StringUtils.substringAfterLast(filename, WAYPOINTS_FILE_SUFFIX); - if (gpxFileName.equals(expectedGpxFileName)) { - return filename; - } - } - return null; - } - - protected void importFinished() { - if (importFinishedHandler != null) { - importFinishedHandler.sendEmptyMessage(0); - } - } -} +package cgeo.geocaching.files; + +import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.StaticMapsProvider; +import cgeo.geocaching.cgData; +import cgeo.geocaching.activity.IAbstractActivity; +import cgeo.geocaching.activity.Progress; +import cgeo.geocaching.enumerations.LoadFlags; +import cgeo.geocaching.utils.CancellableHandler; +import cgeo.geocaching.utils.Log; + +import org.apache.commons.lang3.StringUtils; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CancellationException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class GPXImporter { + static final int IMPORT_STEP_START = 0; + static final int IMPORT_STEP_READ_FILE = 1; + static final int IMPORT_STEP_READ_WPT_FILE = 2; + static final int IMPORT_STEP_STORE_STATIC_MAPS = 4; + static final int IMPORT_STEP_FINISHED = 5; + static final int IMPORT_STEP_FINISHED_WITH_ERROR = 6; + static final int IMPORT_STEP_CANCEL = 7; + static final int IMPORT_STEP_CANCELED = 8; + static final int IMPORT_STEP_STATIC_MAPS_SKIPPED = 9; + + public static final String GPX_FILE_EXTENSION = ".gpx"; + public static final String ZIP_FILE_EXTENSION = ".zip"; + public static final String WAYPOINTS_FILE_SUFFIX = "-wpts"; + public static final String WAYPOINTS_FILE_SUFFIX_AND_EXTENSION = WAYPOINTS_FILE_SUFFIX + GPX_FILE_EXTENSION; + + private static final List GPX_MIME_TYPES = Arrays.asList("text/xml", "application/xml"); + private static final List ZIP_MIME_TYPES = Arrays.asList("application/zip", "application/x-compressed", "application/x-zip-compressed", "application/x-zip", "application/octet-stream"); + + private Progress progress = new Progress(true); + + private Resources res; + private int listId; + private IAbstractActivity fromActivity; + private Handler importFinishedHandler; + + public GPXImporter(final IAbstractActivity fromActivity, final int listId, final Handler importFinishedHandler) { + this.listId = listId; + this.fromActivity = fromActivity; + res = ((Activity) fromActivity).getResources(); + this.importFinishedHandler = importFinishedHandler; + } + + /** + * Import GPX file. Currently supports *.gpx, *.zip (containing gpx files, e.g. PQ queries) or *.loc files. + * + * @param file + * the file to import + */ + public void importGPX(final File file) { + if (StringUtils.endsWithIgnoreCase(file.getName(), GPX_FILE_EXTENSION)) { + new ImportGpxFileThread(file, listId, importStepHandler, progressHandler).start(); + } else if (StringUtils.endsWithIgnoreCase(file.getName(), ZIP_FILE_EXTENSION)) { + new ImportGpxZipFileThread(file, listId, importStepHandler, progressHandler).start(); + } else { + new ImportLocFileThread(file, listId, importStepHandler, progressHandler).start(); + } + } + + /** + * Import GPX provided via intent of activity that instantiated this GPXImporter. + */ + public void importGPX() { + final ContentResolver contentResolver = ((Activity) fromActivity).getContentResolver(); + final Intent intent = ((Activity) fromActivity).getIntent(); + final Uri uri = intent.getData(); + + String mimeType = intent.getType(); + // if mimetype can't be determined (e.g. for emulators email app), derive it from uri file extension + // contentResolver.getType(uri) doesn't help but throws exception for emulators email app + // Permission Denial: reading com.android.email.provider.EmailProvider uri + // Google search says: there is no solution for this problem + // Gmail doesn't work at all, see #967 + if (mimeType == null) { + if (StringUtils.endsWithIgnoreCase(uri.getPath(), GPX_FILE_EXTENSION)) { + mimeType = "application/xml"; + } else { + // if we can't determine a better type, default to zip import + // emulator email sends e.g. content://com.android.email.attachmentprovider/1/1/RAW, mimetype=null + mimeType = "application/zip"; + } + } + + Log.i("importGPX: " + uri + ", mimetype=" + mimeType); + if (GPX_MIME_TYPES.contains(mimeType)) { + new ImportGpxAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start(); + } else if (ZIP_MIME_TYPES.contains(mimeType)) { + new ImportGpxZipAttachmentThread(uri, contentResolver, listId, importStepHandler, progressHandler).start(); + } else { + importFinished(); + } + } + + static abstract class ImportThread extends Thread { + final int listId; + final Handler importStepHandler; + final CancellableHandler progressHandler; + + protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { + this.listId = listId; + this.importStepHandler = importStepHandler; + this.progressHandler = progressHandler; + } + + @Override + public void run() { + try { + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_START)); + final Collection caches = doImport(); + Log.i("Imported successfully " + caches.size() + " caches."); + + final SearchResult search = new SearchResult(); + for (Geocache cache : caches) { + search.addCache(cache); + } + + if (Settings.isStoreOfflineMaps() || Settings.isStoreOfflineWpMaps()) { + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_STORE_STATIC_MAPS, R.string.gpx_import_store_static_maps, search.getCount())); + boolean finishedWithoutCancel = importStaticMaps(search); + // Skip last message if static maps where canceled + if (!finishedWithoutCancel) { + return; + } + } + + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED, search.getCount(), 0, search)); + } catch (IOException e) { + Log.i("Importing caches failed - error reading data: " + e.getMessage()); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_io, 0, e.getLocalizedMessage())); + } catch (ParserException e) { + Log.i("Importing caches failed - data format error" + e.getMessage()); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_parser, 0, e.getLocalizedMessage())); + } catch (CancellationException e) { + Log.i("Importing caches canceled"); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_CANCELED)); + } catch (Exception e) { + Log.e("Importing caches failed - unknown error: ", e); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_FINISHED_WITH_ERROR, R.string.gpx_import_error_unexpected, 0, e.getLocalizedMessage())); + } + } + + protected abstract Collection doImport() throws IOException, ParserException; + + private boolean importStaticMaps(final SearchResult importedCaches) { + int storedCacheMaps = 0; + for (final String geocode : importedCaches.getGeocodes()) { + final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS); + if (cache != null) { + Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode); + StaticMapsProvider.downloadMaps(cache); + } else { + Log.d("GPXImporter.ImportThread.importStaticMaps: no data found for " + geocode); + } + storedCacheMaps++; + if (progressHandler.isCancelled()) { + return false; + } + progressHandler.sendMessage(progressHandler.obtainMessage(0, storedCacheMaps, 0)); + } + return true; + } + } + + static class ImportLocFileThread extends ImportThread { + private final File file; + + public ImportLocFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + this.file = file; + } + + @Override + protected Collection doImport() throws IOException, ParserException { + Log.i("Import LOC file: " + file.getAbsolutePath()); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) file.length())); + LocParser parser = new LocParser(listId); + return parser.parse(file, progressHandler); + } + } + + static abstract class ImportGpxThread extends ImportThread { + + protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + } + + @Override + protected Collection doImport() throws IOException, ParserException { + try { + // try to parse cache file as GPX 10 + return doImport(new GPX10Parser(listId)); + } catch (ParserException pe) { + // didn't work -> lets try GPX11 + return doImport(new GPX11Parser(listId)); + } + } + + protected abstract Collection doImport(GPXParser parser) throws IOException, ParserException; + } + + static class ImportGpxFileThread extends ImportGpxThread { + private final File cacheFile; + + public ImportGpxFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + this.cacheFile = file; + } + + @Override + protected Collection doImport(GPXParser parser) throws IOException, ParserException { + Log.i("Import GPX file: " + cacheFile.getAbsolutePath()); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) cacheFile.length())); + Collection caches = parser.parse(cacheFile, progressHandler); + + final String wptsFilename = getWaypointsFileNameForGpxFile(cacheFile); + if (wptsFilename != null) { + final File wptsFile = new File(cacheFile.getParentFile(), wptsFilename); + if (wptsFile.canRead()) { + Log.i("Import GPX waypoint file: " + wptsFile.getAbsolutePath()); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) wptsFile.length())); + caches = parser.parse(wptsFile, progressHandler); + } + } + return caches; + } + } + + static class ImportGpxAttachmentThread extends ImportGpxThread { + private final Uri uri; + private ContentResolver contentResolver; + + public ImportGpxAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + this.uri = uri; + this.contentResolver = contentResolver; + } + + @Override + protected Collection doImport(GPXParser parser) throws IOException, ParserException { + Log.i("Import GPX from uri: " + uri); + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, -1)); + InputStream is = contentResolver.openInputStream(uri); + try { + return parser.parse(is, progressHandler); + } finally { + is.close(); + } + } + } + + static abstract class ImportGpxZipThread extends ImportGpxThread { + + protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + } + + @Override + protected Collection doImport(GPXParser parser) throws IOException, ParserException { + Collection caches = Collections.emptySet(); + // can't assume that GPX file comes before waypoint file in zip -> so we need two passes + // 1. parse GPX files + ZipInputStream zis = new ZipInputStream(getInputStream()); + try { + for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) { + if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), GPX_FILE_EXTENSION)) { + if (!StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) { + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches, (int) zipEntry.getSize())); + caches = parser.parse(new NoCloseInputStream(zis), progressHandler); + } + } else { + throw new ParserException("Imported zip is not a GPX zip file."); + } + zis.closeEntry(); + } + } finally { + zis.close(); + } + + // 2. parse waypoint files + zis = new ZipInputStream(getInputStream()); + try { + for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis.getNextEntry()) { + if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) { + importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints, (int) zipEntry.getSize())); + caches = parser.parse(new NoCloseInputStream(zis), progressHandler); + } + zis.closeEntry(); + } + } finally { + zis.close(); + } + + return caches; + } + + protected abstract InputStream getInputStream() throws IOException; + } + + static class ImportGpxZipFileThread extends ImportGpxZipThread { + private final File cacheFile; + + public ImportGpxZipFileThread(final File file, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + this.cacheFile = file; + Log.i("Import zipped GPX: " + file); + } + + @Override + protected InputStream getInputStream() throws IOException { + return new FileInputStream(cacheFile); + } + } + + static class ImportGpxZipAttachmentThread extends ImportGpxZipThread { + private final Uri uri; + private ContentResolver contentResolver; + + public ImportGpxZipAttachmentThread(Uri uri, ContentResolver contentResolver, int listId, Handler importStepHandler, CancellableHandler progressHandler) { + super(listId, importStepHandler, progressHandler); + this.uri = uri; + this.contentResolver = contentResolver; + Log.i("Import zipped GPX from uri: " + uri); + } + + @Override + protected InputStream getInputStream() throws IOException { + return contentResolver.openInputStream(uri); + } + } + + final private CancellableHandler progressHandler = new CancellableHandler() { + @Override + public void handleRegularMessage(Message msg) { + progress.setProgress(msg.arg1); + } + }; + + final private Handler importStepHandler = new Handler() { + private boolean showProgressAfterCancel = false; + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case IMPORT_STEP_START: + Message cancelMessage = importStepHandler.obtainMessage(IMPORT_STEP_CANCEL); + progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_reading_file), res.getString(R.string.gpx_import_loading_caches), ProgressDialog.STYLE_HORIZONTAL, cancelMessage); + break; + + case IMPORT_STEP_READ_FILE: + case IMPORT_STEP_READ_WPT_FILE: + progress.setMessage(res.getString(msg.arg1)); + progress.setMaxProgressAndReset(msg.arg2); + break; + + case IMPORT_STEP_STORE_STATIC_MAPS: + progress.dismiss(); + Message skipMessage = importStepHandler.obtainMessage(IMPORT_STEP_STATIC_MAPS_SKIPPED, msg.arg2, 0); + progress.show((Context) fromActivity, res.getString(R.string.gpx_import_title_static_maps), res.getString(R.string.gpx_import_store_static_maps), ProgressDialog.STYLE_HORIZONTAL, skipMessage); + progress.setMaxProgressAndReset(msg.arg2); + break; + + case IMPORT_STEP_STATIC_MAPS_SKIPPED: + progress.dismiss(); + progressHandler.cancel(); + StringBuilder bufferSkipped = new StringBuilder(20); + bufferSkipped.append(res.getString(R.string.gpx_import_static_maps_skipped)).append(", ").append(msg.arg1).append(' ').append(res.getString(R.string.gpx_import_caches_imported)); + fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), bufferSkipped.toString()); + importFinished(); + break; + + case IMPORT_STEP_FINISHED: + progress.dismiss(); + fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_imported), msg.arg1 + " " + res.getString(R.string.gpx_import_caches_imported)); + importFinished(); + break; + + case IMPORT_STEP_FINISHED_WITH_ERROR: + progress.dismiss(); + fromActivity.helpDialog(res.getString(R.string.gpx_import_title_caches_import_failed), res.getString(msg.arg1) + "\n\n" + msg.obj); + importFinished(); + break; + + case IMPORT_STEP_CANCEL: + progress.dismiss(); + progressHandler.cancel(); + break; + + case IMPORT_STEP_CANCELED: + StringBuilder bufferCanceled = new StringBuilder(20); + bufferCanceled.append(res.getString(R.string.gpx_import_canceled)); + if (showProgressAfterCancel) { + bufferCanceled.append(", ").append(progress.getProgress()).append(' ').append(res.getString(R.string.gpx_import_caches_imported)); + } + fromActivity.showShortToast(bufferCanceled.toString()); + importFinished(); + break; + + default: + break; + } + } + }; + + /** + * @param gpxfile + * the gpx file + * @return the expected file name of the waypoints file + */ + static String getWaypointsFileNameForGpxFile(final File gpxfile) { + if (gpxfile == null || !gpxfile.canRead()) { + return null; + } + final String gpxFileName = gpxfile.getName(); + File dir = gpxfile.getParentFile(); + String[] filenameList = dir.list(); + for (String filename : filenameList) { + if (!StringUtils.containsIgnoreCase(filename, WAYPOINTS_FILE_SUFFIX)) { + continue; + } + String expectedGpxFileName = StringUtils.substringBeforeLast(filename, WAYPOINTS_FILE_SUFFIX) + + StringUtils.substringAfterLast(filename, WAYPOINTS_FILE_SUFFIX); + if (gpxFileName.equals(expectedGpxFileName)) { + return filename; + } + } + return null; + } + + protected void importFinished() { + if (importFinishedHandler != null) { + importFinishedHandler.sendEmptyMessage(0); + } + } +} -- cgit v1.1 From a06ebc504275d11b740a54fddfb6dc60a0d0887a Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 17:57:35 +0200 Subject: refactoring: remove redundant null check If the cache parameter is null, both callers will crash right before or right after the call to storeCachePreviewMap. There is no point in checking for nullness in this method. --- main/src/cgeo/geocaching/StaticMapsProvider.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 48f1e48..37a6cd6 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -163,10 +163,6 @@ public class StaticMapsProvider { } public static void storeCachePreviewMap(final Geocache cache) { - if (cache == null) { - Log.e("storeCachePreviewMap - missing input parameter cache"); - return; - } final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA); final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); -- cgit v1.1 From a7c667f396f629957da115da3d46ce989b7ad736 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 18:06:25 +0200 Subject: refactoring: remove extra check If getWaypoints() returns an empty collection, then the loop will do nothing. Since it cannot return a null value, the test is redundant. --- main/src/cgeo/geocaching/StaticMapsProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 37a6cd6..e7332a8 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -92,8 +92,8 @@ public class StaticMapsProvider { } // clean old and download static maps for waypoints if one is missing - if (Settings.isStoreOfflineWpMaps() && CollectionUtils.isNotEmpty(cache.getWaypoints())) { - for (Waypoint waypoint : cache.getWaypoints()) { + if (Settings.isStoreOfflineWpMaps()) { + for (final Waypoint waypoint : cache.getWaypoints()) { if (!hasAllStaticMapsForWaypoint(cache.getGeocode(), waypoint)) { refreshAllWpStaticMaps(cache, edge); } -- cgit v1.1 From b39ac269cec2ef1f77e35864189556b7954ba357 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 18:08:32 +0200 Subject: refactoring: remove unused import --- main/src/cgeo/geocaching/StaticMapsProvider.java | 1 - 1 file changed, 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index e7332a8..7afd33f 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -10,7 +10,6 @@ import cgeo.geocaching.utils.Log; import ch.boye.httpclientandroidlib.HttpResponse; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import android.content.Context; -- cgit v1.1 From d53097da51ee155ac88c3e89680e673e087a3c64 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 18:10:50 +0200 Subject: refactoring: use Math.max to compute the maximum of two integer values --- main/src/cgeo/geocaching/StaticMapsProvider.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java index 7afd33f..9a4c00b 100644 --- a/main/src/cgeo/geocaching/StaticMapsProvider.java +++ b/main/src/cgeo/geocaching/StaticMapsProvider.java @@ -174,12 +174,7 @@ public class StaticMapsProvider { private static int guessMaxDisplaySide() { Point displaySize = Compatibility.getDisplaySize(); - final int maxWidth = displaySize.x - 25; - final int maxHeight = displaySize.y - 25; - if (maxWidth > maxHeight) { - return maxWidth; - } - return maxHeight; + return Math.max(displaySize.x, displaySize.y) - 25; } private static void downloadMaps(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge, -- cgit v1.1 From a2a94ea05224d696268ab385bf14d7322c366bfc Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 18:38:52 +0200 Subject: refactoring: simplify attribute resolution code getString(id) would not return a blank string, it would raise an exception if the given id was not found. --- main/src/cgeo/geocaching/filter/AttributeFilter.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index 4b6f382..f3e8eb3 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -1,13 +1,11 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.R; import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; -import org.apache.commons.lang3.StringUtils; - import android.content.res.Resources; import java.util.EnumSet; @@ -24,13 +22,7 @@ class AttributeFilter extends AbstractFilter { private static String getName(final String attribute, final Resources res, final String packageName) { // dynamically search for a translation of the attribute final int id = res.getIdentifier(attribute, "string", packageName); - if (id > 0) { - final String translated = res.getString(id); - if (StringUtils.isNotBlank(translated)) { - return translated; - } - } - return attribute; + return id > 0 ? res.getString(id) : attribute; } @Override -- cgit v1.1 From a684000289227de82d944da97d3d8d2d4998572b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 20:13:46 +0200 Subject: refactoring: use lists instead of arrays for filter collections Using arrays makes the surrounding code very constrained. Most of the time, filter collections were built in lists and converted into arrays. Using lists in the filter factory signature makes it more natural to manipulate those collections. --- main/src/cgeo/geocaching/filter/AttributeFilter.java | 11 ++++++----- main/src/cgeo/geocaching/filter/DifficultyFilter.java | 5 +++-- main/src/cgeo/geocaching/filter/FilterUserInterface.java | 9 +++++---- main/src/cgeo/geocaching/filter/IFilterFactory.java | 4 +++- main/src/cgeo/geocaching/filter/ModifiedFilter.java | 7 +++++-- main/src/cgeo/geocaching/filter/OriginFilter.java | 5 +++-- main/src/cgeo/geocaching/filter/SizeFilter.java | 9 +++++---- main/src/cgeo/geocaching/filter/StateFilter.java | 7 ++++--- main/src/cgeo/geocaching/filter/TerrainFilter.java | 8 ++++---- main/src/cgeo/geocaching/filter/TrackablesFilter.java | 9 ++++++--- main/src/cgeo/geocaching/filter/TypeFilter.java | 9 +++++---- 11 files changed, 49 insertions(+), 34 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java index f3e8eb3..cadcf49 100644 --- a/main/src/cgeo/geocaching/filter/AttributeFilter.java +++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java @@ -9,6 +9,8 @@ import cgeo.geocaching.enumerations.LoadFlags.LoadFlag; import android.content.res.Resources; import java.util.EnumSet; +import java.util.LinkedList; +import java.util.List; class AttributeFilter extends AbstractFilter { @@ -37,14 +39,13 @@ class AttributeFilter extends AbstractFilter { public static class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { + public List getFilters() { final String packageName = cgeoapplication.getInstance().getBaseContext().getPackageName(); final Resources res = cgeoapplication.getInstance().getResources(); - final String[] ids = res.getStringArray(R.array.attribute_ids); - final IFilter[] filters = new IFilter[ids.length]; - for (int i = 0; i < ids.length; i++) { - filters[i] = new AttributeFilter(getName("attribute_" + ids[i], res, packageName), ids[i]); + final List filters = new LinkedList(); + for (final String id: res.getStringArray(R.array.attribute_ids)) { + filters.add(new AttributeFilter(getName("attribute_" + id, res, packageName), id)); } return filters; } diff --git a/main/src/cgeo/geocaching/filter/DifficultyFilter.java b/main/src/cgeo/geocaching/filter/DifficultyFilter.java index c0ec61a..8099a51 100644 --- a/main/src/cgeo/geocaching/filter/DifficultyFilter.java +++ b/main/src/cgeo/geocaching/filter/DifficultyFilter.java @@ -4,6 +4,7 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import java.util.ArrayList; +import java.util.List; class DifficultyFilter extends AbstractRangeFilter { @@ -19,12 +20,12 @@ class DifficultyFilter extends AbstractRangeFilter { public static class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { + public List getFilters() { final ArrayList filters = new ArrayList(5); for (int difficulty = 1; difficulty <= 5; difficulty++) { filters.add(new DifficultyFilter(difficulty)); } - return filters.toArray(new IFilter[filters.size()]); + return filters; } } diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java index be63a08..a1d42cc 100644 --- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java +++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java @@ -16,6 +16,7 @@ import android.widget.ArrayAdapter; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; public final class FilterUserInterface { @@ -101,9 +102,9 @@ public final class FilterUserInterface { } private void selectFromFactory(final IFilterFactory factory, final String menuTitle, final RunnableWithArgument runAfterwards) { - final IFilter[] filters = factory.getFilters(); - if (filters.length == 1) { - runAfterwards.run(filters[0]); + final List filters = Collections.unmodifiableList(factory.getFilters()); + if (filters.size() == 1) { + runAfterwards.run(filters.get(0)); return; } @@ -114,7 +115,7 @@ public final class FilterUserInterface { builder.setAdapter(adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int item) { - runAfterwards.run(filters[item]); + runAfterwards.run(filters.get(item)); } }); diff --git a/main/src/cgeo/geocaching/filter/IFilterFactory.java b/main/src/cgeo/geocaching/filter/IFilterFactory.java index 3491fd7..e750639 100644 --- a/main/src/cgeo/geocaching/filter/IFilterFactory.java +++ b/main/src/cgeo/geocaching/filter/IFilterFactory.java @@ -1,5 +1,7 @@ package cgeo.geocaching.filter; +import java.util.List; + interface IFilterFactory { - public IFilter[] getFilters(); + public List getFilters(); } diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java index f3e57de..74befda 100644 --- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java +++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java @@ -4,6 +4,9 @@ import cgeo.geocaching.Geocache; import cgeo.geocaching.R; import cgeo.geocaching.cgeoapplication; +import java.util.Collections; +import java.util.List; + class ModifiedFilter extends AbstractFilter implements IFilterFactory { public ModifiedFilter() { @@ -17,7 +20,7 @@ class ModifiedFilter extends AbstractFilter implements IFilterFactory { } @Override - public IFilter[] getFilters() { - return new IFilter[] { this }; + public List getFilters() { + return Collections.singletonList(this); } } diff --git a/main/src/cgeo/geocaching/filter/OriginFilter.java b/main/src/cgeo/geocaching/filter/OriginFilter.java index a880092..bd4e41e 100644 --- a/main/src/cgeo/geocaching/filter/OriginFilter.java +++ b/main/src/cgeo/geocaching/filter/OriginFilter.java @@ -7,6 +7,7 @@ import cgeo.geocaching.connector.IConnector; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; public class OriginFilter extends AbstractFilter { @@ -25,7 +26,7 @@ public class OriginFilter extends AbstractFilter { public static final class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { + public List getFilters() { final ArrayList filters = new ArrayList(); for (IConnector connector : ConnectorFactory.getConnectors()) { filters.add(new OriginFilter(connector)); @@ -40,7 +41,7 @@ public class OriginFilter extends AbstractFilter { } }); - return filters.toArray(new OriginFilter[filters.size()]); + return filters; } } diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java index 7a34c83..8ddc475 100644 --- a/main/src/cgeo/geocaching/filter/SizeFilter.java +++ b/main/src/cgeo/geocaching/filter/SizeFilter.java @@ -3,7 +3,8 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheSize; -import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; class SizeFilter extends AbstractFilter { private final CacheSize cacheSize; @@ -26,15 +27,15 @@ class SizeFilter extends AbstractFilter { public static class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { + public List getFilters() { final CacheSize[] cacheSizes = CacheSize.values(); - final ArrayList filters = new ArrayList(); + final List filters = new LinkedList(); for (CacheSize cacheSize : cacheSizes) { if (cacheSize != CacheSize.UNKNOWN) { filters.add(new SizeFilter(cacheSize)); } } - return filters.toArray(new SizeFilter[filters.size()]); + return filters; } } diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java index 0df47c1..ae3fac2 100644 --- a/main/src/cgeo/geocaching/filter/StateFilter.java +++ b/main/src/cgeo/geocaching/filter/StateFilter.java @@ -9,6 +9,7 @@ import android.content.res.Resources; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; abstract class StateFilter extends AbstractFilter { @@ -89,8 +90,8 @@ abstract class StateFilter extends AbstractFilter { public static class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { - final ArrayList filters = new ArrayList(); + public List getFilters() { + final List filters = new ArrayList(6); filters.add(new StateFoundFilter()); filters.add(new StateArchivedFilter()); filters.add(new StateDisabledFilter()); @@ -106,7 +107,7 @@ abstract class StateFilter extends AbstractFilter { } }); - return filters.toArray(new StateFilter[filters.size()]); + return filters; } } diff --git a/main/src/cgeo/geocaching/filter/TerrainFilter.java b/main/src/cgeo/geocaching/filter/TerrainFilter.java index f7703d5..87372c6 100644 --- a/main/src/cgeo/geocaching/filter/TerrainFilter.java +++ b/main/src/cgeo/geocaching/filter/TerrainFilter.java @@ -1,10 +1,10 @@ package cgeo.geocaching.filter; - -import cgeo.geocaching.R; import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; import java.util.ArrayList; +import java.util.List; class TerrainFilter extends AbstractRangeFilter { @@ -19,12 +19,12 @@ class TerrainFilter extends AbstractRangeFilter { public static class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { + public List getFilters() { final ArrayList filters = new ArrayList(5); for (int terrain = 1; terrain <= 5; terrain++) { filters.add(new TerrainFilter(terrain)); } - return filters.toArray(new IFilter[filters.size()]); + return filters; } } diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java index 3225daa..5eff8a7 100644 --- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java +++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java @@ -1,9 +1,12 @@ package cgeo.geocaching.filter; -import cgeo.geocaching.R; import cgeo.geocaching.Geocache; +import cgeo.geocaching.R; import cgeo.geocaching.cgeoapplication; +import java.util.Collections; +import java.util.List; + class TrackablesFilter extends AbstractFilter implements IFilterFactory { public TrackablesFilter() { super(cgeoapplication.getInstance().getString(R.string.caches_filter_track)); @@ -15,8 +18,8 @@ class TrackablesFilter extends AbstractFilter implements IFilterFactory { } @Override - public IFilter[] getFilters() { - return new IFilter[] { this }; + public List getFilters() { + return Collections.singletonList(this); } } diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java index eeab552..ea0ccff 100644 --- a/main/src/cgeo/geocaching/filter/TypeFilter.java +++ b/main/src/cgeo/geocaching/filter/TypeFilter.java @@ -3,7 +3,8 @@ package cgeo.geocaching.filter; import cgeo.geocaching.Geocache; import cgeo.geocaching.enumerations.CacheType; -import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; class TypeFilter extends AbstractFilter { private final CacheType cacheType; @@ -26,15 +27,15 @@ class TypeFilter extends AbstractFilter { public static class Factory implements IFilterFactory { @Override - public IFilter[] getFilters() { + public List getFilters() { final CacheType[] types = CacheType.values(); - final ArrayList filters = new ArrayList(types.length); + final List filters = new LinkedList(); for (CacheType cacheType : types) { if (cacheType != CacheType.ALL) { filters.add(new TypeFilter(cacheType)); } } - return filters.toArray(new IFilter[filters.size()]); + return filters; } } -- cgit v1.1 From e3c3b9bb066db079ac293052bc5dbcf2ba6f9bb4 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 21:05:23 +0200 Subject: fix #2585: log progress dismissed when tapping on screen Use AsyncTaskWithProgress to factor out code at the same time. --- main/src/cgeo/geocaching/VisitCacheActivity.java | 137 +++++++++-------------- 1 file changed, 56 insertions(+), 81 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index f8232af..8957aa1 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -12,6 +12,7 @@ import cgeo.geocaching.network.Parameters; import cgeo.geocaching.twitter.Twitter; import cgeo.geocaching.ui.Formatter; import cgeo.geocaching.ui.dialog.DateDialog; +import cgeo.geocaching.utils.AsyncTaskWithProgress; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.LogTemplateProvider; import cgeo.geocaching.utils.LogTemplateProvider.LogContext; @@ -20,17 +21,15 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; +import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; -import android.app.ProgressDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.util.SparseArray; @@ -67,7 +66,6 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD private LayoutInflater inflater = null; private Geocache cache = null; - private ProgressDialog waitDialog = null; private String cacheid = null; private String geocode = null; private String text = null; @@ -240,34 +238,6 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD return res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*"; } - private final Handler postLogHandler = new Handler() { - - @Override - public void handleMessage(final Message msg) { - if (waitDialog != null) { - waitDialog.dismiss(); - } - - final StatusCode error = (StatusCode) msg.obj; - if (error == StatusCode.NO_ERROR) { - showToast(res.getString(R.string.info_log_posted)); - // No need to save the log when quitting if it has been posted. - text = currentLogText(); - finish(); - } else if (error == StatusCode.LOG_SAVED) { - showToast(res.getString(R.string.info_log_saved)); - - if (waitDialog != null) { - waitDialog.dismiss(); - } - - finish(); - } else { - showToast(error.getErrorString(res)); - } - } - }; - public VisitCacheActivity() { super("c:geo-log"); } @@ -543,75 +513,80 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD private class PostListener implements View.OnClickListener { @Override public void onClick(View arg0) { - waitDialog = ProgressDialog.show(VisitCacheActivity.this, null, - res.getString(StringUtils.isBlank(imageUri.getPath()) ? R.string.log_saving : R.string.log_saving_and_uploading), true); - waitDialog.setCancelable(true); - - final Thread thread = new PostLogThread(postLogHandler, currentLogText()); - thread.start(); + final String message = res.getString(StringUtils.isBlank(imageUri.getPath()) ? + R.string.log_saving : + R.string.log_saving_and_uploading); + new Poster(VisitCacheActivity.this, message).execute(currentLogText()); } } - private class PostLogThread extends Thread { + private class Poster extends AsyncTaskWithProgress { - private final Handler handler; - private final String log; - - public PostLogThread(Handler handlerIn, String logIn) { - super("Post log"); - handler = handlerIn; - log = logIn; + public Poster(final Activity activity, final String progressMessage) { + super(activity, 0, null, progressMessage); } @Override - public void run() { - final StatusCode status = postLogFn(log); - handler.sendMessage(handler.obtainMessage(0, status)); - } - } + protected StatusCode doInBackground(final String... args) { + final String log = args[0]; + try { + final ImmutablePair postResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, + date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), + log, trackables); - public StatusCode postLogFn(String log) { - try { - final ImmutablePair postResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, - date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), - log, trackables); + if (postResult.left == StatusCode.NO_ERROR) { + final LogEntry logNow = new LogEntry(date, typeSelected, log); - if (postResult.left == StatusCode.NO_ERROR) { - final LogEntry logNow = new LogEntry(date, typeSelected, log); + cache.getLogs().add(0, logNow); - cache.getLogs().add(0, logNow); - - if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) { - cache.setFound(true); - } + if (typeSelected == LogType.FOUND_IT || typeSelected == LogType.ATTENDED) { + cache.setFound(true); + } - cgData.saveChangedCache(cache); - cgData.clearLogOffline(geocode); + cgData.saveChangedCache(cache); + cgData.clearLogOffline(geocode); - if (typeSelected == LogType.FOUND_IT) { - if (tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) { - Twitter.postTweetCache(geocode); + if (typeSelected == LogType.FOUND_IT) { + if (tweetCheck.isChecked() && tweetBox.getVisibility() == View.VISIBLE) { + Twitter.postTweetCache(geocode); + } + GCVote.setRating(cache, rating); } - GCVote.setRating(cache, rating); - } - if (StringUtils.isNotBlank(imageUri.getPath())) { - ImmutablePair imageResult = GCParser.uploadLogImage(postResult.right, imageCaption, imageDescription, imageUri); - final String uploadedImageUrl = imageResult.right; - if (StringUtils.isNotEmpty(uploadedImageUrl)) { - logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription)); - cgData.saveChangedCache(cache); + if (StringUtils.isNotBlank(imageUri.getPath())) { + ImmutablePair imageResult = GCParser.uploadLogImage(postResult.right, imageCaption, imageDescription, imageUri); + final String uploadedImageUrl = imageResult.right; + if (StringUtils.isNotEmpty(uploadedImageUrl)) { + logNow.addLogImage(new Image(uploadedImageUrl, imageCaption, imageDescription)); + cgData.saveChangedCache(cache); + } + return imageResult.left; } - return imageResult.left; } + + return postResult.left; + } catch (Exception e) { + Log.e("cgeovisit.postLogFn", e); } - return postResult.left; - } catch (Exception e) { - Log.e("cgeovisit.postLogFn", e); + return StatusCode.LOG_POST_ERROR; } - return StatusCode.LOG_POST_ERROR; + @Override + protected void onPostExecute(final StatusCode status) { + super.onPostExecute(status); + if (status == StatusCode.NO_ERROR) { + showToast(res.getString(R.string.info_log_posted)); + // No need to save the log when quitting if it has been posted. + text = currentLogText(); + finish(); + } else if (status == StatusCode.LOG_SAVED) { + showToast(res.getString(R.string.info_log_saved)); + finish(); + } else { + showToast(status.getErrorString(res)); + } + } } private void saveLog(final boolean force) { -- cgit v1.1 From 990b75b58d3c2d274028a3253f28364ee115a460 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sat, 6 Apr 2013 21:48:25 +0200 Subject: refactoring: prefer StringUtils.defaultIfBlank over an explicit test --- main/src/cgeo/geocaching/Geocache.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/Geocache.java b/main/src/cgeo/geocaching/Geocache.java index 96bb2fe..4b78e4d 100644 --- a/main/src/cgeo/geocaching/Geocache.java +++ b/main/src/cgeo/geocaching/Geocache.java @@ -711,10 +711,7 @@ public class Geocache implements ICache, IWaypoint { public String getPersonalNote() { // non premium members have no personal notes, premium members have an empty string by default. // map both to null, so other code doesn't need to differentiate - if (StringUtils.isBlank(personalNote)) { - return null; - } - return personalNote; + return StringUtils.defaultIfBlank(personalNote, null); } public boolean supportsUserActions() { -- cgit v1.1 From 325c9aad24d3aa2e2582cbc5e2d9ae815583b94a Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 7 Apr 2013 08:33:59 +0200 Subject: refactoring: make API of AsyncTaskWithProgress more explicit --- main/src/cgeo/geocaching/VisitCacheActivity.java | 9 +- .../cgeo/geocaching/export/FieldnoteExport.java | 29 +++---- main/src/cgeo/geocaching/export/GpxExport.java | 44 +++++----- .../geocaching/utils/AsyncTaskWithProgress.java | 99 +++++++++++++++++----- 4 files changed, 119 insertions(+), 62 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java index 8957aa1..74890f4 100644 --- a/main/src/cgeo/geocaching/VisitCacheActivity.java +++ b/main/src/cgeo/geocaching/VisitCacheActivity.java @@ -523,12 +523,12 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD private class Poster extends AsyncTaskWithProgress { public Poster(final Activity activity, final String progressMessage) { - super(activity, 0, null, progressMessage); + super(activity, null, progressMessage, true); } @Override - protected StatusCode doInBackground(final String... args) { - final String log = args[0]; + protected StatusCode doInBackgroundInternal(final String[] logTexts) { + final String log = logTexts[0]; try { final ImmutablePair postResult = GCParser.postLog(geocode, cacheid, viewstates, typeSelected, date.get(Calendar.YEAR), (date.get(Calendar.MONTH) + 1), date.get(Calendar.DATE), @@ -573,8 +573,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD } @Override - protected void onPostExecute(final StatusCode status) { - super.onPostExecute(status); + protected void onPostExecuteInternal(final StatusCode status) { if (status == StatusCode.NO_ERROR) { showToast(res.getString(R.string.info_log_posted)); // No need to save the log when quitting if it has been posted. diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java index eadcb77..2900781 100644 --- a/main/src/cgeo/geocaching/export/FieldnoteExport.java +++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java @@ -56,18 +56,19 @@ class FieldnoteExport extends AbstractExport { } @Override - public void export(final List caches, final Activity activity) { + public void export(final List cachesList, final Activity activity) { + final Geocache[] caches = cachesList.toArray(new Geocache[cachesList.size()]); if (null == activity) { // No activity given, so no user interaction possible. // Start export with default parameters. - new ExportTask(caches, null, false, false).execute((Void) null); + new ExportTask(null, false, false).execute(caches); } else { // Show configuration dialog getExportOptionsDialog(caches, activity).show(); } } - private Dialog getExportOptionsDialog(final List caches, final Activity activity) { + private Dialog getExportOptionsDialog(final Geocache[] caches, final Activity activity) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); // AlertDialog has always dark style, so we have to apply it as well always @@ -90,19 +91,17 @@ class FieldnoteExport extends AbstractExport { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); new ExportTask( - caches, activity, uploadOption.isChecked(), onlyNewOption.isChecked()) - .execute((Void) null); + .execute(caches); } }); return builder.create(); } - private class ExportTask extends AsyncTaskWithProgress { - private final List caches; + private class ExportTask extends AsyncTaskWithProgress { private final Activity activity; private final boolean upload; private final boolean onlyNew; @@ -113,8 +112,6 @@ class FieldnoteExport extends AbstractExport { /** * Instantiates and configures the task for exporting field notes. * - * @param caches - * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported * @param activity * optional: Show a progress bar and toasts * @param upload @@ -122,16 +119,15 @@ class FieldnoteExport extends AbstractExport { * @param onlyNew * Upload/export only new logs since last export */ - public ExportTask(final List caches, final Activity activity, final boolean upload, final boolean onlyNew) { + public ExportTask(final Activity activity, final boolean upload, final boolean onlyNew) { super(activity, getProgressTitle(), getString(R.string.export_fieldnotes_creating)); - this.caches = caches; this.activity = activity; this.upload = upload; this.onlyNew = onlyNew; } @Override - protected Boolean doInBackground(Void... params) { + protected Boolean doInBackgroundInternal(Geocache[] caches) { final StringBuilder fieldNoteBuffer = new StringBuilder(); try { int i = 0; @@ -219,8 +215,7 @@ class FieldnoteExport extends AbstractExport { } @Override - protected void onPostExecute(Boolean result) { - super.onPostExecute(result); + protected void onPostExecuteInternal(Boolean result) { if (null != activity) { if (result) { // if (onlyNew) { @@ -239,12 +234,12 @@ class FieldnoteExport extends AbstractExport { } @Override - protected void onProgressUpdate(Integer... status) { + protected void onProgressUpdateInternal(int status) { if (null != activity) { - if (STATUS_UPLOAD == status[0]) { + if (STATUS_UPLOAD == status) { setMessage(getString(R.string.export_fieldnotes_uploading)); } else { - setMessage(getString(R.string.export_fieldnotes_creating) + " (" + status[0] + ')'); + setMessage(getString(R.string.export_fieldnotes_creating) + " (" + status + ')'); } } } diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java index 4c5d1e2..c6f72fd 100644 --- a/main/src/cgeo/geocaching/export/GpxExport.java +++ b/main/src/cgeo/geocaching/export/GpxExport.java @@ -5,9 +5,9 @@ import cgeo.geocaching.LogEntry; import cgeo.geocaching.R; import cgeo.geocaching.Settings; import cgeo.geocaching.Waypoint; -import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; +import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.enumerations.CacheAttribute; import cgeo.geocaching.enumerations.LoadFlags; import cgeo.geocaching.geopoint.Geopoint; @@ -37,6 +37,7 @@ import java.io.FileWriter; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; @@ -60,18 +61,19 @@ class GpxExport extends AbstractExport { @Override public void export(final List caches, final Activity activity) { + String[] geocodes = getGeocodes(caches); if (null == activity) { // No activity given, so no user interaction possible. // Start export with default parameters. - new ExportTask(caches, null).execute((Void) null); + new ExportTask(null).execute(geocodes); } else { // Show configuration dialog - getExportDialog(caches, activity).show(); + getExportDialog(geocodes, activity).show(); } } - private Dialog getExportDialog(final List caches, final Activity activity) { + private Dialog getExportDialog(final String[] geocodes, final Activity activity) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); // AlertDialog has always dark style, so we have to apply it as well always @@ -97,44 +99,47 @@ class GpxExport extends AbstractExport { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); - new ExportTask(caches, activity).execute((Void) null); + new ExportTask(activity).execute(geocodes); } }); return builder.create(); } - private class ExportTask extends AsyncTaskWithProgress { - private final List allGeocodes; + private static String[] getGeocodes(final List caches) { + ArrayList allGeocodes = new ArrayList(caches.size()); + for (final Geocache geocache : caches) { + allGeocodes.add(geocache.getGeocode()); + } + return allGeocodes.toArray(new String[allGeocodes.size()]); + } + + private class ExportTask extends AsyncTaskWithProgress { private final Activity activity; private int countExported = 0; /** * Instantiates and configures the task for exporting field notes. * - * @param caches - * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported * @param activity * optional: Show a progress bar and toasts */ - public ExportTask(final List caches, final Activity activity) { - super(activity, caches.size(), getProgressTitle(), cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, caches.size(), caches.size())); - - // get rid of the (half loaded) caches, we will reload them as full caches during the export - allGeocodes = new ArrayList(caches.size()); - for (final Geocache geocache : caches) { - allGeocodes.add(geocache.getGeocode()); - } + public ExportTask(final Activity activity) { + super(activity, getProgressTitle()); this.activity = activity; } @Override - protected File doInBackground(Void... params) { + protected File doInBackgroundInternal(String[] geocodes) { // quick check for being able to write the GPX file if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { return null; } + List allGeocodes = new ArrayList(Arrays.asList(geocodes)); + + setMessage(cgeoapplication.getInstance().getResources().getQuantityString(R.plurals.cache_counts, allGeocodes.size(), allGeocodes.size())); + final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); final File exportFile = new File(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(new Date()) + ".gpx"); FileWriter writer = null; @@ -359,8 +364,7 @@ class GpxExport extends AbstractExport { } @Override - protected void onPostExecute(final File exportFile) { - super.onPostExecute(exportFile); + protected void onPostExecuteInternal(final File exportFile) { if (null != activity) { if (exportFile != null) { ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString()); diff --git a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java index b23fa9d..7526d92 100644 --- a/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java +++ b/main/src/cgeo/geocaching/utils/AsyncTaskWithProgress.java @@ -8,8 +8,12 @@ import android.os.AsyncTask; /** * AsyncTask which automatically shows a progress dialog. Use it like the {@code AsyncTask} class, but leave away the - * middle template parameter. - * + * middle template parameter. Override {@link #doInBackgroundInternal(Object[])} and related methods. + *

+ * If no style is given, the progress dialog uses "determinate" style with known maximum. The progress maximum is + * automatically derived from the number of {@code Params} given to the task in {@link #execute(Object...)}. + *

+ * * @param * @param */ @@ -17,64 +21,119 @@ public abstract class AsyncTaskWithProgress extends AsyncTask= 0) { + progress.setProgress(progressValue); } + onProgressUpdateInternal(progressValue); + } + + /** + * This method should by overridden by sub classes instead of {@link #onProgressUpdate(Integer...)}. + */ + protected void onProgressUpdateInternal(@SuppressWarnings("unused") int progress) { + // empty by default } protected void setMessage(final String message) { progress.setMessage(message); } + + @Override + protected final Result doInBackground(Params... params) { + if (params != null) { + progress.setMaxProgressAndReset(params.length); + } + return doInBackgroundInternal(params); + } + + protected abstract Result doInBackgroundInternal(Params[] params); } -- cgit v1.1 From 0518f75e136d51260164bb2681b03353b65b6ba5 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 09:14:32 +0200 Subject: refactoring: remove empty statements --- main/src/cgeo/geocaching/cgeo.java | 3 +-- main/src/cgeo/geocaching/maps/CGeoMap.java | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java index 5680ff3..0140c3a 100644 --- a/main/src/cgeo/geocaching/cgeo.java +++ b/main/src/cgeo/geocaching/cgeo.java @@ -311,6 +311,7 @@ public class cgeo extends AbstractActivity { @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == SCAN_REQUEST_CODE) { + // Only handle positive results, don't do anything if cancelled. if (resultCode == RESULT_OK) { String scan = intent.getStringExtra("SCAN_RESULT"); if (StringUtils.isBlank(scan)) { @@ -318,8 +319,6 @@ public class cgeo extends AbstractActivity { } SearchActivity.startActivityScan(scan, this); - } else if (resultCode == RESULT_CANCELED) { - // do nothing } } else if (requestCode == SEARCH_REQUEST_CODE) { // SearchActivity activity returned without making a search diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index f2e455c..e305b20 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -750,9 +750,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto @Override public void onClick(DialogInterface dialog, int newItem) { - if (newItem == selectedItem) { - // no change - } else { + if (newItem != selectedItem) { // Adjust index because of selection if (newItem > 0) { Settings.setCustomRenderThemeFile(themeFiles[newItem - 1].getPath()); -- cgit v1.1 From 1d1a6b02b77f65b1e9271acd56514fc443fdce4e Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 09:18:03 +0200 Subject: refactoring: remove redundant type casts getParcelable() does not return a Parcelable, it returns a T where T is a generic type deriving from Parcelable. Those type casts will be done automatically and do not need to be spelled out explicitely. --- main/src/cgeo/geocaching/cgeocaches.java | 2 +- main/src/cgeo/geocaching/cgeonavigate.java | 2 +- main/src/cgeo/geocaching/maps/CGeoMap.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index a8e798f..66333d4 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -428,7 +428,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity if (extras != null) { Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE); type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE; - coords = (Geopoint) extras.getParcelable(Intents.EXTRAS_COORDS); + coords = extras.getParcelable(Intents.EXTRAS_COORDS); } else { extras = new Bundle(); diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java index 17c2e20..929f0a3 100644 --- a/main/src/cgeo/geocaching/cgeonavigate.java +++ b/main/src/cgeo/geocaching/cgeonavigate.java @@ -63,7 +63,7 @@ public class cgeonavigate extends AbstractActivity { if (extras != null) { title = extras.getString(EXTRAS_GEOCODE); final String name = extras.getString(EXTRAS_NAME); - dstCoords = (Geopoint) extras.getParcelable(EXTRAS_COORDS); + dstCoords = extras.getParcelable(EXTRAS_COORDS); info = extras.getString(EXTRAS_CACHE_INFO); if (StringUtils.isNotBlank(name)) { diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java index e305b20..21c4984 100644 --- a/main/src/cgeo/geocaching/maps/CGeoMap.java +++ b/main/src/cgeo/geocaching/maps/CGeoMap.java @@ -382,9 +382,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto if (extras != null) { mapMode = (MapMode) extras.get(EXTRAS_MAP_MODE); isLiveEnabled = extras.getBoolean(EXTRAS_LIVE_ENABLED, false); - searchIntent = (SearchResult) extras.getParcelable(EXTRAS_SEARCH); + searchIntent = extras.getParcelable(EXTRAS_SEARCH); geocodeIntent = extras.getString(EXTRAS_GEOCODE); - coordsIntent = (Geopoint) extras.getParcelable(EXTRAS_COORDS); + coordsIntent = extras.getParcelable(EXTRAS_COORDS); waypointTypeIntent = WaypointType.findById(extras.getString(EXTRAS_WPTTYPE)); mapStateIntent = extras.getIntArray(EXTRAS_MAPSTATE); mapTitle = extras.getString(EXTRAS_MAP_TITLE); -- cgit v1.1 From 566f67a196b8aaa9fd29b05c18ddd4e767b3b3f3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 09:20:55 +0200 Subject: refactoring: remove unused warnings on mandatory parameters --- main/src/cgeo/geocaching/cgeocaches.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 66333d4..657b06d 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -1445,7 +1445,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity * @param view * unused here but needed since this method is referenced from XML layout */ - public void selectList(View view) { + public void selectList(@SuppressWarnings("unused") View view) { if (type != CacheListType.OFFLINE) { return; } @@ -1544,7 +1544,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity * @param view * unused here but needed since this method is referenced from XML layout */ - public void goMap(View view) { + public void goMap(@SuppressWarnings("unused") View view) { if (search == null || CollectionUtils.isEmpty(cacheList)) { showToast(res.getString(R.string.warn_no_cache_coord)); -- cgit v1.1 From ba2a3ed0e0a02e90552b6605a94cb47d093c782e Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 7 Apr 2013 09:47:52 +0200 Subject: fix #2542: NPE when deleting list with all caches in it --- main/src/cgeo/geocaching/cgeocaches.java | 62 +++++++++++++++----------------- 1 file changed, 28 insertions(+), 34 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 657b06d..bcd9531 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -39,6 +39,7 @@ import cgeo.geocaching.sorting.VisitComparator; import cgeo.geocaching.ui.CacheListAdapter; import cgeo.geocaching.ui.LoggingUI; import cgeo.geocaching.ui.WeakReferenceHandler; +import cgeo.geocaching.utils.AsyncTaskWithProgress; import cgeo.geocaching.utils.DateUtils; import cgeo.geocaching.utils.GeoDirHandler; import cgeo.geocaching.utils.Log; @@ -74,6 +75,7 @@ import android.widget.ListView; import android.widget.TextView; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashSet; @@ -373,21 +375,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } }; - private Handler dropDetailsHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - if (msg.what != MSG_CANCEL) { - adapter.setSelectMode(false); - - refreshCurrentList(); - - replaceCacheListFromSearch(); - - progress.dismiss(); - } - } - }; private Handler clearOfflineLogsHandler = new Handler() { @Override @@ -794,7 +781,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } public void deletePastEvents() { - progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL)); final List deletion = new ArrayList(); for (Geocache cache : adapter.getCheckedOrAllCaches()) { if (cache.isEventCache()) { @@ -804,7 +790,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } } - new DropDetailsThread(dropDetailsHandler, deletion).start(); + new DropDetailsTask(false).execute(deletion.toArray(new Geocache[deletion.size()])); } public void clearOfflineLogs() { @@ -1177,10 +1163,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity @Override public void onClick(DialogInterface dialog, int id) { - dropSelected(); - if (removeListAfterwards) { - removeList(false); - } + dropSelected(removeListAfterwards); dialog.cancel(); } }); @@ -1196,9 +1179,9 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity alert.show(); } - public void dropSelected() { - progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL)); - new DropDetailsThread(dropDetailsHandler, adapter.getCheckedOrAllCaches()).start(); + public void dropSelected(boolean removeListAfterwards) { + final List selected = adapter.getCheckedOrAllCaches(); + new DropDetailsTask(removeListAfterwards).execute(selected.toArray(new Geocache[selected.size()])); } /** @@ -1383,24 +1366,35 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } - private class DropDetailsThread extends Thread { + private class DropDetailsTask extends AsyncTaskWithProgress { - final private Handler handler; - final private List selected; + private final boolean removeListAfterwards; - public DropDetailsThread(Handler handlerIn, List selectedIn) { - handler = handlerIn; - selected = selectedIn; + public DropDetailsTask(boolean removeListAfterwards) { + super(cgeocaches.this, null, res.getString(R.string.caches_drop_progress), true); + this.removeListAfterwards = removeListAfterwards; } @Override - public void run() { + protected Void doInBackgroundInternal(Geocache[] caches) { removeGeoAndDir(); - cgData.markDropped(selected); - handler.sendEmptyMessage(MSG_DONE); - + cgData.markDropped(Arrays.asList(caches)); startGeoAndDir(); + return null; + } + + @Override + protected void onPostExecuteInternal(Void result) { + // remove list in UI because of toast + if (removeListAfterwards) { + removeList(false); + } + + adapter.setSelectMode(false); + refreshCurrentList(); + replaceCacheListFromSearch(); } + } private class ClearOfflineLogsThread extends Thread { -- cgit v1.1 From 5a7ff22ff39d8726bdbbdd21364f23bcbd31de04 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 10:19:48 +0200 Subject: Add method documentation --- main/src/cgeo/geocaching/AbstractPopupActivity.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java index a7d1107..44acfc5 100644 --- a/main/src/cgeo/geocaching/AbstractPopupActivity.java +++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java @@ -74,8 +74,13 @@ public abstract class AbstractPopupActivity extends AbstractActivity { } }; + /** + * Callback to run when new location information is available. + * This may be overriden by deriving classes. The default implementation does nothing. + * + * @param geo the new data + */ public void onUpdateGeoData(final IGeoData geo) { - } protected AbstractPopupActivity(String helpTopic, int layout) { -- cgit v1.1 From 777d113d77f1d384001d7ca2f75958871a70b26b Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 12:54:22 +0200 Subject: Rename EXTRAS_COORDS into the more correct EXTRA_COORDS --- main/src/cgeo/geocaching/Intents.java | 2 +- main/src/cgeo/geocaching/cgeocaches.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java index 7f0a004..db4f245 100644 --- a/main/src/cgeo/geocaching/Intents.java +++ b/main/src/cgeo/geocaching/Intents.java @@ -9,7 +9,7 @@ public class Intents { private static final String PREFIX = "cgeo.geocaching.intent.extra."; public static final String EXTRA_ADDRESS = PREFIX + "address"; - public static final String EXTRAS_COORDS = PREFIX + "coords"; + public static final String EXTRA_COORDS = PREFIX + "coords"; public static final String EXTRA_COUNT = PREFIX + "count"; public static final String EXTRA_GEOCODE = PREFIX + "geocode"; public static final String EXTRA_GUID = PREFIX + "guid"; diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index bcd9531..30a18c5 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -415,7 +415,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity if (extras != null) { Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE); type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE; - coords = extras.getParcelable(Intents.EXTRAS_COORDS); + coords = extras.getParcelable(Intents.EXTRA_COORDS); } else { extras = new Bundle(); @@ -1661,7 +1661,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } final Intent cachesIntent = new Intent(context, cgeocaches.class); cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.NEAREST); - cachesIntent.putExtra(Intents.EXTRAS_COORDS, coordsNow); + cachesIntent.putExtra(Intents.EXTRA_COORDS, coordsNow); context.startActivity(cachesIntent); } @@ -1674,7 +1674,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity public static void startActivityAddress(final Context context, final Geopoint coords, final String address) { final Intent addressIntent = new Intent(context, cgeocaches.class); addressIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.ADDRESS); - addressIntent.putExtra(Intents.EXTRAS_COORDS, coords); + addressIntent.putExtra(Intents.EXTRA_COORDS, coords); addressIntent.putExtra(Intents.EXTRA_ADDRESS, address); context.startActivity(addressIntent); } @@ -1685,7 +1685,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } final Intent cachesIntent = new Intent(context, cgeocaches.class); cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.COORDINATE); - cachesIntent.putExtra(Intents.EXTRAS_COORDS, coords); + cachesIntent.putExtra(Intents.EXTRA_COORDS, coords); context.startActivity(cachesIntent); } -- cgit v1.1 From c1b68d1b4b5d73afe60dcbbe03e9d3fd12f428b0 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 12:55:33 +0200 Subject: Put EXTRA parameters into the Intent class --- main/src/cgeo/geocaching/ImagesActivity.java | 16 ++++++---------- main/src/cgeo/geocaching/Intents.java | 2 ++ 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java index 24f699e..de84af2 100644 --- a/main/src/cgeo/geocaching/ImagesActivity.java +++ b/main/src/cgeo/geocaching/ImagesActivity.java @@ -19,10 +19,6 @@ import java.util.List; public class ImagesActivity extends AbstractActivity { - private static final String EXTRAS_IMAGES = "images"; - private static final String EXTRAS_TYPE = "type"; - private static final String EXTRAS_GEOCODE = "geocode"; - private boolean offline; private ArrayList imageNames; private ImagesList imagesList; @@ -37,8 +33,8 @@ public class ImagesActivity extends AbstractActivity { String geocode = null; if (extras != null) { - geocode = extras.getString(EXTRAS_GEOCODE); - imgType = (ImageType) extras.getSerializable(EXTRAS_TYPE); + geocode = extras.getString(Intents.EXTRA_GEOCODE); + imgType = (ImageType) extras.getSerializable(Intents.EXTRA_TYPE); } if (extras == null || geocode == null) { @@ -54,7 +50,7 @@ public class ImagesActivity extends AbstractActivity { imagesList = new ImagesList(this, geocode); - imageNames = extras.getParcelableArrayList(EXTRAS_IMAGES); + imageNames = extras.getParcelableArrayList(Intents.EXTRA_IMAGES); if (CollectionUtils.isEmpty(imageNames)) { showToast(res.getString(R.string.warn_load_images)); finish(); @@ -85,12 +81,12 @@ public class ImagesActivity extends AbstractActivity { final Intent logImgIntent = new Intent(fromActivity, ImagesActivity.class); // if resuming our app within this activity, finish it and return to the cache activity logImgIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) - .putExtra(EXTRAS_GEOCODE, geocode) - .putExtra(EXTRAS_TYPE, imageType); + .putExtra(Intents.EXTRA_GEOCODE, geocode) + .putExtra(Intents.EXTRA_TYPE, imageType); // avoid forcing the array list as parameter type final ArrayList arrayList = new ArrayList(logImages); - logImgIntent.putParcelableArrayListExtra(EXTRAS_IMAGES, arrayList); + logImgIntent.putParcelableArrayListExtra(Intents.EXTRA_IMAGES, arrayList); fromActivity.startActivity(logImgIntent); } diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java index db4f245..a700451 100644 --- a/main/src/cgeo/geocaching/Intents.java +++ b/main/src/cgeo/geocaching/Intents.java @@ -13,6 +13,7 @@ public class Intents { public static final String EXTRA_COUNT = PREFIX + "count"; public static final String EXTRA_GEOCODE = PREFIX + "geocode"; public static final String EXTRA_GUID = PREFIX + "guid"; + public static final String EXTRA_IMAGES = PREFIX + "images"; public static final String EXTRA_ID = PREFIX + "id"; public static final String EXTRA_KEYWORD = PREFIX + "keyword"; public static final String EXTRA_KEYWORD_SEARCH = PREFIX + "keyword_search"; @@ -23,6 +24,7 @@ public class Intents { public static final String EXTRA_SEARCH = PREFIX + "search"; public static final String EXTRA_START_DIR = PREFIX + "start_dir"; public static final String EXTRA_TRACKING_CODE = PREFIX + "tracking_code"; + public static final String EXTRA_TYPE = PREFIX + "type"; public static final String EXTRA_USERNAME = PREFIX + "username"; public static final String EXTRA_WAYPOINT_ID = PREFIX + "waypoint_id"; public static final String EXTRA_CACHELIST = PREFIX + "cache_list"; -- cgit v1.1 From 154d9869c3972939cff5d95cb2b2343dc5e76309 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Sun, 7 Apr 2013 13:02:11 +0200 Subject: Replace progress dialog by individual progress bars when loading images --- main/res/layout/cache_image_item.xml | 6 +++++ main/res/values-cs/strings.xml | 3 --- main/res/values-de/strings.xml | 3 --- main/res/values-es/strings.xml | 2 -- main/res/values-fr/strings.xml | 3 --- main/res/values-hu/strings.xml | 3 --- main/res/values-it/strings.xml | 3 --- main/res/values-ja/strings.xml | 3 --- main/res/values-nl/strings.xml | 3 --- main/res/values-pl/strings.xml | 3 --- main/res/values-pt/strings.xml | 3 --- main/res/values-sk/strings.xml | 3 --- main/res/values-sv/strings.xml | 3 --- main/res/values/strings.xml | 3 --- main/src/cgeo/geocaching/CacheDetailActivity.java | 3 +-- main/src/cgeo/geocaching/ImagesActivity.java | 2 +- main/src/cgeo/geocaching/ui/ImagesList.java | 33 +++++------------------ 17 files changed, 14 insertions(+), 68 deletions(-) (limited to 'main') diff --git a/main/res/layout/cache_image_item.xml b/main/res/layout/cache_image_item.xml index 7ed4782..3e025e1 100644 --- a/main/res/layout/cache_image_item.xml +++ b/main/res/layout/cache_image_item.xml @@ -27,4 +27,10 @@ android:textSize="14dip" android:visibility="gone" /> + + \ No newline at end of file diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index caf0a17..a93a535 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -514,7 +514,6 @@ Atributy Inventář Offline Log - Načítání obrázků z logů… Obrázky z Logů Fotografie Osobní poznámka @@ -617,9 +616,7 @@ Souřadnice Původní souřadnice Obrázky s nápovědou - Načítání obrázků s nápovědou… Obrázky - Načítání obrázků… Typy zápisů Tato keš nemá souřadnice. Vymazat historii diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index 87086ef..d011ce8 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -502,7 +502,6 @@ Attribute Inventar Offline-Log - Lade Logbild… Logbild Bild Persönliche Notiz @@ -603,8 +602,6 @@ Koordinaten Ursprüngliche Koordinaten Hinweisbilder - Lade Hinweisbilder… - Lade Bilder… Logs Dieser Cache hat keine Koordinaten. Verlauf leeren diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index 7215d72..0fe60b5 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -401,7 +401,6 @@ Atributos Inventario Registro desconectado - Cargando imagen de registro… Imagen de resgistro Foto Nota personal @@ -464,7 +463,6 @@ Ubicación Coordenadas Imágenes reveladoras - Cargando imágenes reveladoras… Tipos de registro Este escondite no tiene coordenadas. Borrar historial diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index 9de84ac..1fe3e20 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -512,7 +512,6 @@ Attributs Inventaire Visite hors-ligne - Chargement de l\'image de la visite… Image de la visite Photo Note personnelle @@ -615,9 +614,7 @@ Coordonnées Coordonnées d\'origine Images indices - Chargement des images indices… Images - Chargement des images… Types de visites Cette cache n\'a pas de coordonnées. Effacer l\'historique diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml index ec5e06e..dd8dfb9 100644 --- a/main/res/values-hu/strings.xml +++ b/main/res/values-hu/strings.xml @@ -483,7 +483,6 @@ Tulajdonságok Tárgyak Offline bejegyzés - Bejegyzés kép betöltése… Bejegyzés kép Fotó Személyes megjegyzés @@ -577,9 +576,7 @@ Koordináták Eredeti koordináták Spoiler képek - Spoiler képek betöltése… Képek - Képek betéltése… Bejegyzés típusok Ennek a ládának nincsenek koordinátái. Előzmények törlése diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index f7d29cb..0205a19 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -484,7 +484,6 @@ Attributi Oggetti Log Offline - Caricamento immagini log… Immagini Log Foto Note personali @@ -583,9 +582,7 @@ Coordinate Coordinate originali Immagini spoiler - Caricamento immagini spoiler… Immaginis - Caricamento immagini… Tipi di Log Questo cache non ha coordinate. Cancella cronologia diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml index 126a03c..926122f 100644 --- a/main/res/values-ja/strings.xml +++ b/main/res/values-ja/strings.xml @@ -494,7 +494,6 @@ 属性 目録 オフラインログ - 添付画像をロード中… ログの添付画像 写真 パーソナルノート @@ -595,9 +594,7 @@ 座標 オリジナル座標 スポイラー画像 - スポイラー画像をロード中… 画像 - 画像をロード中… ログタイプ このキャッシュに座標値はありません。 全履歴を削除 diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml index 729c382..322bb0b 100644 --- a/main/res/values-nl/strings.xml +++ b/main/res/values-nl/strings.xml @@ -497,7 +497,6 @@ Attributen Inventaris Offline log - Laden van logafbeeldingen… Logafbeelding Foto Persoonlijke aantekening @@ -600,9 +599,7 @@ Coördinaten Originele coordinaten Spoiler afbeeldingen - Spoiler afbeeldingen laden… Afbeeldingen - Afbeeldingen laden… Log types Deze cache heeft geen coördinaten. Maak geschiedenis leeg diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml index b5328c4..4ab069e 100644 --- a/main/res/values-pl/strings.xml +++ b/main/res/values-pl/strings.xml @@ -488,7 +488,6 @@ Atrybuty Inwentarz Wpis offline - Trwa ładowanie zdjęć z wpisu… Zdjęcie z wpisu Zdjęcie Notatka osobista @@ -586,9 +585,7 @@ Współrzędne Oryginalne współrzędne Zdjęcia spoiler - Ładuję zdjęcia spoiler… Zdjęcia - Ładuję zdjęcia… Rodzaj wpisu Ta skrzynka nie ma współrzędnych GPS. Usuń historię diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml index 5f67281..d6ee413 100644 --- a/main/res/values-pt/strings.xml +++ b/main/res/values-pt/strings.xml @@ -484,7 +484,6 @@ Atributos Inventário Registo Offline - A carregar imagem do registo… Imagem do registo Foto Nota pessoal @@ -580,9 +579,7 @@ Coordenadas Coordenadas originais Imagens spoiler - A carregar imagens spoiler… Imagens - A carregar as imagens… Tipos de log Esta cache não tem coordenadas. Apagar histórico diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index cef88d4..e128fb0 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -484,7 +484,6 @@ Atribúty Obsah Offline log - Načítanie obrázku z logu… Obrázok z logu Fotografia Osobná poznámka @@ -579,9 +578,7 @@ Súradnice Pôvodné súradnice Spoilerové obrázky - Načítanie spoilerových obrázkov… Obrázky - Prebieha načítanie obrázkov… Typy záznamov Táto skrýša nemá žiadne súradnice. Vymazať históriu diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml index d3be9ff..b68de4c 100644 --- a/main/res/values-sv/strings.xml +++ b/main/res/values-sv/strings.xml @@ -512,7 +512,6 @@ Attribut Innehåll Offline logg - Laddar loggbilder… Loggbild Foto Personlig anteckning @@ -615,9 +614,7 @@ Koordinater Ursprungliga koordinater Spoiler bilder - Laddar spoiler bilder… Bilder - Laddar bilder… Loggtyper Cachen saknar koordinater. Rensa historik diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 13926c5..c539915 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -512,7 +512,6 @@ Attributes Inventory Offline Log - Loading Log images… Log images Photo Personal note @@ -615,9 +614,7 @@ Coordinates Original Coordinates Spoiler images - Loading spoiler images… Images - Loading images… Log types This cache has no coordinates. Clear history diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index daeb14e..c4287ed 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -27,7 +27,6 @@ import cgeo.geocaching.ui.EditNoteDialog; import cgeo.geocaching.ui.EditNoteDialog.EditNoteDialogListener; 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.utils.BaseUtils; @@ -905,7 +904,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity bitmaps = new LinkedList(); @@ -83,18 +77,10 @@ public class ImagesList { inflater = activity.getLayoutInflater(); } - public void loadImages(final View parentView, final List images, ImageType imageType, final boolean offline) { + public void loadImages(final View parentView, final List images, final boolean offline) { imagesView = (LinearLayout) parentView.findViewById(R.id.spoiler_list); - count = images.size(); - progressDialog = new ProgressDialog(activity); - progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - progressDialog.setMessage(activity.getString(imageType.loadingResId)); - progressDialog.setCancelable(true); - progressDialog.setMax(count); - progressDialog.show(); - for (final Image img : images) { LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null); @@ -154,19 +140,12 @@ public class ImagesList { imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageView.setLayoutParams(new LayoutParams(bounds.width(), bounds.height())); + view.findViewById(R.id.progress_bar).setVisibility(View.GONE); view.addView(imageView); imageView.setId(image.hashCode()); images.put(imageView.getId(), img); } - - synchronized (activity) { - countDone++; - progressDialog.setProgress(countDone); - if (progressDialog.getProgress() >= count) { - progressDialog.dismiss(); - } - } } } -- cgit v1.1 From 97b10e667d2fdfd9abb56be8e5bfaee259e27f65 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 7 Apr 2013 14:45:42 +0200 Subject: fix #2640: Filter out stored caches --- main/res/values-de/strings.xml | 2 ++ main/res/values/strings.xml | 2 ++ main/src/cgeo/geocaching/filter/StateFilter.java | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) (limited to 'main') diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index d011ce8..aa27553 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -584,6 +584,8 @@ Deaktiviert Nur für Premium-Mitglieder Für alle Mitglieder + Gespeichert + Nicht gespeichert Geocode Name Typ diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index c539915..218c22b 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -596,6 +596,8 @@ Disabled Premium Members only All Members Access + Stored + Not stored Geo code Name Type diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java index ae3fac2..e18128d 100644 --- a/main/src/cgeo/geocaching/filter/StateFilter.java +++ b/main/src/cgeo/geocaching/filter/StateFilter.java @@ -87,6 +87,28 @@ abstract class StateFilter extends AbstractFilter { } } + static class StateStoredFilter extends StateFilter { + public StateStoredFilter() { + super(res.getString(R.string.cache_status_stored)); + } + + @Override + public boolean accepts(Geocache cache) { + return cache.isOffline(); + } + } + + static class StateNotStoredFilter extends StateFilter { + public StateNotStoredFilter() { + super(res.getString(R.string.cache_status_not_stored)); + } + + @Override + public boolean accepts(Geocache cache) { + return !cache.isOffline(); + } + } + public static class Factory implements IFilterFactory { @Override @@ -98,6 +120,8 @@ abstract class StateFilter extends AbstractFilter { filters.add(new StatePremiumFilter()); filters.add(new StateNonPremiumFilter()); filters.add(new StateOfflineLogFilter()); + filters.add(new StateStoredFilter()); + filters.add(new StateNotStoredFilter()); Collections.sort(filters, new Comparator() { -- cgit v1.1 From ae47c7df2d2fab20b709a85b8053908907f0eafd Mon Sep 17 00:00:00 2001 From: TriakCZ Date: Mon, 8 Apr 2013 08:06:17 +0200 Subject: Partial revert of R3gis patch to translations --- main/res/values-cs/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'main') diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index a93a535..d8c924a 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -90,7 +90,7 @@ Odeslat Log Odeslat Log a hlasovat Odeslat Log a nehlasovat - Načítání stránky s Logy… + Načítání stránky s Logovacím formulářem… Přidat Hodnocení Bez hodnocení @@ -323,7 +323,7 @@ Se sledovatelnými předměty Vymazat filtry S upravenými souřadnicemi - Originální + Původ keše Čištění Historie… Smazat offline Logy Mazání offline logů @@ -552,7 +552,7 @@ Načítání GCVote Načítání údajů o nadmořské výšce Ukládání do mezipaměti - Renderování zobrazení + Vykreslování pohledu Offline Ukládání keše pro offline použití… Offline -- cgit v1.1 From bc0fc04b30412aff6804e48063d9eccb068e84bd Mon Sep 17 00:00:00 2001 From: triakcz Date: Wed, 10 Apr 2013 00:40:18 +0200 Subject: Removed translation of distance units --- main/res/values-cs/strings.xml | 7 ------- main/res/values-de/strings.xml | 7 ------- main/res/values-fr/strings.xml | 7 ------- main/res/values-hu/strings.xml | 7 ------- main/res/values-it/strings.xml | 7 ------- main/res/values-ja/strings.xml | 7 ------- main/res/values-nl/strings.xml | 7 ------- main/res/values-pl/strings.xml | 7 ------- main/res/values-sk/strings.xml | 7 ------- main/res/values/strings.xml | 7 ------- main/res/values/strings_not_translatable.xml | 9 ++++++++- 11 files changed, 8 insertions(+), 71 deletions(-) (limited to 'main') diff --git a/main/res/values-cs/strings.xml b/main/res/values-cs/strings.xml index d8c924a..58e28ac 100644 --- a/main/res/values-cs/strings.xml +++ b/main/res/values-cs/strings.xml @@ -716,13 +716,6 @@ Prostý - - m (Metry) - km (Kilometry) - ft (Stopy) - yd (Yardy) - mi (Míle) - Oznámit nález na Twitteru diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index aa27553..048991b 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -703,13 +703,6 @@ Schlicht - - m - km - ft - yd - mi - Diesen Eintrag auf Twitter veröffentlichen diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index 1fe3e20..f7a6fde 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -714,13 +714,6 @@ Texte - - m - km - ft - yd - mi - Publier votre découverte sur Twitter diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml index dd8dfb9..353aa10 100644 --- a/main/res/values-hu/strings.xml +++ b/main/res/values-hu/strings.xml @@ -658,13 +658,6 @@ Előzmények törölve Egyszerű - - - m - km - ft - yd - mi Twitteld ki ezt a megtalálást diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index 0205a19..b070b10 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -680,13 +680,6 @@ Plain - - m - km - piedi - iarde - miglia - Segnala questo ritrovamento su Twitter diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml index 926122f..27ffbd3 100644 --- a/main/res/values-ja/strings.xml +++ b/main/res/values-ja/strings.xml @@ -692,13 +692,6 @@ プレーン - - m - km - ft - yd - mi - この発見をTwitterでつぶやく diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml index 322bb0b..557aa79 100644 --- a/main/res/values-nl/strings.xml +++ b/main/res/values-nl/strings.xml @@ -698,13 +698,6 @@ Vlak - - m - km - ft - yd - mi - Post deze vondst op Twitter diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml index 4ab069e..b3a5032 100644 --- a/main/res/values-pl/strings.xml +++ b/main/res/values-pl/strings.xml @@ -681,13 +681,6 @@ zwykłe - - m - km - stopy - jardy - mile - Wyślij informację do Twitter diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index e128fb0..ef316ea 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -662,13 +662,6 @@ Iba text - - m - km - ft - yd - mi - informovať o nájdení na Twitteri diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index 218c22b..d35a982 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -716,13 +716,6 @@ Plain - - m - km - ft - yd - mi - Post this find to Twitter diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml index 8de1483..b392d73 100644 --- a/main/res/values/strings_not_translatable.xml +++ b/main/res/values/strings_not_translatable.xml @@ -8,7 +8,14 @@ - + m + km + ft + yd + mi + + + @string/unit_m @string/unit_km @string/unit_ft -- cgit v1.1 From 154fb6457c4ba05b99a8cf97afe9a5f3c1937cc1 Mon Sep 17 00:00:00 2001 From: Marco Jacob Date: Wed, 10 Apr 2013 20:55:19 +0200 Subject: fixes #2651 - exclude inaccessable dirs from choice --- main/src/cgeo/geocaching/files/SimpleDirChooser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java index 7520e2e..844287c 100644 --- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java +++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java @@ -238,7 +238,7 @@ public class SimpleDirChooser extends ListActivity { @Override public boolean accept(File dir, String filename) { File file = new File(dir, filename); - return file.isDirectory(); + return file.isDirectory() && file.canWrite(); } } -- cgit v1.1 From 9945bf9dc036d52718e26b316621ee88eeabef04 Mon Sep 17 00:00:00 2001 From: RomNexus6 Date: Thu, 11 Apr 2013 14:28:20 +0300 Subject: updated translation-it to feb-24 --- main/res/values-it/strings.xml | 91 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 12 deletions(-) (limited to 'main') diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index b070b10..c0c2ce5 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -85,6 +85,7 @@ Cambia tutto Salva Invio log… + Invio log e immagine… Azzera Invia log Invia log + voto @@ -118,6 +119,13 @@ Oggi Ieri Smile + Immagine + Aggiungi immagine + Modifica immagine + Esistente + Nuova + Didascalia + Descrizione Traduci in %s @@ -167,6 +175,8 @@ Per cortesia inserire il nome del dispositivo prima di registrarsi. Errore nella modifica dello stato preferiti. + La selezione dell\'immagine per il log è fallita. + Acquisizione immagine fallita. c:geo non riesce a visualizzare il trackable che vuoi. È veramente un trackable? c:geo non riesce ad aprire i dettagli del trackable. @@ -189,6 +199,7 @@ c:geo sta ancora caricando i dati necessari per salvare il log. Per cortesia attendere ancora un pochino. c:geo non è riuscito ad inviare il log perché il server non risponde. Sembra che il log non sia stato inviato. Prego verificare su Geocaching.com. + Sembra la l\'immagine non sia stata caricata. Si prega di controllare su Geocaching.com. c:geo ha dimenticato l\'indirizzo che vuoi trovare. c:geo non riesce ad interpretare la latitudine. @@ -218,6 +229,8 @@ c:geo ha salvato il log. Il log è stato azzerato. Il tipo di log è cambiato! + Selezione o cattura immagine annnulata. + Nuova immagine salvata su: Tento di salvare la static map @@ -307,6 +320,7 @@ Con oggetti trackables Rimuovi filtri Con coordinate modificate + Origine Rimozione dalla cronologia… @@ -387,6 +401,7 @@ Salva immagini contenute nei log Usa miglia/piedi Quando salvi log, fallo sempre offline (non visualizzerà lo schermo di log online, non invierà subito il log) + Ask for list when storing caches Visualizza in che direzione sono i cache, nelle liste Correzione di altitudine Se il GPS restituisce un\'errata altitudine, puoi correggerla inserendo un valore positivo o negativo, in metri. @@ -498,6 +513,9 @@ Questo cache non è uno dei tuoi favoriti. Aggiungi Rimuovi + Lista: + Sposta + Non in una lista Immagini Waypoints @@ -653,6 +671,7 @@ Modifica waypoint Aggiungi waypoint Note + Visitato Salva Caricamento waypoint… Nessuna modifica alle coordinate cache @@ -813,10 +832,7 @@ Il file GPX sarà esportato in %1$s con data ed ora correnti come nome file. Invia il GPX esportato a - - (attributo sconosciuto) permesso - (attributo sconosciuto) non permesso - + Cani permessi Cani NON permessi Biciclette permesse @@ -835,8 +851,6 @@ Fuochi da campo NON permessi Camper/roulotte permessi Camper/roulotte NON permessi - - Raccomandato per bambini Non raccomandato per bambini Richiede meno di un\'ora @@ -889,8 +903,6 @@ Non è un tour \"Lost and found\" Cache di gruppo Cache non di gruppo - - Accesso o parcheggio a pagamento Accesso o parcheggio non a pagamento Richiesta attrezzatura da arrampicata @@ -913,8 +925,6 @@ Segnalatore radio non necessario Richiede di salire su un albero Non richiede di salire su un albero - - Piante velenose Piante non velenose Animali pericolosi @@ -931,8 +941,6 @@ Area non pericolosa Rovi Senza rovi - - Accessibile con sedia a rotelle Non accessibile con sedia a rotelle Parcheggio @@ -955,6 +963,65 @@ Lontano da pompa carburante Vicino a punto ristoro Lontano da punti ristoro + + Loggabile solo su Opencaching + Loggabile non solo su Opencaching + Hyperlink solo verso un altro portale di cache + Non solo hyperlink ad un altro portale di cache + Lettera (richiede francobollo) + No lettera (non richiede francobollo) + Ferrovia attiva nelle vicinanze + Nessuna ferrovia nelle vicinanze + Pronto soccorso disponibile + Pronto soccorso non disponibile + Paludoso + Non paludoso + Area collinare + Area non collinare + Punto di interesse + Nessun punto di interesse + Obiettivo in movimento + Obiettivo non in movimento + Webcam + No webcam + Con aree interne (cave, edifici etc.) + Senza aree interne + In acqua + Non in acqua + Senza GPS (lettere, cistes, carta e bussola...) + Con GPS + Necessario permanere di notte + Permanenza notturna non necessaria + Disponibile solo in certi orari + Disponibile a tutte le ore + Solo di giorno + Non solo di giorno + Marea + Senza marea + Tutte le stagioni + Non in tutte le stagioni + Stagione di riproduzione / natura protetta + Disponibile anche in stagione di riproduzione / natura protetta + Nascondiglio a prova di neve + Nascondiglio non a prova di neve + Bussola + Senza bussola + Equipaggiamento da caverna + Senza equipaggiamento da caverna + Aircraft + Senza aircraft + Investigazione + Senza investigazione + Puzzle / Mystery + No puzzle / mystery + Problema aritmetico + Problema non aritmetico + Cache di altro tipo + Cache non di altro tipo + Chiedere al proprietario per le condizioni di partenza + Non chiedere al proprietario per le condizioni di partenza + Attributo sconosciuto + Senza attributo sconosciuto Per usare i servizi di Geocaching.com, si applicano i termini e le condizioni del Contratto Groundspeak che deve essere approvato dall\'utente. -- cgit v1.1 From 4f2242cdb76a1539b2d27eee3e17429990e3f14f Mon Sep 17 00:00:00 2001 From: RomNexus6 Date: Thu, 11 Apr 2013 13:18:19 +0300 Subject: cherry-picked PR from RomNexus6 patch-38 --- main/res/values-it/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'main') diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index c0c2ce5..7d57aac 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -401,7 +401,7 @@ Salva immagini contenute nei log Usa miglia/piedi Quando salvi log, fallo sempre offline (non visualizzerà lo schermo di log online, non invierà subito il log) - Ask for list when storing caches + Chiedi la lista quando salvi un cache Visualizza in che direzione sono i cache, nelle liste Correzione di altitudine Se il GPS restituisce un\'errata altitudine, puoi correggerla inserendo un valore positivo o negativo, in metri. -- cgit v1.1 From 922244640b0d10e90c256660e3ccfb20df067005 Mon Sep 17 00:00:00 2001 From: RomNexus6 Date: Thu, 18 Apr 2013 16:21:46 +0300 Subject: updated translation-it --- main/res/values-it/strings.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index 7d57aac..98a3f9c 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -306,7 +306,7 @@ Aggiorna i cache selezionati Aggiorna tutti Muovi i cache selezionati - Muovi tutte + Muovi tutti Locus Esporta in Locus reCAPTCHA @@ -322,6 +322,8 @@ Con coordinate modificate Origine Rimozione dalla cronologia… + Cancella i log offline + Cancellazione logs offline Lista @@ -354,6 +356,7 @@ Geocaching.com + Attiva Geocaching.com su mappa live e nelle ricerche opencaching.de Attiva opencaching.de su mappa live e nelle ricerche Inserisci il tuo utente opencaching.de per marcare i tuoi ritrovamenti. @@ -400,7 +403,7 @@ Salva i waypoints delle mappe per uso offline Salva immagini contenute nei log Usa miglia/piedi - Quando salvi log, fallo sempre offline (non visualizzerà lo schermo di log online, non invierà subito il log) + Attiva log offline (non visualizzerà lo schermo di log online, non invierà subito il log) Chiedi la lista quando salvi un cache Visualizza in che direzione sono i cache, nelle liste Correzione di altitudine @@ -452,6 +455,12 @@ Visualizza i LOG senza colori Identifica come browser Android. Risolve alcuni problemi di login con alcuni provider di rete. Cartella per i temi mappa personali off-line + + Google: Map + Google: Satellite + OSM: Mapnik + OSM: Cyclemap + OSM: Offline Send to c:geo Nome dispositivo: -- cgit v1.1 From b71d4bd03f8da774881d119c3ab55e16dc27f4d1 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sat, 20 Apr 2013 10:35:24 +0200 Subject: fix #2664: List sorting does not respect locale --- main/src/cgeo/geocaching/StoredList.java | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java index 5a6f132..778c112 100644 --- a/main/src/cgeo/geocaching/StoredList.java +++ b/main/src/cgeo/geocaching/StoredList.java @@ -12,7 +12,10 @@ import android.content.res.Resources; import android.view.View; import android.widget.EditText; +import java.text.Collator; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; public class StoredList { @@ -69,7 +72,7 @@ public class StoredList { } public void promptForListSelection(final int titleId, final RunnableWithArgument runAfterwards, final boolean onlyMoveTargets, final int exceptListId) { - final List lists = cgData.getLists(); + final List lists = getSortedLists(); if (lists == null) { return; @@ -115,6 +118,19 @@ public class StoredList { builder.create().show(); } + private static List getSortedLists() { + final Collator collator = Collator.getInstance(); + final List lists = cgData.getLists(); + Collections.sort(lists, new Comparator() { + + @Override + public int compare(StoredList lhs, StoredList rhs) { + return collator.compare(lhs.getTitle(), rhs.getTitle()); + } + }); + return lists; + } + public void promptForListCreation(final RunnableWithArgument runAfterwards) { handleListNameInput("", R.string.list_dialog_create_title, R.string.list_dialog_create, new RunnableWithArgument() { @@ -176,4 +192,13 @@ public class StoredList { }); } } + + /** + * Get the list title. This method is not public by intention to make clients use the {@link UserInterface} class. + * + * @return + */ + protected String getTitle() { + return title; + } } -- cgit v1.1 From 705dc21ac799f786e6c7b76f9588ff22aa25a05f Mon Sep 17 00:00:00 2001 From: donEgro Date: Sat, 20 Apr 2013 22:13:29 +0200 Subject: Fixed Issue #708 - Refresh caches + no internet = normal progress. --- main/src/cgeo/geocaching/cgeocaches.java | 5 +++++ main/src/cgeo/geocaching/network/Network.java | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 61a32f1..8fc61d4 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -1082,6 +1082,11 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity return; } + if (!Network.isNetworkConnected(getApplicationContext())) { + showToast(getString(R.string.err_server)); + return; + } + if (Settings.getChooseList() && type != CacheListType.OFFLINE) { // let user select list to store cache in new StoredList.UserInterface(this).promptForListSelection(R.string.list_title, diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java index eb6a6ac..5a8cbb2 100644 --- a/main/src/cgeo/geocaching/network/Network.java +++ b/main/src/cgeo/geocaching/network/Network.java @@ -40,6 +40,9 @@ import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; import android.net.Uri; import java.io.File; @@ -471,4 +474,19 @@ public abstract class Network { return null; } + /** + * Checks if the device has network connection. + * + * @param context + * context of the application, cannot be null + * + * @return true if the device is connected to the network. + */ + public static boolean isNetworkConnected(Context context) { + ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetwork = conMan.getActiveNetworkInfo(); + + return activeNetwork != null && activeNetwork.isConnected(); + } + } -- cgit v1.1 From fceb3c05fd6ca7108b536ec2b9b0ab9e50cfba1e Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 22 Apr 2013 08:26:06 +0200 Subject: fix #2671: Don't show short description, if same as long description --- main/src/cgeo/geocaching/CacheDetailActivity.java | 78 +++++++++++++++-------- 1 file changed, 51 insertions(+), 27 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index c4287ed..9a13f91 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -1752,8 +1752,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity */ private class LoadDescriptionTask extends AsyncTask { - private View loadingIndicatorView; - private TextView descriptionView; - private String descriptionString; + private final View loadingIndicatorView; + private final TextView descriptionView; + private final String descriptionString; private Spanned description; + private final View shortDescView; + public LoadDescriptionTask(final String description, final View descriptionView, final View loadingIndicatorView, final View shortDescView) { + this.descriptionString = description; + this.descriptionView = (TextView) descriptionView; + this.loadingIndicatorView = loadingIndicatorView; + this.shortDescView = shortDescView; + } @Override protected Void doInBackground(Object... params) { try { - descriptionString = ((String) params[0]); - descriptionView = (TextView) params[1]; - loadingIndicatorView = (View) params[2]; - // Fast preview: parse only HTML without loading any images HtmlImageCounter imageCounter = new HtmlImageCounter(); final UnknownTagsHandler unknownTagsHandler = new UnknownTagsHandler(); description = Html.fromHtml(descriptionString, imageCounter, unknownTagsHandler); publishProgress(); + + boolean needsRefresh = false; if (imageCounter.getImageCount() > 0) { // Complete view: parse again with loading images - if necessary ! If there are any images causing problems the user can see at least the preview description = Html.fromHtml(descriptionString, new HtmlImage(cache.getGeocode(), true, cache.getListId(), false), unknownTagsHandler); - publishProgress(); + needsRefresh = true; } // If description has an HTML construct which may be problematic to render, add a note at the end of the long description. @@ -1934,6 +1939,10 @@ public class CacheDetailActivity extends AbstractViewPagerActivity" + connector.getName() + "")); ((Editable) description).append("\n\n").append(tableNote); ((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + needsRefresh = true; + } + + if (needsRefresh) { publishProgress(); } } catch (Exception e) { @@ -1942,25 +1951,40 @@ public class CacheDetailActivity extends AbstractViewPagerActivity= 0 && index < 200) { + shortDescView.setVisibility(View.GONE); + } + } + } + } + + @Override + protected void onPostExecute(Void result) { if (null != loadingIndicatorView) { loadingIndicatorView.setVisibility(View.GONE); } -- cgit v1.1 From 9dac2f6bb2bf6849ec74a3438b17e1c85e1b01a8 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 22 Apr 2013 08:35:53 +0200 Subject: refactoring: move third party code into new source path * makes it more easy to ignore warnings in third party code --- main/.classpath | 5 + .../support/v4/app/FragmentListActivity.java | 316 --------- main/src/cgeo/org/kxml2/io/KXmlSerializer.java | 605 ---------------- main/src/com/viewpagerindicator/PageIndicator.java | 63 -- .../com/viewpagerindicator/TitlePageIndicator.java | 771 --------------------- main/src/com/viewpagerindicator/TitleProvider.java | 28 - .../app/appmanualclient/AppManualReaderClient.java | 375 ---------- .../openintents/intents/FileManagerIntents.java | 127 ---- .../support/v4/app/FragmentListActivity.java | 316 +++++++++ .../cgeo/org/kxml2/io/KXmlSerializer.java | 605 ++++++++++++++++ .../com/viewpagerindicator/PageIndicator.java | 63 ++ .../com/viewpagerindicator/TitlePageIndicator.java | 771 +++++++++++++++++++++ .../com/viewpagerindicator/TitleProvider.java | 28 + .../app/appmanualclient/AppManualReaderClient.java | 375 ++++++++++ .../openintents/intents/FileManagerIntents.java | 127 ++++ 15 files changed, 2290 insertions(+), 2285 deletions(-) delete mode 100644 main/src/android/support/v4/app/FragmentListActivity.java delete mode 100644 main/src/cgeo/org/kxml2/io/KXmlSerializer.java delete mode 100644 main/src/com/viewpagerindicator/PageIndicator.java delete mode 100644 main/src/com/viewpagerindicator/TitlePageIndicator.java delete mode 100644 main/src/com/viewpagerindicator/TitleProvider.java delete mode 100644 main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java delete mode 100644 main/src/org/openintents/intents/FileManagerIntents.java create mode 100644 main/thirdparty/android/support/v4/app/FragmentListActivity.java create mode 100644 main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java create mode 100644 main/thirdparty/com/viewpagerindicator/PageIndicator.java create mode 100644 main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java create mode 100644 main/thirdparty/com/viewpagerindicator/TitleProvider.java create mode 100644 main/thirdparty/gnu/android/app/appmanualclient/AppManualReaderClient.java create mode 100644 main/thirdparty/org/openintents/intents/FileManagerIntents.java (limited to 'main') diff --git a/main/.classpath b/main/.classpath index 79a19e9..2905a42 100644 --- a/main/.classpath +++ b/main/.classpath @@ -6,6 +6,11 @@ + + + + + diff --git a/main/src/android/support/v4/app/FragmentListActivity.java b/main/src/android/support/v4/app/FragmentListActivity.java deleted file mode 100644 index e3ed42c..0000000 --- a/main/src/android/support/v4/app/FragmentListActivity.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.support.v4.app; - -import android.os.Bundle; -import android.os.Handler; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListAdapter; -import android.widget.ListView; - -/** - * An activity that displays a list of items by binding to a data source such as - * an array or Cursor, and exposes event handlers when the user selects an item. - *

- * FragmentListActivity hosts a {@link android.widget.ListView ListView} object that can - * be bound to different data sources, typically either an array or a Cursor - * holding query results. Binding, screen layout, and row layout are discussed - * in the following sections. - *

- * Screen Layout - *

- *

- * FragmentListActivity has a default layout that consists of a single, full-screen list - * in the center of the screen. However, if you desire, you can customize the - * screen layout by setting your own view layout with setContentView() in - * onCreate(). To do this, your own view MUST contain a ListView object with the - * id "@android:id/list" (or {@link android.R.id#list} if it's in code) - *

- * Optionally, your custom view can contain another view object of any type to - * display when the list view is empty. This "empty list" notifier must have an - * id "android:empty". Note that when an empty view is present, the list view - * will be hidden when there is no data to display. - *

- * The following code demonstrates an (ugly) custom screen layout. It has a list - * with a green background, and an alternate red "no data" message. - *

- * - *
- * <?xml version="1.0" encoding="utf-8"?>
- * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- *         android:orientation="vertical"
- *         android:layout_width="fill_parent" 
- *         android:layout_height="fill_parent"
- *         android:paddingLeft="8dp"
- *         android:paddingRight="8dp">
- * 
- *     <ListView android:id="@id/android:list"
- *               android:layout_width="fill_parent" 
- *               android:layout_height="fill_parent"
- *               android:background="#00FF00"
- *               android:layout_weight="1"
- *               android:drawSelectorOnTop="false"/>
- * 
- *     <TextView android:id="@id/android:empty"
- *               android:layout_width="fill_parent" 
- *               android:layout_height="fill_parent"
- *               android:background="#FF0000"
- *               android:text="No data"/>
- * </LinearLayout>
- * 
- * - *

- * Row Layout - *

- *

- * You can specify the layout of individual rows in the list. You do this by - * specifying a layout resource in the ListAdapter object hosted by the activity - * (the ListAdapter binds the ListView to the data; more on this later). - *

- * A ListAdapter constructor takes a parameter that specifies a layout resource - * for each row. It also has two additional parameters that let you specify - * which data field to associate with which object in the row layout resource. - * These two parameters are typically parallel arrays. - *

- *

- * Android provides some standard row layout resources. These are in the - * {@link android.R.layout} class, and have names such as simple_list_item_1, - * simple_list_item_2, and two_line_list_item. The following layout XML is the - * source for the resource two_line_list_item, which displays two data - * fields,one above the other, for each list row. - *

- * - *
- * <?xml version="1.0" encoding="utf-8"?>
- * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- *     android:layout_width="fill_parent"
- *     android:layout_height="wrap_content"
- *     android:orientation="vertical">
- * 
- *     <TextView android:id="@+id/text1"
- *         android:textSize="16sp"
- *         android:textStyle="bold"
- *         android:layout_width="fill_parent"
- *         android:layout_height="wrap_content"/>
- * 
- *     <TextView android:id="@+id/text2"
- *         android:textSize="16sp"
- *         android:layout_width="fill_parent"
- *         android:layout_height="wrap_content"/>
- * </LinearLayout>
- * 
- * - *

- * You must identify the data bound to each TextView object in this layout. The - * syntax for this is discussed in the next section. - *

- *

- * Binding to Data - *

- *

- * You bind the FragmentListActivity's ListView object to data using a class that - * implements the {@link android.widget.ListAdapter ListAdapter} interface. - * Android provides two standard list adapters: - * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps), - * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor - * query results. - *

- *

- * The following code from a custom FragmentListActivity demonstrates querying the - * Contacts provider for all contacts, then binding the Name and Company fields - * to a two line row layout in the activity's ListView. - *

- * - *
- * public class MyListAdapter extends FragmentListActivity {
- * 
- *     @Override
- *     protected void onCreate(Bundle savedInstanceState){
- *         super.onCreate(savedInstanceState);
- * 
- *         // We'll define a custom screen layout here (the one shown above), but
- *         // typically, you could just use the standard FragmentListActivity layout.
- *         setContentView(R.layout.custom_list_activity_view);
- * 
- *         // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class.
- *         // Put a managed wrapper around the retrieved cursor so we don't have to worry about
- *         // requerying or closing it as the activity changes state.
- *         mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null);
- *         startManagingCursor(mCursor);
- * 
- *         // Now create a new list adapter bound to the cursor. 
- *         // SimpleListAdapter is designed for binding to a Cursor.
- *         ListAdapter adapter = new SimpleCursorAdapter(
- *                 this, // Context.
- *                 android.R.layout.two_line_list_item,  // Specify the row template to use (here, two columns bound to the two retrieved cursor 
- * rows).
- *                 mCursor,                                              // Pass in the cursor to bind to.
- *                 new String[] {People.NAME, People.COMPANY},           // Array of cursor columns to bind to.
- *                 new int[] {android.R.id.text1, android.R.id.text2});  // Parallel array of which template objects to bind to those columns.
- * 
- *         // Bind to our new adapter.
- *         setListAdapter(adapter);
- *     }
- * }
- * 
- * - * @see #setListAdapter - * @see android.widget.ListView - */ -public class FragmentListActivity extends FragmentActivity { - /** - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected ListAdapter mAdapter; - /** - * This field should be made private, so it is hidden from the SDK. - * {@hide} - */ - protected ListView mList; - - private Handler mHandler = new Handler(); - private boolean mFinishedStart = false; - - private Runnable mRequestFocus = new Runnable() { - @Override - public void run() { - mList.focusableViewAvailable(mList); - } - }; - - /** - * This method will be called when an item in the list is selected. - * Subclasses should override. Subclasses can call - * getListView().getItemAtPosition(position) if they need to access the - * data associated with the selected item. - * - * @param l The ListView where the click happened - * @param v The view that was clicked within the ListView - * @param position The position of the view in the list - * @param id The row id of the item that was clicked - */ - protected void onListItemClick(ListView l, View v, int position, long id) { - } - - /** - * Ensures the list view has been created before Activity restores all - * of the view states. - * - *@see Activity#onRestoreInstanceState(Bundle) - */ - @Override - protected void onRestoreInstanceState(Bundle state) { - ensureList(); - super.onRestoreInstanceState(state); - } - - /** - * Updates the screen state (current list and other views) when the - * content changes. - * - * @see Activity#onContentChanged() - */ - @Override - public void onContentChanged() { - super.onContentChanged(); - View emptyView = findViewById(android.R.id.empty); - mList = (ListView)findViewById(android.R.id.list); - if (mList == null) { - throw new RuntimeException( - "Your content must have a ListView whose id attribute is " + - "'android.R.id.list'"); - } - if (emptyView != null) { - mList.setEmptyView(emptyView); - } - mList.setOnItemClickListener(mOnClickListener); - if (mFinishedStart) { - setListAdapter(mAdapter); - } - mHandler.post(mRequestFocus); - mFinishedStart = true; - } - - /** - * Provide the cursor for the list view. - */ - public void setListAdapter(ListAdapter adapter) { - synchronized (this) { - ensureList(); - mAdapter = adapter; - mList.setAdapter(adapter); - } - } - - /** - * Set the currently selected list item to the specified - * position with the adapter's data - * - * @param position - */ - public void setSelection(int position) { - mList.setSelection(position); - } - - /** - * Get the position of the currently selected list item. - */ - public int getSelectedItemPosition() { - return mList.getSelectedItemPosition(); - } - - /** - * Get the cursor row ID of the currently selected list item. - */ - public long getSelectedItemId() { - return mList.getSelectedItemId(); - } - - /** - * Get the activity's list view widget. - */ - public ListView getListView() { - ensureList(); - return mList; - } - - /** - * Get the ListAdapter associated with this activity's ListView. - */ - public ListAdapter getListAdapter() { - return mAdapter; - } - - private void ensureList() { - if (mList != null) { - return; - } - setContentView(android.R.layout.list_content); - - } - - private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View v, int position, long id) - { - onListItemClick((ListView)parent, v, position, id); - } - }; -} - diff --git a/main/src/cgeo/org/kxml2/io/KXmlSerializer.java b/main/src/cgeo/org/kxml2/io/KXmlSerializer.java deleted file mode 100644 index 027ff53..0000000 --- a/main/src/cgeo/org/kxml2/io/KXmlSerializer.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -package cgeo.org.kxml2.io; - -import org.apache.commons.lang3.StringUtils; -import org.xmlpull.v1.XmlSerializer; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.Locale; - -public class KXmlSerializer implements XmlSerializer { - - // static final String UNDEFINED = ":"; - - // BEGIN android-added - /** size (in characters) for the write buffer */ - private static final int WRITE_BUFFER_SIZE = 500; - // END android-added - - // BEGIN android-changed - // (Guarantee that the writer is always buffered.) - private BufferedWriter writer; - // END android-changed - - private boolean pending; - private int auto; - private int depth; - - private String[] elementStack = new String[12]; - //nsp/prefix/name - private int[] nspCounts = new int[4]; - private String[] nspStack = new String[8]; - //prefix/nsp; both empty are "" - private boolean[] indent = new boolean[4]; - private boolean unicode; - private String encoding; - - private final void check(boolean close) throws IOException { - if (!pending) { - return; - } - - depth++; - pending = false; - - if (indent.length <= depth) { - boolean[] hlp = new boolean[depth + 4]; - System.arraycopy(indent, 0, hlp, 0, depth); - indent = hlp; - } - indent[depth] = indent[depth - 1]; - - for (int i = nspCounts[depth - 1]; i < nspCounts[depth]; i++) { - writer.write(' '); - writer.write("xmlns"); - if (!StringUtils.isEmpty(nspStack[i * 2])) { - writer.write(':'); - writer.write(nspStack[i * 2]); - } - else if (StringUtils.isEmpty(getNamespace()) && !StringUtils.isEmpty(nspStack[i * 2 + 1])) { - throw new IllegalStateException("Cannot set default namespace for elements in no namespace"); - } - writer.write("=\""); - writeEscaped(nspStack[i * 2 + 1], '"'); - writer.write('"'); - } - - if (nspCounts.length <= depth + 1) { - int[] hlp = new int[depth + 8]; - System.arraycopy(nspCounts, 0, hlp, 0, depth + 1); - nspCounts = hlp; - } - - nspCounts[depth + 1] = nspCounts[depth]; - // nspCounts[depth + 2] = nspCounts[depth]; - - writer.write(close ? " />" : ">"); - } - - private final void writeEscaped(String s, int quot) throws IOException { - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case '\n': - case '\r': - case '\t': - if (quot == -1) { - writer.write(c); - } else { - writer.write("&#"+((int) c)+';'); - } - break; - case '&': - writer.write("&"); - break; - case '>': - writer.write(">"); - break; - case '<': - writer.write("<"); - break; - default: - if (c == quot) { - writer.write(c == '"' ? """ : "'"); - break; - } - // BEGIN android-changed: refuse to output invalid characters - // See http://www.w3.org/TR/REC-xml/#charsets for definition. - // Corrected for c:geo to handle utf-16 codepoint surrogates correctly - // See http://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B10000_to_U.2B10FFFF - // Note: tab, newline, and carriage return have already been - // handled above. - // Check for lead surrogate - if (c >= 0xd800 && c <= 0xdbff) { - - if (i + 1 < s.length()) { - writer.write(s.substring(i, i + 1)); - i++; - break; - } - // if the lead surrogate is at the string end, it's not valid utf-16 - reportInvalidCharacter(c); - } - boolean valid = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd); - if (!valid) { - reportInvalidCharacter(c); - } - if (unicode || c < 127) { - writer.write(c); - } else { - writer.write("&#" + ((int) c) + ";"); - } - // END android-changed - } - } - } - - // BEGIN android-added - private static void reportInvalidCharacter(char ch) { - throw new IllegalArgumentException("Illegal character (" + Integer.toHexString((int) ch) + ")"); - } - // END android-added - - /* - * private final void writeIndent() throws IOException { - * writer.write("\r\n"); - * for (int i = 0; i < depth; i++) - * writer.write(' '); - * } - */ - - public void docdecl(String dd) throws IOException { - writer.write(""); - } - - public void endDocument() throws IOException { - while (depth > 0) { - endTag(elementStack[depth * 3 - 3], elementStack[depth * 3 - 1]); - } - flush(); - } - - public void entityRef(String name) throws IOException { - check(false); - writer.write('&'); - writer.write(name); - writer.write(';'); - } - - public boolean getFeature(String name) { - //return false; - return ("http://xmlpull.org/v1/doc/features.html#indent-output" - .equals( - name)) - ? indent[depth] - : false; - } - - public String getPrefix(String namespace, boolean create) { - try { - return getPrefix(namespace, false, create); - } catch (IOException e) { - throw new RuntimeException(e.toString()); - } - } - - private final String getPrefix( - String namespace, - boolean includeDefault, - boolean create) - throws IOException { - - for (int i = nspCounts[depth + 1] * 2 - 2; i >= 0; i -= 2) { - if (nspStack[i + 1].equals(namespace) - && (includeDefault || !StringUtils.isEmpty(nspStack[i]))) { - String cand = nspStack[i]; - for (int j = i + 2; j < nspCounts[depth + 1] * 2; j++) { - if (nspStack[j].equals(cand)) { - cand = null; - break; - } - } - if (cand != null) { - return cand; - } - } - } - - if (!create) { - return null; - } - - String prefix; - - if (StringUtils.isEmpty(namespace)) { - prefix = ""; - } else { - do { - prefix = "n" + (auto++); - for (int i = nspCounts[depth + 1] * 2 - 2; i >= 0; i -= 2) { - if (prefix.equals(nspStack[i])) { - prefix = null; - break; - } - } - } while (prefix == null); - } - - boolean p = pending; - pending = false; - setPrefix(prefix, namespace); - pending = p; - return prefix; - } - - public Object getProperty(String name) { - throw new RuntimeException("Unsupported property"); - } - - public void ignorableWhitespace(String s) - throws IOException { - text(s); - } - - public void setFeature(String name, boolean value) { - if ("http://xmlpull.org/v1/doc/features.html#indent-output" - .equals(name)) { - indent[depth] = value; - } else { - throw new RuntimeException("Unsupported Feature"); - } - } - - public void setProperty(String name, Object value) { - throw new RuntimeException( - "Unsupported Property:" + value); - } - - public void setPrefix(String prefix, String namespace) - throws IOException { - - check(false); - if (prefix == null) { - prefix = ""; - } - if (namespace == null) { - namespace = ""; - } - - String defined = getPrefix(namespace, true, false); - - // boil out if already defined - - if (prefix.equals(defined)) { - return; - } - - int pos = (nspCounts[depth + 1]++) << 1; - - if (nspStack.length < pos + 1) { - String[] hlp = new String[nspStack.length + 16]; - System.arraycopy(nspStack, 0, hlp, 0, pos); - nspStack = hlp; - } - - nspStack[pos++] = prefix; - nspStack[pos] = namespace; - } - - public void setOutput(Writer writer) { - // BEGIN android-changed - // Guarantee that the writer is always buffered. - if (writer instanceof BufferedWriter) { - this.writer = (BufferedWriter) writer; - } else { - this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE); - } - // END android-changed - - // elementStack = new String[12]; //nsp/prefix/name - //nspCounts = new int[4]; - //nspStack = new String[8]; //prefix/nsp - //indent = new boolean[4]; - - nspCounts[0] = 2; - nspCounts[1] = 2; - nspStack[0] = ""; - nspStack[1] = ""; - nspStack[2] = "xml"; - nspStack[3] = "http://www.w3.org/XML/1998/namespace"; - pending = false; - auto = 0; - depth = 0; - - unicode = false; - } - - public void setOutput(OutputStream os, String encoding) - throws IOException { - if (os == null) { - throw new IllegalArgumentException("os == null"); - } - setOutput(encoding == null - ? new OutputStreamWriter(os) - : new OutputStreamWriter(os, encoding)); - this.encoding = encoding; - if (encoding != null && encoding.toLowerCase(Locale.US).startsWith("utf")) { - unicode = true; - } - } - - public void startDocument(String encoding, Boolean standalone) throws IOException { - writer.write(""); - } - - public XmlSerializer startTag(String namespace, String name) - throws IOException { - check(false); - - // if (namespace == null) - // namespace = ""; - - if (indent[depth]) { - writer.write("\r\n"); - for (int i = 0; i < depth; i++) { - writer.write(" "); - } - } - - int esp = depth * 3; - - if (elementStack.length < esp + 3) { - String[] hlp = new String[elementStack.length + 12]; - System.arraycopy(elementStack, 0, hlp, 0, esp); - elementStack = hlp; - } - - String prefix = - namespace == null - ? "" - : getPrefix(namespace, true, true); - - if (namespace != null && StringUtils.isEmpty(namespace)) { - for (int i = nspCounts[depth]; i < nspCounts[depth + 1]; i++) { - if (StringUtils.isEmpty(nspStack[i * 2]) && !StringUtils.isEmpty(nspStack[i * 2 + 1])) { - throw new IllegalStateException("Cannot set default namespace for elements in no namespace"); - } - } - } - - elementStack[esp++] = namespace; - elementStack[esp++] = prefix; - elementStack[esp] = name; - - writer.write('<'); - if (!StringUtils.isEmpty(prefix)) { - writer.write(prefix); - writer.write(':'); - } - - writer.write(name); - - pending = true; - - return this; - } - - public XmlSerializer attribute( - String namespace, - String name, - String value) - throws IOException { - if (!pending) { - throw new IllegalStateException("illegal position for attribute"); - } - - // int cnt = nspCounts[depth]; - - if (namespace == null) { - namespace = ""; - } - - // depth--; - // pending = false; - - String prefix = - StringUtils.isEmpty(namespace) - ? "" - : getPrefix(namespace, false, true); - - // pending = true; - // depth++; - - /* - * if (cnt != nspCounts[depth]) { - * writer.write(' '); - * writer.write("xmlns"); - * if (nspStack[cnt * 2] != null) { - * writer.write(':'); - * writer.write(nspStack[cnt * 2]); - * } - * writer.write("=\""); - * writeEscaped(nspStack[cnt * 2 + 1], '"'); - * writer.write('"'); - * } - */ - - writer.write(' '); - if (!StringUtils.isEmpty(prefix)) { - writer.write(prefix); - writer.write(':'); - } - writer.write(name); - writer.write('='); - char q = value.indexOf('"') == -1 ? '"' : '\''; - writer.write(q); - writeEscaped(value, q); - writer.write(q); - - return this; - } - - public void flush() throws IOException { - check(false); - writer.flush(); - } - - /* - * public void close() throws IOException { - * check(); - * writer.close(); - * } - */ - public XmlSerializer endTag(String namespace, String name) - throws IOException { - - if (!pending) - { - depth--; - // if (namespace == null) - // namespace = ""; - } - - if ((namespace == null - && elementStack[depth * 3] != null) - || (namespace != null - && !namespace.equals(elementStack[depth * 3])) - || !elementStack[depth * 3 + 2].equals(name)) { - throw new IllegalArgumentException(" does not match start"); - } - - if (pending) { - check(true); - depth--; - } - else { - if (indent[depth + 1]) { - writer.write("\r\n"); - for (int i = 0; i < depth; i++) { - writer.write(" "); - } - } - - writer.write("'); - } - - nspCounts[depth + 1] = nspCounts[depth]; - return this; - } - - public String getNamespace() { - return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3]; - } - - public String getName() { - return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1]; - } - - public int getDepth() { - return pending ? depth + 1 : depth; - } - - public XmlSerializer text(String text) throws IOException { - check(false); - indent[depth] = false; - writeEscaped(text, -1); - return this; - } - - public XmlSerializer text(char[] text, int start, int len) - throws IOException { - text(new String(text, start, len)); - return this; - } - - public void cdsect(String data) throws IOException { - check(false); - // BEGIN android-changed: ]]> is not allowed within a CDATA, - // so break and start a new one when necessary. - data = data.replace("]]>", "]]]]>"); - char[] chars = data.toCharArray(); - // We also aren't allowed any invalid characters. - for (char ch : chars) { - boolean valid = (ch >= 0x20 && ch <= 0xd7ff) || - (ch == '\t' || ch == '\n' || ch == '\r') || - (ch >= 0xe000 && ch <= 0xfffd); - if (!valid) { - reportInvalidCharacter(ch); - } - } - writer.write(""); - // END android-changed - } - - public void comment(String comment) throws IOException { - check(false); - writer.write(""); - } - - public void processingInstruction(String pi) - throws IOException { - check(false); - writer.write(""); - } -} \ No newline at end of file diff --git a/main/src/com/viewpagerindicator/PageIndicator.java b/main/src/com/viewpagerindicator/PageIndicator.java deleted file mode 100644 index 26414d8..0000000 --- a/main/src/com/viewpagerindicator/PageIndicator.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 Patrik Akerfeldt - * Copyright (C) 2011 Jake Wharton - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.viewpagerindicator; - -import android.support.v4.view.ViewPager; - -/** - * A PageIndicator is responsible to show an visual indicator on the total views - * number and the current visible view. - */ -public interface PageIndicator extends ViewPager.OnPageChangeListener { - /** - * Bind the indicator to a ViewPager. - * - * @param view - */ - public void setViewPager(ViewPager view); - - /** - * Bind the indicator to a ViewPager. - * - * @param view - * @param initialPosition - */ - public void setViewPager(ViewPager view, int initialPosition); - - /** - *

Set the current page of both the ViewPager and indicator.

- * - *

This must be used if you need to set the page before - * the views are drawn on screen (e.g., default start page).

- * - * @param item - */ - public void setCurrentItem(int item); - - /** - * Set a page change listener which will receive forwarded events. - * - * @param listener - */ - public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); - - /** - * Notify the indicator that the fragment list has changed. - */ - public void notifyDataSetChanged(); -} diff --git a/main/src/com/viewpagerindicator/TitlePageIndicator.java b/main/src/com/viewpagerindicator/TitlePageIndicator.java deleted file mode 100644 index 94ac962..0000000 --- a/main/src/com/viewpagerindicator/TitlePageIndicator.java +++ /dev/null @@ -1,771 +0,0 @@ -/* - * Copyright (C) 2011 Patrik Akerfeldt - * Copyright (C) 2011 Francisco Figueiredo Jr. - * Copyright (C) 2011 Jake Wharton - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.viewpagerindicator; - -import cgeo.geocaching.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.os.Parcel; -import android.os.Parcelable; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.PagerAdapter; -import android.support.v4.view.ViewConfigurationCompat; -import android.support.v4.view.ViewPager; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -import java.util.ArrayList; - -/** - * A TitlePageIndicator is a PageIndicator which displays the title of left view - * (if exist), the title of the current select view (centered) and the title of - * the right view (if exist). When the user scrolls the ViewPager then titles are - * also scrolled. - */ -public class TitlePageIndicator extends View implements PageIndicator { - /** - * Percentage indicating what percentage of the screen width away from - * center should the underline be fully faded. A value of 0.25 means that - * halfway between the center of the screen and an edge. - */ - private static final float SELECTION_FADE_PERCENTAGE = 0.25f; - - /** - * Percentage indicating what percentage of the screen width away from - * center should the selected text bold turn off. A value of 0.05 means - * that 10% between the center and an edge. - */ - private static final float BOLD_FADE_PERCENTAGE = 0.05f; - - public enum IndicatorStyle { - None(0), Triangle(1), Underline(2); - - public final int value; - - IndicatorStyle(int value) { - this.value = value; - } - - public static IndicatorStyle fromValue(int value) { - for (IndicatorStyle style : IndicatorStyle.values()) { - if (style.value == value) { - return style; - } - } - return null; - } - } - - private ViewPager mViewPager; - private ViewPager.OnPageChangeListener mListener; - private TitleProvider mTitleProvider; - private int mCurrentPage; - private int mCurrentOffset; - private int mScrollState; - private final Paint mPaintText; - private boolean mBoldText; - private int mColorText; - private int mColorSelected; - private Path mPath = new Path(); - private final Paint mPaintFooterLine; - private IndicatorStyle mFooterIndicatorStyle; - private final Paint mPaintFooterIndicator; - private float mFooterIndicatorHeight; - private float mFooterIndicatorUnderlinePadding; - private float mFooterPadding; - private float mTitlePadding; - private float mTopPadding; - /** Left and right side padding for not active view titles. */ - private float mClipPadding; - private float mFooterLineHeight; - - private static final int INVALID_POINTER = -1; - - private int mTouchSlop; - private float mLastMotionX = -1; - private int mActivePointerId = INVALID_POINTER; - private boolean mIsDragging; - - - public TitlePageIndicator(Context context) { - this(context, null); - } - - public TitlePageIndicator(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.vpiTitlePageIndicatorStyle); - } - - public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - //Load defaults from resources - final Resources res = getResources(); - final int defaultFooterColor = res.getColor(R.color.default_title_indicator_footer_color); - final float defaultFooterLineHeight = res.getDimension(R.dimen.default_title_indicator_footer_line_height); - final int defaultFooterIndicatorStyle = res.getInteger(R.integer.default_title_indicator_footer_indicator_style); - final float defaultFooterIndicatorHeight = res.getDimension(R.dimen.default_title_indicator_footer_indicator_height); - final float defaultFooterIndicatorUnderlinePadding = res.getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding); - final float defaultFooterPadding = res.getDimension(R.dimen.default_title_indicator_footer_padding); - final int defaultSelectedColor = res.getColor(R.color.default_title_indicator_selected_color); - final boolean defaultSelectedBold = res.getBoolean(R.bool.default_title_indicator_selected_bold); - final int defaultTextColor = res.getColor(R.color.default_title_indicator_text_color); - final float defaultTextSize = res.getDimension(R.dimen.default_title_indicator_text_size); - final float defaultTitlePadding = res.getDimension(R.dimen.default_title_indicator_title_padding); - final float defaultClipPadding = res.getDimension(R.dimen.default_title_indicator_clip_padding); - final float defaultTopPadding = res.getDimension(R.dimen.default_title_indicator_top_padding); - - //Retrieve styles attributes - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitlePageIndicator, defStyle, R.style.Widget_TitlePageIndicator); - - //Retrieve the colors to be used for this view and apply them. - mFooterLineHeight = a.getDimension(R.styleable.TitlePageIndicator_footerLineHeight, defaultFooterLineHeight); - mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger(R.styleable.TitlePageIndicator_footerIndicatorStyle, defaultFooterIndicatorStyle)); - mFooterIndicatorHeight = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorHeight, defaultFooterIndicatorHeight); - mFooterIndicatorUnderlinePadding = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, defaultFooterIndicatorUnderlinePadding); - mFooterPadding = a.getDimension(R.styleable.TitlePageIndicator_footerPadding, defaultFooterPadding); - mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, defaultTopPadding); - mTitlePadding = a.getDimension(R.styleable.TitlePageIndicator_titlePadding, defaultTitlePadding); - mClipPadding = a.getDimension(R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding); - mColorSelected = a.getColor(R.styleable.TitlePageIndicator_selectedColor, defaultSelectedColor); - mColorText = a.getColor(R.styleable.TitlePageIndicator_textColor, defaultTextColor); - mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, defaultSelectedBold); - - final float textSize = a.getDimension(R.styleable.TitlePageIndicator_textSize, defaultTextSize); - final int footerColor = a.getColor(R.styleable.TitlePageIndicator_footerColor, defaultFooterColor); - mPaintText = new Paint(); - mPaintText.setTextSize(textSize); - mPaintText.setAntiAlias(true); - mPaintFooterLine = new Paint(); - mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE); - mPaintFooterLine.setStrokeWidth(mFooterLineHeight); - mPaintFooterLine.setColor(footerColor); - mPaintFooterIndicator = new Paint(); - mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE); - mPaintFooterIndicator.setColor(footerColor); - - a.recycle(); - - final ViewConfiguration configuration = ViewConfiguration.get(context); - mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); - } - - - public int getFooterColor() { - return mPaintFooterLine.getColor(); - } - - public void setFooterColor(int footerColor) { - mPaintFooterLine.setColor(footerColor); - mPaintFooterIndicator.setColor(footerColor); - invalidate(); - } - - public float getFooterLineHeight() { - return mFooterLineHeight; - } - - public void setFooterLineHeight(float footerLineHeight) { - mFooterLineHeight = footerLineHeight; - mPaintFooterLine.setStrokeWidth(mFooterLineHeight); - invalidate(); - } - - public float getFooterIndicatorHeight() { - return mFooterIndicatorHeight; - } - - public void setFooterIndicatorHeight(float footerTriangleHeight) { - mFooterIndicatorHeight = footerTriangleHeight; - invalidate(); - } - - public float getFooterIndicatorPadding() { - return mFooterPadding; - } - - public void setFooterIndicatorPadding(float footerIndicatorPadding) { - mFooterPadding = footerIndicatorPadding; - invalidate(); - } - - public IndicatorStyle getFooterIndicatorStyle() { - return mFooterIndicatorStyle; - } - - public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) { - mFooterIndicatorStyle = indicatorStyle; - invalidate(); - } - - public int getSelectedColor() { - return mColorSelected; - } - - public void setSelectedColor(int selectedColor) { - mColorSelected = selectedColor; - invalidate(); - } - - public boolean isSelectedBold() { - return mBoldText; - } - - public void setSelectedBold(boolean selectedBold) { - mBoldText = selectedBold; - invalidate(); - } - - public int getTextColor() { - return mColorText; - } - - public void setTextColor(int textColor) { - mPaintText.setColor(textColor); - mColorText = textColor; - invalidate(); - } - - public float getTextSize() { - return mPaintText.getTextSize(); - } - - public void setTextSize(float textSize) { - mPaintText.setTextSize(textSize); - invalidate(); - } - - public float getTitlePadding() { - return this.mTitlePadding; - } - - public void setTitlePadding(float titlePadding) { - mTitlePadding = titlePadding; - invalidate(); - } - - public float getTopPadding() { - return this.mTopPadding; - } - - public void setTopPadding(float topPadding) { - mTopPadding = topPadding; - invalidate(); - } - - public float getClipPadding() { - return this.mClipPadding; - } - - public void setClipPadding(float clipPadding) { - mClipPadding = clipPadding; - invalidate(); - } - - /* - * (non-Javadoc) - * - * @see android.view.View#onDraw(android.graphics.Canvas) - */ - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (mViewPager == null) { - return; - } - final int count = mViewPager.getAdapter().getCount(); - if (count == 0) { - return; - } - - //Calculate views bounds - ArrayList bounds = calculateAllBounds(mPaintText); - - //Make sure we're on a page that still exists - if (mCurrentPage >= bounds.size()) { - setCurrentItem(bounds.size()-1); - } - - final int countMinusOne = count - 1; - final float halfWidth = getWidth() / 2f; - final int left = getLeft(); - final float leftClip = left + mClipPadding; - final int width = getWidth(); - final int height = getHeight(); - final int right = left + width; - final float rightClip = right - mClipPadding; - - int page = mCurrentPage; - float offsetPercent; - if (mCurrentOffset <= halfWidth) { - offsetPercent = 1.0f * mCurrentOffset / width; - } else { - page += 1; - offsetPercent = 1.0f * (width - mCurrentOffset) / width; - } - final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); - final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); - final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; - - //Verify if the current view must be clipped to the screen - RectF curPageBound = bounds.get(mCurrentPage); - float curPageWidth = curPageBound.right - curPageBound.left; - if (curPageBound.left < leftClip) { - //Try to clip to the screen (left side) - clipViewOnTheLeft(curPageBound, curPageWidth, left); - } - if (curPageBound.right > rightClip) { - //Try to clip to the screen (right side) - clipViewOnTheRight(curPageBound, curPageWidth, right); - } - - //Left views starting from the current position - if (mCurrentPage > 0) { - for (int i = mCurrentPage - 1; i >= 0; i--) { - RectF bound = bounds.get(i); - //Is left side is outside the screen - if (bound.left < leftClip) { - float w = bound.right - bound.left; - //Try to clip to the screen (left side) - clipViewOnTheLeft(bound, w, left); - //Except if there's an intersection with the right view - RectF rightBound = bounds.get(i + 1); - //Intersection - if (bound.right + mTitlePadding > rightBound.left) { - bound.left = rightBound.left - w - mTitlePadding; - bound.right = bound.left + w; - } - } - } - } - //Right views starting from the current position - if (mCurrentPage < countMinusOne) { - for (int i = mCurrentPage + 1 ; i < count; i++) { - RectF bound = bounds.get(i); - //If right side is outside the screen - if (bound.right > rightClip) { - float w = bound.right - bound.left; - //Try to clip to the screen (right side) - clipViewOnTheRight(bound, w, right); - //Except if there's an intersection with the left view - RectF leftBound = bounds.get(i - 1); - //Intersection - if (bound.left - mTitlePadding < leftBound.right) { - bound.left = leftBound.right + mTitlePadding; - bound.right = bound.left + w; - } - } - } - } - - //Now draw views - for (int i = 0; i < count; i++) { - //Get the title - RectF bound = bounds.get(i); - //Only if one side is visible - if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { - final boolean currentPage = (i == page); - //Only set bold if we are within bounds - mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); - - //Draw text as unselected - mPaintText.setColor(mColorText); - canvas.drawText(mTitleProvider.getTitle(i), bound.left, bound.bottom + mTopPadding, mPaintText); - - //If we are within the selected bounds draw the selected text - if (currentPage && currentSelected) { - mPaintText.setColor(mColorSelected); - mPaintText.setAlpha((int)((mColorSelected >>> 24) * selectedPercent)); - canvas.drawText(mTitleProvider.getTitle(i), bound.left, bound.bottom + mTopPadding, mPaintText); - } - } - } - - //Draw the footer line - mPath.reset(); - mPath.moveTo(0, height - mFooterLineHeight / 2f); - mPath.lineTo(width, height - mFooterLineHeight / 2f); - mPath.close(); - canvas.drawPath(mPath, mPaintFooterLine); - - switch (mFooterIndicatorStyle) { - case Triangle: - mPath.reset(); - mPath.moveTo(halfWidth, height - mFooterLineHeight - mFooterIndicatorHeight); - mPath.lineTo(halfWidth + mFooterIndicatorHeight, height - mFooterLineHeight); - mPath.lineTo(halfWidth - mFooterIndicatorHeight, height - mFooterLineHeight); - mPath.close(); - canvas.drawPath(mPath, mPaintFooterIndicator); - break; - - case Underline: - if (!currentSelected) { - break; - } - - RectF underlineBounds = bounds.get(page); - mPath.reset(); - mPath.moveTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight); - mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight); - mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight); - mPath.lineTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight); - mPath.close(); - - mPaintFooterIndicator.setAlpha((int)(0xFF * selectedPercent)); - canvas.drawPath(mPath, mPaintFooterIndicator); - mPaintFooterIndicator.setAlpha(0xFF); - break; - - default: - break; - } - } - - @Override - public boolean onTouchEvent(android.view.MotionEvent ev) { - if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { - return false; - } - - final int action = ev.getAction(); - - switch (action & MotionEventCompat.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - mActivePointerId = MotionEventCompat.getPointerId(ev, 0); - mLastMotionX = ev.getX(); - break; - - case MotionEvent.ACTION_MOVE: { - final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); - final float x = MotionEventCompat.getX(ev, activePointerIndex); - final float deltaX = x - mLastMotionX; - - if (!mIsDragging) { - if (Math.abs(deltaX) > mTouchSlop) { - mIsDragging = true; - } - } - - if (mIsDragging) { - if (!mViewPager.isFakeDragging()) { - mViewPager.beginFakeDrag(); - } - - mLastMotionX = x; - - mViewPager.fakeDragBy(deltaX); - } - - break; - } - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - if (!mIsDragging) { - final int count = mViewPager.getAdapter().getCount(); - final int width = getWidth(); - final float halfWidth = width / 2f; - final float sixthWidth = width / 6f; - - if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { - mViewPager.setCurrentItem(mCurrentPage - 1); - return true; - } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { - mViewPager.setCurrentItem(mCurrentPage + 1); - return true; - } - } - - mIsDragging = false; - mActivePointerId = INVALID_POINTER; - if (mViewPager.isFakeDragging()) { - mViewPager.endFakeDrag(); - } - break; - - case MotionEventCompat.ACTION_POINTER_DOWN: { - final int index = MotionEventCompat.getActionIndex(ev); - mLastMotionX = MotionEventCompat.getX(ev, index); - mActivePointerId = MotionEventCompat.getPointerId(ev, index); - break; - } - - case MotionEventCompat.ACTION_POINTER_UP: - final int pointerIndex = MotionEventCompat.getActionIndex(ev); - final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); - if (pointerId == mActivePointerId) { - final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); - } - mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); - break; - } - - return true; - } - - /** - * Set bounds for the right textView including clip padding. - * - * @param curViewBound - * current bounds. - * @param curViewWidth - * width of the view. - */ - private void clipViewOnTheRight(RectF curViewBound, float curViewWidth, int right) { - curViewBound.right = right - mClipPadding; - curViewBound.left = curViewBound.right - curViewWidth; - } - - /** - * Set bounds for the left textView including clip padding. - * - * @param curViewBound - * current bounds. - * @param curViewWidth - * width of the view. - */ - private void clipViewOnTheLeft(RectF curViewBound, float curViewWidth, int left) { - curViewBound.left = left + mClipPadding; - curViewBound.right = mClipPadding + curViewWidth; - } - - /** - * Calculate views bounds and scroll them according to the current index - * - * @param paint - * @param currentIndex - * @return - */ - private ArrayList calculateAllBounds(Paint paint) { - ArrayList list = new ArrayList(); - //For each views (If no values then add a fake one) - final int count = mViewPager.getAdapter().getCount(); - final int width = getWidth(); - final int halfWidth = width / 2; - for (int i = 0; i < count; i++) { - RectF bounds = calcBounds(i, paint); - float w = (bounds.right - bounds.left); - float h = (bounds.bottom - bounds.top); - bounds.left = (halfWidth) - (w / 2) - mCurrentOffset + ((i - mCurrentPage) * width); - bounds.right = bounds.left + w; - bounds.top = 0; - bounds.bottom = h; - list.add(bounds); - } - - return list; - } - - /** - * Calculate the bounds for a view's title - * - * @param index - * @param paint - * @return - */ - private RectF calcBounds(int index, Paint paint) { - //Calculate the text bounds - RectF bounds = new RectF(); - bounds.right = paint.measureText(mTitleProvider.getTitle(index)); - bounds.bottom = paint.descent() - paint.ascent(); - return bounds; - } - - @Override - public void setViewPager(ViewPager view) { - final PagerAdapter adapter = view.getAdapter(); - if (adapter == null) { - throw new IllegalStateException("ViewPager does not have adapter instance."); - } - if (!(adapter instanceof TitleProvider)) { - throw new IllegalStateException("ViewPager adapter must implement TitleProvider to be used with TitlePageIndicator."); - } - mViewPager = view; - mViewPager.setOnPageChangeListener(this); - mTitleProvider = (TitleProvider)adapter; - invalidate(); - } - - @Override - public void setViewPager(ViewPager view, int initialPosition) { - setViewPager(view); - setCurrentItem(initialPosition); - } - - @Override - public void notifyDataSetChanged() { - invalidate(); - } - - @Override - public void setCurrentItem(int item) { - if (mViewPager == null) { - throw new IllegalStateException("ViewPager has not been bound."); - } - mViewPager.setCurrentItem(item); - mCurrentPage = item; - invalidate(); - } - - @Override - public void onPageScrollStateChanged(int state) { - mScrollState = state; - - if (mListener != null) { - mListener.onPageScrollStateChanged(state); - } - } - - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - mCurrentPage = position; - mCurrentOffset = positionOffsetPixels; - invalidate(); - - if (mListener != null) { - mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); - } - } - - @Override - public void onPageSelected(int position) { - if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { - mCurrentPage = position; - invalidate(); - } - - if (mListener != null) { - mListener.onPageSelected(position); - } - } - - @Override - public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { - mListener = listener; - } - - /* - * (non-Javadoc) - * - * @see android.view.View#onMeasure(int, int) - */ - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); - } - - /** - * Determines the width of this view - * - * @param measureSpec - * A measureSpec packed into an int - * @return The width of the view, honoring constraints from measureSpec - */ - private int measureWidth(int measureSpec) { - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException(getClass().getSimpleName() + " can only be used in EXACTLY mode."); - } - return specSize; - } - - /** - * Determines the height of this view - * - * @param measureSpec - * A measureSpec packed into an int - * @return The height of the view, honoring constraints from measureSpec - */ - private int measureHeight(int measureSpec) { - float result; - int specMode = MeasureSpec.getMode(measureSpec); - int specSize = MeasureSpec.getSize(measureSpec); - - if (specMode == MeasureSpec.EXACTLY) { - //We were told how big to be - result = specSize; - } else { - //Calculate the text bounds - RectF bounds = new RectF(); - bounds.bottom = mPaintText.descent()-mPaintText.ascent(); - result = bounds.bottom - bounds.top + mFooterLineHeight + mFooterPadding + mTopPadding; - if (mFooterIndicatorStyle != IndicatorStyle.None) { - result += mFooterIndicatorHeight; - } - } - return (int)result; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState savedState = (SavedState)state; - super.onRestoreInstanceState(savedState.getSuperState()); - mCurrentPage = savedState.currentPage; - requestLayout(); - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - SavedState savedState = new SavedState(superState); - savedState.currentPage = mCurrentPage; - return savedState; - } - - static class SavedState extends BaseSavedState { - int currentPage; - - public SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - currentPage = in.readInt(); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - super.writeToParcel(dest, flags); - dest.writeInt(currentPage); - } - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - @Override - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } -} diff --git a/main/src/com/viewpagerindicator/TitleProvider.java b/main/src/com/viewpagerindicator/TitleProvider.java deleted file mode 100644 index 2a04b65..0000000 --- a/main/src/com/viewpagerindicator/TitleProvider.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2011 Patrik Akerfeldt - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.viewpagerindicator; - -/** - * A TitleProvider provides the title to display according to a view. - */ -public interface TitleProvider { - /** - * Returns the title of the view at position - * @param position - * @return - */ - public String getTitle(int position); -} diff --git a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java b/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java deleted file mode 100644 index af4c03e..0000000 --- a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java +++ /dev/null @@ -1,375 +0,0 @@ -package gnu.android.app.appmanualclient; - -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.net.Uri; -import android.util.Log; - -import java.util.List; - -/** - * The "App Manual Reader" client is a class to be used in applications which - * want to offer their users manuals through the gnu.android.appmanualreader - * application. Such applications do not need to include the whole - * "App Manual Reader" app but instead just have to include only this little - * package. This package then provides the mechanism to open suitable installed - * manuals. It does not include any manuals itself. - *

- * - * (c) 2011 Geocrasher (geocrasher@gmx.eu) - *

- * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - *

- * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - *

- * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - * @author Geocrasher - */ -public class AppManualReaderClient { - - /** - * The URI scheme used to identify application manual URIs when flinging - * Intents around within an Android device, in the hope that there are - * activities registered which will handle such application manual URIs. - * Usually, there won't be just a single activity registered but instead - * many, depending on how many manuals are installed on an Android device. - */ - public static final String URI_SCHEME_APPMANUAL = "appmanual"; - - /** - * Standardized topic for opening a manual at its beginning. - * - * @see #openManual(String, String, Context) - * @see #openManual(String, String, Context, String) - */ - public static final String TOPIC_HOME = "andtw-home"; - /** - * Standardized topic for opening the index of a manual. - * - * @see #openManual(String, String, Context) - * @see #openManual(String, String, Context, String) - */ - public static final String TOPIC_INDEX = "andtw-index"; - /** - * Standardized topic for opening a manual's "about" topic. - * - * @see #openManual(String, String, Context) - * @see #openManual(String, String, Context, String) - */ - public static final String TOPIC_ABOUT_MANUAL = "andtw-about"; - - /** - * Convenience function to open a manual at a specific topic. See - * {@link #openManual(String, String, Context, String)} for a detailed - * description. - * - * @param manualIdentifier - * the identifier of the manual to open. This identifier must - * uniquely identify the manual as such, independent of the - * particular locale the manual is intended for. - * @param topic - * the topic to open. Please do not use spaces for topic names. - * With respect to the TiddlyWiki infrastructure used for manuals - * the topic needs to the tag of a (single) tiddler. This way - * manuals can be localized (especially their topic titles) - * without breaking an app's knowledge about topics. Some - * standardized topics are predefined, such as {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and - * {@link #TOPIC_ABOUT_MANUAL}. - * @param context - * the context (usually an Activity) from which the manual is to - * be opened. In particular, this context is required to derive - * the proper current locale configuration in order to open - * appropriate localized manuals, if installed. - * - * @exception ActivityNotFoundException - * there is no suitable manual installed and all combinations - * of locale scope failed to activate any manual. - * - * @see #openManual(String, String, Context, String, boolean) - */ - public static void openManual(String manualIdentifier, String topic, - Context context) throws ActivityNotFoundException { - openManual(manualIdentifier, topic, context, null, false); - } - - /** - * Convenience function to open a manual at a specific topic. See - * {@link #openManual(String, String, Context, String)} for a detailed - * description. - * - * @param manualIdentifier - * the identifier of the manual to open. This identifier must - * uniquely identify the manual as such, independent of the - * particular locale the manual is intended for. - * @param topic - * the topic to open. Please do not use spaces for topic names. - * With respect to the TiddlyWiki infrastructure used for manuals - * the topic needs to the tag of a (single) tiddler. This way - * manuals can be localized (especially their topic titles) - * without breaking an app's knowledge about topics. Some - * standardized topics are predefined, such as {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and - * {@link #TOPIC_ABOUT_MANUAL}. - * @param context - * the context (usually an Activity) from which the manual is to - * be opened. In particular, this context is required to derive - * the proper current locale configuration in order to open - * appropriate localized manuals, if installed. - * @param fallbackUri - * either null or a fallback URI to be used in case - * the user has not installed any suitable manual. - * - * @exception ActivityNotFoundException - * there is no suitable manual installed and all combinations - * of locale scope failed to activate any manual. - * - * @see #openManual(String, String, Context, String, boolean) - */ - public static void openManual(String manualIdentifier, String topic, - Context context, String fallbackUri) - throws ActivityNotFoundException { - openManual(manualIdentifier, topic, context, fallbackUri, false); - } - - /** - * Opens a manual at a specific topic. At least it tries to open a manual. - * As manuals are (usually) installed separately and we use late binding in - * form of implicit intents, a lot of things can go wrong. - * - * We use late binding and the intent architecture in particular as follows: - * first, we use our own URI scheme called "appmanual". Second, we use the - * host field as a unique manual identifier (such as "c-geo" for the app - * manuals for a map which must not be named by the powers that wanna be). - * Third, a localized manual is differentiated as a path with a single - * element in form of (in this precedence) "/lang_country_variant", - * "/lang__variant", "/lang_country", "/lang", or "/". Fourth, the topic to - * open is encoded as the a fragment "#topic=mytopic". - * - * In order to support localization, manuals can register themselves with - * different URIs. - * - * @param manualIdentifier - * the identifier of the manual to open. This identifier must - * uniquely identify the manual as such, independent of the - * particular locale the manual is intended for. - * @param topic - * the topic to open. Please do not use spaces for topic names. - * With respect to the TiddlyWiki infrastructure used for manuals - * the topic needs to the tag of a (single) tiddler. This way - * manuals can be localized (especially their topic titles) - * without breaking an app's knowledge about topics. Some - * standardized topics are predefined, such as - * {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and - * {@link #TOPIC_ABOUT_MANUAL}. - * @param context - * the context (usually an Activity) from which the manual is to - * be opened. In particular, this context is required to derive - * the proper current locale configuration in order to open - * appropriate localized manuals, if installed. - * @param fallbackUri - * either null or a fallback URI to be used in case - * the user has not installed any suitable manual. - * @param contextAffinity - * if true, then we try to open the manual within - * the context, if possible. That is, if the package of the - * calling context also offers suitable activity registrations, - * then we will prefer them over any other registrations. If you - * don't know what this means, then you probably don't need this - * very special capability and should specify false - * for this parameter. - * - * @exception ActivityNotFoundException - * there is no suitable manual installed and all combinations - * of locale scope failed to activate any manual and no - * {@literal fallbackUri} was given. - */ - public static void openManual(String manualIdentifier, String topic, - Context context, String fallbackUri, boolean contextAffinity) - throws ActivityNotFoundException { - // - // The path of an "appmanual:" URI consists simply of the locale - // information. This allows manual packages to register themselves - // for both very specific locales as well as very broad ones. - // - String localePath = "/" - + context.getResources().getConfiguration().locale.toString(); - // - // We later need this intent in order to try to launch an appropriate - // manual (respectively its manual viewer). And yes, we need to set - // the intent's category explicitly, even as we will later use - // startActivity(): if we don't do this, the proper activity won't be - // started albeit the filter almost matches. That dirty behavior (it is - // documented wrong) had cost me half a day until I noticed some - // informational log entry generated from the ActivityManager. Grrrr! - // - Intent intent = new Intent(Intent.ACTION_VIEW); - int defaultIntentFlags = intent.getFlags(); - intent.addCategory(Intent.CATEGORY_DEFAULT); - // - // Try to open the manual in the following order (subject to - // availability): - // 1. manualIdentifier_lang_country_variant (can also be - // manualIdentifier_lang__variant in some cases) - // 2. manualIdentifier_lang_country - // 3. manualIdentifier_lang - // 4. manualIdentifier - // Of course, manuals are free to register more than one Intent, - // in particular, the should register also the plain manualIdentifier - // as a suitable fallback strategy. Even when installing multiple - // manuals this doesn't matter, as the user then can choose which - // one to use on a single or permanent basis. - // - while (true) { - Uri uri = Uri.parse(URI_SCHEME_APPMANUAL + "://" + manualIdentifier - + localePath + "#topic='" + topic + "'"); - // Note: we do not use a MIME type for this. - intent.setData(uri); - intent.setFlags(defaultIntentFlags); - if ( contextAffinity ) { - // - // What is happening here? Well, here we try something that we - // would like to call "package affinity activity resolving". - // Given an implicit(!) intent we try to figure out whether the - // package of the context which is trying to open the manual is - // able to resolve the intent. If this is the case, then we - // simply turn the implicit intent into an explicit(!) intent. - // We do this by setting the concrete module, that is: package - // name (eventually the one of the calling context) and class - // name within the package. - // - List capableActivities = context - .getPackageManager() - .queryIntentActivityOptions(null, null, intent, - PackageManager.MATCH_DEFAULT_ONLY); - int capables = capableActivities.size(); - if ( capables > 1 ) { - for ( int idx = 0; idx < capables; ++idx ) { - ActivityInfo activityInfo = capableActivities.get(idx).activityInfo; - if ( activityInfo.packageName.contentEquals(context - .getPackageName()) ) { - intent.setClassName(activityInfo.packageName, - activityInfo.name); - // - // First match is okay, so we quit searching and - // continue with the usual attempt to start the - // activity. This should not fail, as we already - // found a match; yet the code is very forgiving in - // this respect and would just try another round - // with "downsized" locale requirements. - // - break; - } - } - } - // FIXME - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - } else { - // - // No context affinity required, thus we need to set some flags: - // - // ...NEW_TASK: we want to start the manual reader activity as a - // separate - // task so that it can be kept open, yet in the background when - // returning to the application from which the manual was - // opened. - // - // ...SINGLE_TOP: - // - // ...RESET_TASK_IF_NEEDED: clear the manual reader activities - // down to the root activity. We've set the required - // ...CLEAR_WHEN_TASK_RESET above when opening the meta-manual - // with the context affinity. - // - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_SINGLE_TOP - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); - } - try { - String logTag = "appmanualclient"; - if ( Log.isLoggable(logTag, Log.INFO) ) { - Log.i(logTag, - "Trying to activate manual: uri=" + uri.toString()); - } - context.startActivity(intent); - // - // We could successfully activate the manual activity, so no - // further trials are required. - // - return; - } catch ( ActivityNotFoundException noActivity ) { - // - // Ensure that we switch back to implicit intent resolving for - // the next round. - // - intent.setComponent(null); - // - // As long as we still have some locale information, reduce it - // and try again a broader locale. - // - if ( localePath.length() > 1 ) { - int underscore = localePath.lastIndexOf('_'); - if ( underscore > 0 ) { - localePath = localePath.substring(0, underscore); - // - // Handle the case where we have a locale variant, yet - // no locale country, thus two underscores in immediate - // series. Get rid of both. - // - if ( localePath.endsWith("_") ) { - localePath = localePath - .substring(0, underscore - 1); - } - } else { - // - // Ready for the last round: try without any locale - // modifiers. - // - localePath = "/"; - } - } else { - // - // We've tried all combinations, so we've run out of them - // and bail out. - // - break; - } - } - // - // Okay, go for the next round, we've updated (or rather trimmed) - // the localeIdent, so let us try this. - // - } - // - // If we reach this code point then no suitable activity could be found - // and activated. In case the caller specified a fallback URI we will - // try to open that. As this will activate a suitable browser and this - // is an asynchronous activity we won't get back any negative results, - // such as 404's. Here we will only see such problems that prevented the - // start of a suitable browsing activity. - // - if ( fallbackUri != null ) { - intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fallbackUri)); - intent.addCategory(Intent.CATEGORY_BROWSABLE); - context.startActivity(intent); - } - // - // We could not activate any manual and there was no fallback URI to - // open, so we finally bail out unsuccessful with an exception. - // - throw new ActivityNotFoundException(); - } -} diff --git a/main/src/org/openintents/intents/FileManagerIntents.java b/main/src/org/openintents/intents/FileManagerIntents.java deleted file mode 100644 index 8ff10c8..0000000 --- a/main/src/org/openintents/intents/FileManagerIntents.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2008 OpenIntents.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openintents.intents; - -/** - * Provides OpenIntents actions, extras, and categories used by providers. - *

These specifiers extend the standard Android specifiers.

- */ -public final class FileManagerIntents { - - /** - * Activity Action: Pick a file through the file manager, or let user - * specify a custom file name. - * Data is the current file name or file name suggestion. - * Returns a new file name as file URI in data. - * - *

Constant Value: "org.openintents.action.PICK_FILE"

- */ - public static final String ACTION_PICK_FILE = "org.openintents.action.PICK_FILE"; - - /** - * Activity Action: Pick a directory through the file manager, or let user - * specify a custom file name. - * Data is the current directory name or directory name suggestion. - * Returns a new directory name as file URI in data. - * - *

Constant Value: "org.openintents.action.PICK_DIRECTORY"

- */ - public static final String ACTION_PICK_DIRECTORY = "org.openintents.action.PICK_DIRECTORY"; - - /** - * Activity Action: Move, copy or delete after select entries. - * Data is the current directory name or directory name suggestion. - * - *

Constant Value: "org.openintents.action.MULTI_SELECT"

- */ - public static final String ACTION_MULTI_SELECT = "org.openintents.action.MULTI_SELECT"; - - public static final String ACTION_SEARCH_STARTED = "org.openintents.action.SEARCH_STARTED"; - - public static final String ACTION_SEARCH_FINISHED = "org.openintens.action.SEARCH_FINISHED"; - - /** - * The title to display. - * - *

This is shown in the title bar of the file manager.

- * - *

Constant Value: "org.openintents.extra.TITLE"

- */ - public static final String EXTRA_TITLE = "org.openintents.extra.TITLE"; - - /** - * The text on the button to display. - * - *

Depending on the use, it makes sense to set this to "Open" or "Save".

- * - *

Constant Value: "org.openintents.extra.BUTTON_TEXT"

- */ - public static final String EXTRA_BUTTON_TEXT = "org.openintents.extra.BUTTON_TEXT"; - - /** - * Flag indicating to show only writeable files and folders. - * - *

Constant Value: "org.openintents.extra.WRITEABLE_ONLY"

- */ - public static final String EXTRA_WRITEABLE_ONLY = "org.openintents.extra.WRITEABLE_ONLY"; - - /** - * The path to prioritize in search. Usually denotes the path the user was on when the search was initiated. - * - *

Constant Value: "org.openintents.extra.SEARCH_INIT_PATH"

- */ - public static final String EXTRA_SEARCH_INIT_PATH = "org.openintents.extra.SEARCH_INIT_PATH"; - - /** - * The search query as sent to SearchService. - * - *

Constant Value: "org.openintents.extra.SEARCH_QUERY"

- */ - public static final String EXTRA_SEARCH_QUERY = "org.openintents.extra.SEARCH_QUERY"; - - /** - *

Constant Value: "org.openintents.extra.DIR_PATH"

- */ - public static final String EXTRA_DIR_PATH = "org.openintents.extra.DIR_PATH"; - - /** - * Extension by which to filter. - * - *

Constant Value: "org.openintents.extra.FILTER_FILETYPE"

- */ - public static final String EXTRA_FILTER_FILETYPE = "org.openintents.extra.FILTER_FILETYPE"; - - /** - * Mimetype by which to filter. - * - *

Constant Value: "org.openintents.extra.FILTER_MIMETYPE"

- */ - public static final String EXTRA_FILTER_MIMETYPE = "org.openintents.extra.FILTER_MIMETYPE"; - - /** - * Only show directories. - * - *

Constant Value: "org.openintents.extra.DIRECTORIES_ONLY"

- */ - public static final String EXTRA_DIRECTORIES_ONLY = "org.openintents.extra.DIRECTORIES_ONLY"; - - public static final String EXTRA_DIALOG_FILE_HOLDER = "org.openintents.extra.DIALOG_FILE"; - - public static final String EXTRA_IS_GET_CONTENT_INITIATED = "org.openintents.extra.ENABLE_ACTIONS"; - - public static final String EXTRA_FILENAME = "org.openintents.extra.FILENAME"; -} diff --git a/main/thirdparty/android/support/v4/app/FragmentListActivity.java b/main/thirdparty/android/support/v4/app/FragmentListActivity.java new file mode 100644 index 0000000..e3ed42c --- /dev/null +++ b/main/thirdparty/android/support/v4/app/FragmentListActivity.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.support.v4.app; + +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ListAdapter; +import android.widget.ListView; + +/** + * An activity that displays a list of items by binding to a data source such as + * an array or Cursor, and exposes event handlers when the user selects an item. + *

+ * FragmentListActivity hosts a {@link android.widget.ListView ListView} object that can + * be bound to different data sources, typically either an array or a Cursor + * holding query results. Binding, screen layout, and row layout are discussed + * in the following sections. + *

+ * Screen Layout + *

+ *

+ * FragmentListActivity has a default layout that consists of a single, full-screen list + * in the center of the screen. However, if you desire, you can customize the + * screen layout by setting your own view layout with setContentView() in + * onCreate(). To do this, your own view MUST contain a ListView object with the + * id "@android:id/list" (or {@link android.R.id#list} if it's in code) + *

+ * Optionally, your custom view can contain another view object of any type to + * display when the list view is empty. This "empty list" notifier must have an + * id "android:empty". Note that when an empty view is present, the list view + * will be hidden when there is no data to display. + *

+ * The following code demonstrates an (ugly) custom screen layout. It has a list + * with a green background, and an alternate red "no data" message. + *

+ * + *
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ *         android:orientation="vertical"
+ *         android:layout_width="fill_parent" 
+ *         android:layout_height="fill_parent"
+ *         android:paddingLeft="8dp"
+ *         android:paddingRight="8dp">
+ * 
+ *     <ListView android:id="@id/android:list"
+ *               android:layout_width="fill_parent" 
+ *               android:layout_height="fill_parent"
+ *               android:background="#00FF00"
+ *               android:layout_weight="1"
+ *               android:drawSelectorOnTop="false"/>
+ * 
+ *     <TextView android:id="@id/android:empty"
+ *               android:layout_width="fill_parent" 
+ *               android:layout_height="fill_parent"
+ *               android:background="#FF0000"
+ *               android:text="No data"/>
+ * </LinearLayout>
+ * 
+ * + *

+ * Row Layout + *

+ *

+ * You can specify the layout of individual rows in the list. You do this by + * specifying a layout resource in the ListAdapter object hosted by the activity + * (the ListAdapter binds the ListView to the data; more on this later). + *

+ * A ListAdapter constructor takes a parameter that specifies a layout resource + * for each row. It also has two additional parameters that let you specify + * which data field to associate with which object in the row layout resource. + * These two parameters are typically parallel arrays. + *

+ *

+ * Android provides some standard row layout resources. These are in the + * {@link android.R.layout} class, and have names such as simple_list_item_1, + * simple_list_item_2, and two_line_list_item. The following layout XML is the + * source for the resource two_line_list_item, which displays two data + * fields,one above the other, for each list row. + *

+ * + *
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ *     android:layout_width="fill_parent"
+ *     android:layout_height="wrap_content"
+ *     android:orientation="vertical">
+ * 
+ *     <TextView android:id="@+id/text1"
+ *         android:textSize="16sp"
+ *         android:textStyle="bold"
+ *         android:layout_width="fill_parent"
+ *         android:layout_height="wrap_content"/>
+ * 
+ *     <TextView android:id="@+id/text2"
+ *         android:textSize="16sp"
+ *         android:layout_width="fill_parent"
+ *         android:layout_height="wrap_content"/>
+ * </LinearLayout>
+ * 
+ * + *

+ * You must identify the data bound to each TextView object in this layout. The + * syntax for this is discussed in the next section. + *

+ *

+ * Binding to Data + *

+ *

+ * You bind the FragmentListActivity's ListView object to data using a class that + * implements the {@link android.widget.ListAdapter ListAdapter} interface. + * Android provides two standard list adapters: + * {@link android.widget.SimpleAdapter SimpleAdapter} for static data (Maps), + * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor + * query results. + *

+ *

+ * The following code from a custom FragmentListActivity demonstrates querying the + * Contacts provider for all contacts, then binding the Name and Company fields + * to a two line row layout in the activity's ListView. + *

+ * + *
+ * public class MyListAdapter extends FragmentListActivity {
+ * 
+ *     @Override
+ *     protected void onCreate(Bundle savedInstanceState){
+ *         super.onCreate(savedInstanceState);
+ * 
+ *         // We'll define a custom screen layout here (the one shown above), but
+ *         // typically, you could just use the standard FragmentListActivity layout.
+ *         setContentView(R.layout.custom_list_activity_view);
+ * 
+ *         // Query for all people contacts using the {@link android.provider.Contacts.People} convenience class.
+ *         // Put a managed wrapper around the retrieved cursor so we don't have to worry about
+ *         // requerying or closing it as the activity changes state.
+ *         mCursor = this.getContentResolver().query(People.CONTENT_URI, null, null, null, null);
+ *         startManagingCursor(mCursor);
+ * 
+ *         // Now create a new list adapter bound to the cursor. 
+ *         // SimpleListAdapter is designed for binding to a Cursor.
+ *         ListAdapter adapter = new SimpleCursorAdapter(
+ *                 this, // Context.
+ *                 android.R.layout.two_line_list_item,  // Specify the row template to use (here, two columns bound to the two retrieved cursor 
+ * rows).
+ *                 mCursor,                                              // Pass in the cursor to bind to.
+ *                 new String[] {People.NAME, People.COMPANY},           // Array of cursor columns to bind to.
+ *                 new int[] {android.R.id.text1, android.R.id.text2});  // Parallel array of which template objects to bind to those columns.
+ * 
+ *         // Bind to our new adapter.
+ *         setListAdapter(adapter);
+ *     }
+ * }
+ * 
+ * + * @see #setListAdapter + * @see android.widget.ListView + */ +public class FragmentListActivity extends FragmentActivity { + /** + * This field should be made private, so it is hidden from the SDK. + * {@hide} + */ + protected ListAdapter mAdapter; + /** + * This field should be made private, so it is hidden from the SDK. + * {@hide} + */ + protected ListView mList; + + private Handler mHandler = new Handler(); + private boolean mFinishedStart = false; + + private Runnable mRequestFocus = new Runnable() { + @Override + public void run() { + mList.focusableViewAvailable(mList); + } + }; + + /** + * This method will be called when an item in the list is selected. + * Subclasses should override. Subclasses can call + * getListView().getItemAtPosition(position) if they need to access the + * data associated with the selected item. + * + * @param l The ListView where the click happened + * @param v The view that was clicked within the ListView + * @param position The position of the view in the list + * @param id The row id of the item that was clicked + */ + protected void onListItemClick(ListView l, View v, int position, long id) { + } + + /** + * Ensures the list view has been created before Activity restores all + * of the view states. + * + *@see Activity#onRestoreInstanceState(Bundle) + */ + @Override + protected void onRestoreInstanceState(Bundle state) { + ensureList(); + super.onRestoreInstanceState(state); + } + + /** + * Updates the screen state (current list and other views) when the + * content changes. + * + * @see Activity#onContentChanged() + */ + @Override + public void onContentChanged() { + super.onContentChanged(); + View emptyView = findViewById(android.R.id.empty); + mList = (ListView)findViewById(android.R.id.list); + if (mList == null) { + throw new RuntimeException( + "Your content must have a ListView whose id attribute is " + + "'android.R.id.list'"); + } + if (emptyView != null) { + mList.setEmptyView(emptyView); + } + mList.setOnItemClickListener(mOnClickListener); + if (mFinishedStart) { + setListAdapter(mAdapter); + } + mHandler.post(mRequestFocus); + mFinishedStart = true; + } + + /** + * Provide the cursor for the list view. + */ + public void setListAdapter(ListAdapter adapter) { + synchronized (this) { + ensureList(); + mAdapter = adapter; + mList.setAdapter(adapter); + } + } + + /** + * Set the currently selected list item to the specified + * position with the adapter's data + * + * @param position + */ + public void setSelection(int position) { + mList.setSelection(position); + } + + /** + * Get the position of the currently selected list item. + */ + public int getSelectedItemPosition() { + return mList.getSelectedItemPosition(); + } + + /** + * Get the cursor row ID of the currently selected list item. + */ + public long getSelectedItemId() { + return mList.getSelectedItemId(); + } + + /** + * Get the activity's list view widget. + */ + public ListView getListView() { + ensureList(); + return mList; + } + + /** + * Get the ListAdapter associated with this activity's ListView. + */ + public ListAdapter getListAdapter() { + return mAdapter; + } + + private void ensureList() { + if (mList != null) { + return; + } + setContentView(android.R.layout.list_content); + + } + + private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View v, int position, long id) + { + onListItemClick((ListView)parent, v, position, id); + } + }; +} + diff --git a/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java new file mode 100644 index 0000000..027ff53 --- /dev/null +++ b/main/thirdparty/cgeo/org/kxml2/io/KXmlSerializer.java @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package cgeo.org.kxml2.io; + +import org.apache.commons.lang3.StringUtils; +import org.xmlpull.v1.XmlSerializer; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.Locale; + +public class KXmlSerializer implements XmlSerializer { + + // static final String UNDEFINED = ":"; + + // BEGIN android-added + /** size (in characters) for the write buffer */ + private static final int WRITE_BUFFER_SIZE = 500; + // END android-added + + // BEGIN android-changed + // (Guarantee that the writer is always buffered.) + private BufferedWriter writer; + // END android-changed + + private boolean pending; + private int auto; + private int depth; + + private String[] elementStack = new String[12]; + //nsp/prefix/name + private int[] nspCounts = new int[4]; + private String[] nspStack = new String[8]; + //prefix/nsp; both empty are "" + private boolean[] indent = new boolean[4]; + private boolean unicode; + private String encoding; + + private final void check(boolean close) throws IOException { + if (!pending) { + return; + } + + depth++; + pending = false; + + if (indent.length <= depth) { + boolean[] hlp = new boolean[depth + 4]; + System.arraycopy(indent, 0, hlp, 0, depth); + indent = hlp; + } + indent[depth] = indent[depth - 1]; + + for (int i = nspCounts[depth - 1]; i < nspCounts[depth]; i++) { + writer.write(' '); + writer.write("xmlns"); + if (!StringUtils.isEmpty(nspStack[i * 2])) { + writer.write(':'); + writer.write(nspStack[i * 2]); + } + else if (StringUtils.isEmpty(getNamespace()) && !StringUtils.isEmpty(nspStack[i * 2 + 1])) { + throw new IllegalStateException("Cannot set default namespace for elements in no namespace"); + } + writer.write("=\""); + writeEscaped(nspStack[i * 2 + 1], '"'); + writer.write('"'); + } + + if (nspCounts.length <= depth + 1) { + int[] hlp = new int[depth + 8]; + System.arraycopy(nspCounts, 0, hlp, 0, depth + 1); + nspCounts = hlp; + } + + nspCounts[depth + 1] = nspCounts[depth]; + // nspCounts[depth + 2] = nspCounts[depth]; + + writer.write(close ? " />" : ">"); + } + + private final void writeEscaped(String s, int quot) throws IOException { + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '\n': + case '\r': + case '\t': + if (quot == -1) { + writer.write(c); + } else { + writer.write("&#"+((int) c)+';'); + } + break; + case '&': + writer.write("&"); + break; + case '>': + writer.write(">"); + break; + case '<': + writer.write("<"); + break; + default: + if (c == quot) { + writer.write(c == '"' ? """ : "'"); + break; + } + // BEGIN android-changed: refuse to output invalid characters + // See http://www.w3.org/TR/REC-xml/#charsets for definition. + // Corrected for c:geo to handle utf-16 codepoint surrogates correctly + // See http://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B10000_to_U.2B10FFFF + // Note: tab, newline, and carriage return have already been + // handled above. + // Check for lead surrogate + if (c >= 0xd800 && c <= 0xdbff) { + + if (i + 1 < s.length()) { + writer.write(s.substring(i, i + 1)); + i++; + break; + } + // if the lead surrogate is at the string end, it's not valid utf-16 + reportInvalidCharacter(c); + } + boolean valid = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd); + if (!valid) { + reportInvalidCharacter(c); + } + if (unicode || c < 127) { + writer.write(c); + } else { + writer.write("&#" + ((int) c) + ";"); + } + // END android-changed + } + } + } + + // BEGIN android-added + private static void reportInvalidCharacter(char ch) { + throw new IllegalArgumentException("Illegal character (" + Integer.toHexString((int) ch) + ")"); + } + // END android-added + + /* + * private final void writeIndent() throws IOException { + * writer.write("\r\n"); + * for (int i = 0; i < depth; i++) + * writer.write(' '); + * } + */ + + public void docdecl(String dd) throws IOException { + writer.write(""); + } + + public void endDocument() throws IOException { + while (depth > 0) { + endTag(elementStack[depth * 3 - 3], elementStack[depth * 3 - 1]); + } + flush(); + } + + public void entityRef(String name) throws IOException { + check(false); + writer.write('&'); + writer.write(name); + writer.write(';'); + } + + public boolean getFeature(String name) { + //return false; + return ("http://xmlpull.org/v1/doc/features.html#indent-output" + .equals( + name)) + ? indent[depth] + : false; + } + + public String getPrefix(String namespace, boolean create) { + try { + return getPrefix(namespace, false, create); + } catch (IOException e) { + throw new RuntimeException(e.toString()); + } + } + + private final String getPrefix( + String namespace, + boolean includeDefault, + boolean create) + throws IOException { + + for (int i = nspCounts[depth + 1] * 2 - 2; i >= 0; i -= 2) { + if (nspStack[i + 1].equals(namespace) + && (includeDefault || !StringUtils.isEmpty(nspStack[i]))) { + String cand = nspStack[i]; + for (int j = i + 2; j < nspCounts[depth + 1] * 2; j++) { + if (nspStack[j].equals(cand)) { + cand = null; + break; + } + } + if (cand != null) { + return cand; + } + } + } + + if (!create) { + return null; + } + + String prefix; + + if (StringUtils.isEmpty(namespace)) { + prefix = ""; + } else { + do { + prefix = "n" + (auto++); + for (int i = nspCounts[depth + 1] * 2 - 2; i >= 0; i -= 2) { + if (prefix.equals(nspStack[i])) { + prefix = null; + break; + } + } + } while (prefix == null); + } + + boolean p = pending; + pending = false; + setPrefix(prefix, namespace); + pending = p; + return prefix; + } + + public Object getProperty(String name) { + throw new RuntimeException("Unsupported property"); + } + + public void ignorableWhitespace(String s) + throws IOException { + text(s); + } + + public void setFeature(String name, boolean value) { + if ("http://xmlpull.org/v1/doc/features.html#indent-output" + .equals(name)) { + indent[depth] = value; + } else { + throw new RuntimeException("Unsupported Feature"); + } + } + + public void setProperty(String name, Object value) { + throw new RuntimeException( + "Unsupported Property:" + value); + } + + public void setPrefix(String prefix, String namespace) + throws IOException { + + check(false); + if (prefix == null) { + prefix = ""; + } + if (namespace == null) { + namespace = ""; + } + + String defined = getPrefix(namespace, true, false); + + // boil out if already defined + + if (prefix.equals(defined)) { + return; + } + + int pos = (nspCounts[depth + 1]++) << 1; + + if (nspStack.length < pos + 1) { + String[] hlp = new String[nspStack.length + 16]; + System.arraycopy(nspStack, 0, hlp, 0, pos); + nspStack = hlp; + } + + nspStack[pos++] = prefix; + nspStack[pos] = namespace; + } + + public void setOutput(Writer writer) { + // BEGIN android-changed + // Guarantee that the writer is always buffered. + if (writer instanceof BufferedWriter) { + this.writer = (BufferedWriter) writer; + } else { + this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE); + } + // END android-changed + + // elementStack = new String[12]; //nsp/prefix/name + //nspCounts = new int[4]; + //nspStack = new String[8]; //prefix/nsp + //indent = new boolean[4]; + + nspCounts[0] = 2; + nspCounts[1] = 2; + nspStack[0] = ""; + nspStack[1] = ""; + nspStack[2] = "xml"; + nspStack[3] = "http://www.w3.org/XML/1998/namespace"; + pending = false; + auto = 0; + depth = 0; + + unicode = false; + } + + public void setOutput(OutputStream os, String encoding) + throws IOException { + if (os == null) { + throw new IllegalArgumentException("os == null"); + } + setOutput(encoding == null + ? new OutputStreamWriter(os) + : new OutputStreamWriter(os, encoding)); + this.encoding = encoding; + if (encoding != null && encoding.toLowerCase(Locale.US).startsWith("utf")) { + unicode = true; + } + } + + public void startDocument(String encoding, Boolean standalone) throws IOException { + writer.write(""); + } + + public XmlSerializer startTag(String namespace, String name) + throws IOException { + check(false); + + // if (namespace == null) + // namespace = ""; + + if (indent[depth]) { + writer.write("\r\n"); + for (int i = 0; i < depth; i++) { + writer.write(" "); + } + } + + int esp = depth * 3; + + if (elementStack.length < esp + 3) { + String[] hlp = new String[elementStack.length + 12]; + System.arraycopy(elementStack, 0, hlp, 0, esp); + elementStack = hlp; + } + + String prefix = + namespace == null + ? "" + : getPrefix(namespace, true, true); + + if (namespace != null && StringUtils.isEmpty(namespace)) { + for (int i = nspCounts[depth]; i < nspCounts[depth + 1]; i++) { + if (StringUtils.isEmpty(nspStack[i * 2]) && !StringUtils.isEmpty(nspStack[i * 2 + 1])) { + throw new IllegalStateException("Cannot set default namespace for elements in no namespace"); + } + } + } + + elementStack[esp++] = namespace; + elementStack[esp++] = prefix; + elementStack[esp] = name; + + writer.write('<'); + if (!StringUtils.isEmpty(prefix)) { + writer.write(prefix); + writer.write(':'); + } + + writer.write(name); + + pending = true; + + return this; + } + + public XmlSerializer attribute( + String namespace, + String name, + String value) + throws IOException { + if (!pending) { + throw new IllegalStateException("illegal position for attribute"); + } + + // int cnt = nspCounts[depth]; + + if (namespace == null) { + namespace = ""; + } + + // depth--; + // pending = false; + + String prefix = + StringUtils.isEmpty(namespace) + ? "" + : getPrefix(namespace, false, true); + + // pending = true; + // depth++; + + /* + * if (cnt != nspCounts[depth]) { + * writer.write(' '); + * writer.write("xmlns"); + * if (nspStack[cnt * 2] != null) { + * writer.write(':'); + * writer.write(nspStack[cnt * 2]); + * } + * writer.write("=\""); + * writeEscaped(nspStack[cnt * 2 + 1], '"'); + * writer.write('"'); + * } + */ + + writer.write(' '); + if (!StringUtils.isEmpty(prefix)) { + writer.write(prefix); + writer.write(':'); + } + writer.write(name); + writer.write('='); + char q = value.indexOf('"') == -1 ? '"' : '\''; + writer.write(q); + writeEscaped(value, q); + writer.write(q); + + return this; + } + + public void flush() throws IOException { + check(false); + writer.flush(); + } + + /* + * public void close() throws IOException { + * check(); + * writer.close(); + * } + */ + public XmlSerializer endTag(String namespace, String name) + throws IOException { + + if (!pending) + { + depth--; + // if (namespace == null) + // namespace = ""; + } + + if ((namespace == null + && elementStack[depth * 3] != null) + || (namespace != null + && !namespace.equals(elementStack[depth * 3])) + || !elementStack[depth * 3 + 2].equals(name)) { + throw new IllegalArgumentException(" does not match start"); + } + + if (pending) { + check(true); + depth--; + } + else { + if (indent[depth + 1]) { + writer.write("\r\n"); + for (int i = 0; i < depth; i++) { + writer.write(" "); + } + } + + writer.write("'); + } + + nspCounts[depth + 1] = nspCounts[depth]; + return this; + } + + public String getNamespace() { + return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3]; + } + + public String getName() { + return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1]; + } + + public int getDepth() { + return pending ? depth + 1 : depth; + } + + public XmlSerializer text(String text) throws IOException { + check(false); + indent[depth] = false; + writeEscaped(text, -1); + return this; + } + + public XmlSerializer text(char[] text, int start, int len) + throws IOException { + text(new String(text, start, len)); + return this; + } + + public void cdsect(String data) throws IOException { + check(false); + // BEGIN android-changed: ]]> is not allowed within a CDATA, + // so break and start a new one when necessary. + data = data.replace("]]>", "]]]]>"); + char[] chars = data.toCharArray(); + // We also aren't allowed any invalid characters. + for (char ch : chars) { + boolean valid = (ch >= 0x20 && ch <= 0xd7ff) || + (ch == '\t' || ch == '\n' || ch == '\r') || + (ch >= 0xe000 && ch <= 0xfffd); + if (!valid) { + reportInvalidCharacter(ch); + } + } + writer.write(""); + // END android-changed + } + + public void comment(String comment) throws IOException { + check(false); + writer.write(""); + } + + public void processingInstruction(String pi) + throws IOException { + check(false); + writer.write(""); + } +} \ No newline at end of file diff --git a/main/thirdparty/com/viewpagerindicator/PageIndicator.java b/main/thirdparty/com/viewpagerindicator/PageIndicator.java new file mode 100644 index 0000000..26414d8 --- /dev/null +++ b/main/thirdparty/com/viewpagerindicator/PageIndicator.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 Patrik Akerfeldt + * Copyright (C) 2011 Jake Wharton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.viewpagerindicator; + +import android.support.v4.view.ViewPager; + +/** + * A PageIndicator is responsible to show an visual indicator on the total views + * number and the current visible view. + */ +public interface PageIndicator extends ViewPager.OnPageChangeListener { + /** + * Bind the indicator to a ViewPager. + * + * @param view + */ + public void setViewPager(ViewPager view); + + /** + * Bind the indicator to a ViewPager. + * + * @param view + * @param initialPosition + */ + public void setViewPager(ViewPager view, int initialPosition); + + /** + *

Set the current page of both the ViewPager and indicator.

+ * + *

This must be used if you need to set the page before + * the views are drawn on screen (e.g., default start page).

+ * + * @param item + */ + public void setCurrentItem(int item); + + /** + * Set a page change listener which will receive forwarded events. + * + * @param listener + */ + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); + + /** + * Notify the indicator that the fragment list has changed. + */ + public void notifyDataSetChanged(); +} diff --git a/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java b/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java new file mode 100644 index 0000000..94ac962 --- /dev/null +++ b/main/thirdparty/com/viewpagerindicator/TitlePageIndicator.java @@ -0,0 +1,771 @@ +/* + * Copyright (C) 2011 Patrik Akerfeldt + * Copyright (C) 2011 Francisco Figueiredo Jr. + * Copyright (C) 2011 Jake Wharton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.viewpagerindicator; + +import cgeo.geocaching.R; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.PagerAdapter; +import android.support.v4.view.ViewConfigurationCompat; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; + +import java.util.ArrayList; + +/** + * A TitlePageIndicator is a PageIndicator which displays the title of left view + * (if exist), the title of the current select view (centered) and the title of + * the right view (if exist). When the user scrolls the ViewPager then titles are + * also scrolled. + */ +public class TitlePageIndicator extends View implements PageIndicator { + /** + * Percentage indicating what percentage of the screen width away from + * center should the underline be fully faded. A value of 0.25 means that + * halfway between the center of the screen and an edge. + */ + private static final float SELECTION_FADE_PERCENTAGE = 0.25f; + + /** + * Percentage indicating what percentage of the screen width away from + * center should the selected text bold turn off. A value of 0.05 means + * that 10% between the center and an edge. + */ + private static final float BOLD_FADE_PERCENTAGE = 0.05f; + + public enum IndicatorStyle { + None(0), Triangle(1), Underline(2); + + public final int value; + + IndicatorStyle(int value) { + this.value = value; + } + + public static IndicatorStyle fromValue(int value) { + for (IndicatorStyle style : IndicatorStyle.values()) { + if (style.value == value) { + return style; + } + } + return null; + } + } + + private ViewPager mViewPager; + private ViewPager.OnPageChangeListener mListener; + private TitleProvider mTitleProvider; + private int mCurrentPage; + private int mCurrentOffset; + private int mScrollState; + private final Paint mPaintText; + private boolean mBoldText; + private int mColorText; + private int mColorSelected; + private Path mPath = new Path(); + private final Paint mPaintFooterLine; + private IndicatorStyle mFooterIndicatorStyle; + private final Paint mPaintFooterIndicator; + private float mFooterIndicatorHeight; + private float mFooterIndicatorUnderlinePadding; + private float mFooterPadding; + private float mTitlePadding; + private float mTopPadding; + /** Left and right side padding for not active view titles. */ + private float mClipPadding; + private float mFooterLineHeight; + + private static final int INVALID_POINTER = -1; + + private int mTouchSlop; + private float mLastMotionX = -1; + private int mActivePointerId = INVALID_POINTER; + private boolean mIsDragging; + + + public TitlePageIndicator(Context context) { + this(context, null); + } + + public TitlePageIndicator(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.vpiTitlePageIndicatorStyle); + } + + public TitlePageIndicator(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + //Load defaults from resources + final Resources res = getResources(); + final int defaultFooterColor = res.getColor(R.color.default_title_indicator_footer_color); + final float defaultFooterLineHeight = res.getDimension(R.dimen.default_title_indicator_footer_line_height); + final int defaultFooterIndicatorStyle = res.getInteger(R.integer.default_title_indicator_footer_indicator_style); + final float defaultFooterIndicatorHeight = res.getDimension(R.dimen.default_title_indicator_footer_indicator_height); + final float defaultFooterIndicatorUnderlinePadding = res.getDimension(R.dimen.default_title_indicator_footer_indicator_underline_padding); + final float defaultFooterPadding = res.getDimension(R.dimen.default_title_indicator_footer_padding); + final int defaultSelectedColor = res.getColor(R.color.default_title_indicator_selected_color); + final boolean defaultSelectedBold = res.getBoolean(R.bool.default_title_indicator_selected_bold); + final int defaultTextColor = res.getColor(R.color.default_title_indicator_text_color); + final float defaultTextSize = res.getDimension(R.dimen.default_title_indicator_text_size); + final float defaultTitlePadding = res.getDimension(R.dimen.default_title_indicator_title_padding); + final float defaultClipPadding = res.getDimension(R.dimen.default_title_indicator_clip_padding); + final float defaultTopPadding = res.getDimension(R.dimen.default_title_indicator_top_padding); + + //Retrieve styles attributes + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitlePageIndicator, defStyle, R.style.Widget_TitlePageIndicator); + + //Retrieve the colors to be used for this view and apply them. + mFooterLineHeight = a.getDimension(R.styleable.TitlePageIndicator_footerLineHeight, defaultFooterLineHeight); + mFooterIndicatorStyle = IndicatorStyle.fromValue(a.getInteger(R.styleable.TitlePageIndicator_footerIndicatorStyle, defaultFooterIndicatorStyle)); + mFooterIndicatorHeight = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorHeight, defaultFooterIndicatorHeight); + mFooterIndicatorUnderlinePadding = a.getDimension(R.styleable.TitlePageIndicator_footerIndicatorUnderlinePadding, defaultFooterIndicatorUnderlinePadding); + mFooterPadding = a.getDimension(R.styleable.TitlePageIndicator_footerPadding, defaultFooterPadding); + mTopPadding = a.getDimension(R.styleable.TitlePageIndicator_topPadding, defaultTopPadding); + mTitlePadding = a.getDimension(R.styleable.TitlePageIndicator_titlePadding, defaultTitlePadding); + mClipPadding = a.getDimension(R.styleable.TitlePageIndicator_clipPadding, defaultClipPadding); + mColorSelected = a.getColor(R.styleable.TitlePageIndicator_selectedColor, defaultSelectedColor); + mColorText = a.getColor(R.styleable.TitlePageIndicator_textColor, defaultTextColor); + mBoldText = a.getBoolean(R.styleable.TitlePageIndicator_selectedBold, defaultSelectedBold); + + final float textSize = a.getDimension(R.styleable.TitlePageIndicator_textSize, defaultTextSize); + final int footerColor = a.getColor(R.styleable.TitlePageIndicator_footerColor, defaultFooterColor); + mPaintText = new Paint(); + mPaintText.setTextSize(textSize); + mPaintText.setAntiAlias(true); + mPaintFooterLine = new Paint(); + mPaintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE); + mPaintFooterLine.setStrokeWidth(mFooterLineHeight); + mPaintFooterLine.setColor(footerColor); + mPaintFooterIndicator = new Paint(); + mPaintFooterIndicator.setStyle(Paint.Style.FILL_AND_STROKE); + mPaintFooterIndicator.setColor(footerColor); + + a.recycle(); + + final ViewConfiguration configuration = ViewConfiguration.get(context); + mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); + } + + + public int getFooterColor() { + return mPaintFooterLine.getColor(); + } + + public void setFooterColor(int footerColor) { + mPaintFooterLine.setColor(footerColor); + mPaintFooterIndicator.setColor(footerColor); + invalidate(); + } + + public float getFooterLineHeight() { + return mFooterLineHeight; + } + + public void setFooterLineHeight(float footerLineHeight) { + mFooterLineHeight = footerLineHeight; + mPaintFooterLine.setStrokeWidth(mFooterLineHeight); + invalidate(); + } + + public float getFooterIndicatorHeight() { + return mFooterIndicatorHeight; + } + + public void setFooterIndicatorHeight(float footerTriangleHeight) { + mFooterIndicatorHeight = footerTriangleHeight; + invalidate(); + } + + public float getFooterIndicatorPadding() { + return mFooterPadding; + } + + public void setFooterIndicatorPadding(float footerIndicatorPadding) { + mFooterPadding = footerIndicatorPadding; + invalidate(); + } + + public IndicatorStyle getFooterIndicatorStyle() { + return mFooterIndicatorStyle; + } + + public void setFooterIndicatorStyle(IndicatorStyle indicatorStyle) { + mFooterIndicatorStyle = indicatorStyle; + invalidate(); + } + + public int getSelectedColor() { + return mColorSelected; + } + + public void setSelectedColor(int selectedColor) { + mColorSelected = selectedColor; + invalidate(); + } + + public boolean isSelectedBold() { + return mBoldText; + } + + public void setSelectedBold(boolean selectedBold) { + mBoldText = selectedBold; + invalidate(); + } + + public int getTextColor() { + return mColorText; + } + + public void setTextColor(int textColor) { + mPaintText.setColor(textColor); + mColorText = textColor; + invalidate(); + } + + public float getTextSize() { + return mPaintText.getTextSize(); + } + + public void setTextSize(float textSize) { + mPaintText.setTextSize(textSize); + invalidate(); + } + + public float getTitlePadding() { + return this.mTitlePadding; + } + + public void setTitlePadding(float titlePadding) { + mTitlePadding = titlePadding; + invalidate(); + } + + public float getTopPadding() { + return this.mTopPadding; + } + + public void setTopPadding(float topPadding) { + mTopPadding = topPadding; + invalidate(); + } + + public float getClipPadding() { + return this.mClipPadding; + } + + public void setClipPadding(float clipPadding) { + mClipPadding = clipPadding; + invalidate(); + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onDraw(android.graphics.Canvas) + */ + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (mViewPager == null) { + return; + } + final int count = mViewPager.getAdapter().getCount(); + if (count == 0) { + return; + } + + //Calculate views bounds + ArrayList bounds = calculateAllBounds(mPaintText); + + //Make sure we're on a page that still exists + if (mCurrentPage >= bounds.size()) { + setCurrentItem(bounds.size()-1); + } + + final int countMinusOne = count - 1; + final float halfWidth = getWidth() / 2f; + final int left = getLeft(); + final float leftClip = left + mClipPadding; + final int width = getWidth(); + final int height = getHeight(); + final int right = left + width; + final float rightClip = right - mClipPadding; + + int page = mCurrentPage; + float offsetPercent; + if (mCurrentOffset <= halfWidth) { + offsetPercent = 1.0f * mCurrentOffset / width; + } else { + page += 1; + offsetPercent = 1.0f * (width - mCurrentOffset) / width; + } + final boolean currentSelected = (offsetPercent <= SELECTION_FADE_PERCENTAGE); + final boolean currentBold = (offsetPercent <= BOLD_FADE_PERCENTAGE); + final float selectedPercent = (SELECTION_FADE_PERCENTAGE - offsetPercent) / SELECTION_FADE_PERCENTAGE; + + //Verify if the current view must be clipped to the screen + RectF curPageBound = bounds.get(mCurrentPage); + float curPageWidth = curPageBound.right - curPageBound.left; + if (curPageBound.left < leftClip) { + //Try to clip to the screen (left side) + clipViewOnTheLeft(curPageBound, curPageWidth, left); + } + if (curPageBound.right > rightClip) { + //Try to clip to the screen (right side) + clipViewOnTheRight(curPageBound, curPageWidth, right); + } + + //Left views starting from the current position + if (mCurrentPage > 0) { + for (int i = mCurrentPage - 1; i >= 0; i--) { + RectF bound = bounds.get(i); + //Is left side is outside the screen + if (bound.left < leftClip) { + float w = bound.right - bound.left; + //Try to clip to the screen (left side) + clipViewOnTheLeft(bound, w, left); + //Except if there's an intersection with the right view + RectF rightBound = bounds.get(i + 1); + //Intersection + if (bound.right + mTitlePadding > rightBound.left) { + bound.left = rightBound.left - w - mTitlePadding; + bound.right = bound.left + w; + } + } + } + } + //Right views starting from the current position + if (mCurrentPage < countMinusOne) { + for (int i = mCurrentPage + 1 ; i < count; i++) { + RectF bound = bounds.get(i); + //If right side is outside the screen + if (bound.right > rightClip) { + float w = bound.right - bound.left; + //Try to clip to the screen (right side) + clipViewOnTheRight(bound, w, right); + //Except if there's an intersection with the left view + RectF leftBound = bounds.get(i - 1); + //Intersection + if (bound.left - mTitlePadding < leftBound.right) { + bound.left = leftBound.right + mTitlePadding; + bound.right = bound.left + w; + } + } + } + } + + //Now draw views + for (int i = 0; i < count; i++) { + //Get the title + RectF bound = bounds.get(i); + //Only if one side is visible + if ((bound.left > left && bound.left < right) || (bound.right > left && bound.right < right)) { + final boolean currentPage = (i == page); + //Only set bold if we are within bounds + mPaintText.setFakeBoldText(currentPage && currentBold && mBoldText); + + //Draw text as unselected + mPaintText.setColor(mColorText); + canvas.drawText(mTitleProvider.getTitle(i), bound.left, bound.bottom + mTopPadding, mPaintText); + + //If we are within the selected bounds draw the selected text + if (currentPage && currentSelected) { + mPaintText.setColor(mColorSelected); + mPaintText.setAlpha((int)((mColorSelected >>> 24) * selectedPercent)); + canvas.drawText(mTitleProvider.getTitle(i), bound.left, bound.bottom + mTopPadding, mPaintText); + } + } + } + + //Draw the footer line + mPath.reset(); + mPath.moveTo(0, height - mFooterLineHeight / 2f); + mPath.lineTo(width, height - mFooterLineHeight / 2f); + mPath.close(); + canvas.drawPath(mPath, mPaintFooterLine); + + switch (mFooterIndicatorStyle) { + case Triangle: + mPath.reset(); + mPath.moveTo(halfWidth, height - mFooterLineHeight - mFooterIndicatorHeight); + mPath.lineTo(halfWidth + mFooterIndicatorHeight, height - mFooterLineHeight); + mPath.lineTo(halfWidth - mFooterIndicatorHeight, height - mFooterLineHeight); + mPath.close(); + canvas.drawPath(mPath, mPaintFooterIndicator); + break; + + case Underline: + if (!currentSelected) { + break; + } + + RectF underlineBounds = bounds.get(page); + mPath.reset(); + mPath.moveTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight); + mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight); + mPath.lineTo(underlineBounds.right + mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight); + mPath.lineTo(underlineBounds.left - mFooterIndicatorUnderlinePadding, height - mFooterLineHeight - mFooterIndicatorHeight); + mPath.close(); + + mPaintFooterIndicator.setAlpha((int)(0xFF * selectedPercent)); + canvas.drawPath(mPath, mPaintFooterIndicator); + mPaintFooterIndicator.setAlpha(0xFF); + break; + + default: + break; + } + } + + @Override + public boolean onTouchEvent(android.view.MotionEvent ev) { + if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { + return false; + } + + final int action = ev.getAction(); + + switch (action & MotionEventCompat.ACTION_MASK) { + case MotionEvent.ACTION_DOWN: + mActivePointerId = MotionEventCompat.getPointerId(ev, 0); + mLastMotionX = ev.getX(); + break; + + case MotionEvent.ACTION_MOVE: { + final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); + final float x = MotionEventCompat.getX(ev, activePointerIndex); + final float deltaX = x - mLastMotionX; + + if (!mIsDragging) { + if (Math.abs(deltaX) > mTouchSlop) { + mIsDragging = true; + } + } + + if (mIsDragging) { + if (!mViewPager.isFakeDragging()) { + mViewPager.beginFakeDrag(); + } + + mLastMotionX = x; + + mViewPager.fakeDragBy(deltaX); + } + + break; + } + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (!mIsDragging) { + final int count = mViewPager.getAdapter().getCount(); + final int width = getWidth(); + final float halfWidth = width / 2f; + final float sixthWidth = width / 6f; + + if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { + mViewPager.setCurrentItem(mCurrentPage - 1); + return true; + } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { + mViewPager.setCurrentItem(mCurrentPage + 1); + return true; + } + } + + mIsDragging = false; + mActivePointerId = INVALID_POINTER; + if (mViewPager.isFakeDragging()) { + mViewPager.endFakeDrag(); + } + break; + + case MotionEventCompat.ACTION_POINTER_DOWN: { + final int index = MotionEventCompat.getActionIndex(ev); + mLastMotionX = MotionEventCompat.getX(ev, index); + mActivePointerId = MotionEventCompat.getPointerId(ev, index); + break; + } + + case MotionEventCompat.ACTION_POINTER_UP: + final int pointerIndex = MotionEventCompat.getActionIndex(ev); + final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); + if (pointerId == mActivePointerId) { + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); + } + mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); + break; + } + + return true; + } + + /** + * Set bounds for the right textView including clip padding. + * + * @param curViewBound + * current bounds. + * @param curViewWidth + * width of the view. + */ + private void clipViewOnTheRight(RectF curViewBound, float curViewWidth, int right) { + curViewBound.right = right - mClipPadding; + curViewBound.left = curViewBound.right - curViewWidth; + } + + /** + * Set bounds for the left textView including clip padding. + * + * @param curViewBound + * current bounds. + * @param curViewWidth + * width of the view. + */ + private void clipViewOnTheLeft(RectF curViewBound, float curViewWidth, int left) { + curViewBound.left = left + mClipPadding; + curViewBound.right = mClipPadding + curViewWidth; + } + + /** + * Calculate views bounds and scroll them according to the current index + * + * @param paint + * @param currentIndex + * @return + */ + private ArrayList calculateAllBounds(Paint paint) { + ArrayList list = new ArrayList(); + //For each views (If no values then add a fake one) + final int count = mViewPager.getAdapter().getCount(); + final int width = getWidth(); + final int halfWidth = width / 2; + for (int i = 0; i < count; i++) { + RectF bounds = calcBounds(i, paint); + float w = (bounds.right - bounds.left); + float h = (bounds.bottom - bounds.top); + bounds.left = (halfWidth) - (w / 2) - mCurrentOffset + ((i - mCurrentPage) * width); + bounds.right = bounds.left + w; + bounds.top = 0; + bounds.bottom = h; + list.add(bounds); + } + + return list; + } + + /** + * Calculate the bounds for a view's title + * + * @param index + * @param paint + * @return + */ + private RectF calcBounds(int index, Paint paint) { + //Calculate the text bounds + RectF bounds = new RectF(); + bounds.right = paint.measureText(mTitleProvider.getTitle(index)); + bounds.bottom = paint.descent() - paint.ascent(); + return bounds; + } + + @Override + public void setViewPager(ViewPager view) { + final PagerAdapter adapter = view.getAdapter(); + if (adapter == null) { + throw new IllegalStateException("ViewPager does not have adapter instance."); + } + if (!(adapter instanceof TitleProvider)) { + throw new IllegalStateException("ViewPager adapter must implement TitleProvider to be used with TitlePageIndicator."); + } + mViewPager = view; + mViewPager.setOnPageChangeListener(this); + mTitleProvider = (TitleProvider)adapter; + invalidate(); + } + + @Override + public void setViewPager(ViewPager view, int initialPosition) { + setViewPager(view); + setCurrentItem(initialPosition); + } + + @Override + public void notifyDataSetChanged() { + invalidate(); + } + + @Override + public void setCurrentItem(int item) { + if (mViewPager == null) { + throw new IllegalStateException("ViewPager has not been bound."); + } + mViewPager.setCurrentItem(item); + mCurrentPage = item; + invalidate(); + } + + @Override + public void onPageScrollStateChanged(int state) { + mScrollState = state; + + if (mListener != null) { + mListener.onPageScrollStateChanged(state); + } + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + mCurrentPage = position; + mCurrentOffset = positionOffsetPixels; + invalidate(); + + if (mListener != null) { + mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); + } + } + + @Override + public void onPageSelected(int position) { + if (mScrollState == ViewPager.SCROLL_STATE_IDLE) { + mCurrentPage = position; + invalidate(); + } + + if (mListener != null) { + mListener.onPageSelected(position); + } + } + + @Override + public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { + mListener = listener; + } + + /* + * (non-Javadoc) + * + * @see android.view.View#onMeasure(int, int) + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); + } + + /** + * Determines the width of this view + * + * @param measureSpec + * A measureSpec packed into an int + * @return The width of the view, honoring constraints from measureSpec + */ + private int measureWidth(int measureSpec) { + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode != MeasureSpec.EXACTLY) { + throw new IllegalStateException(getClass().getSimpleName() + " can only be used in EXACTLY mode."); + } + return specSize; + } + + /** + * Determines the height of this view + * + * @param measureSpec + * A measureSpec packed into an int + * @return The height of the view, honoring constraints from measureSpec + */ + private int measureHeight(int measureSpec) { + float result; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + if (specMode == MeasureSpec.EXACTLY) { + //We were told how big to be + result = specSize; + } else { + //Calculate the text bounds + RectF bounds = new RectF(); + bounds.bottom = mPaintText.descent()-mPaintText.ascent(); + result = bounds.bottom - bounds.top + mFooterLineHeight + mFooterPadding + mTopPadding; + if (mFooterIndicatorStyle != IndicatorStyle.None) { + result += mFooterIndicatorHeight; + } + } + return (int)result; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState savedState = (SavedState)state; + super.onRestoreInstanceState(savedState.getSuperState()); + mCurrentPage = savedState.currentPage; + requestLayout(); + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState savedState = new SavedState(superState); + savedState.currentPage = mCurrentPage; + return savedState; + } + + static class SavedState extends BaseSavedState { + int currentPage; + + public SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + currentPage = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(currentPage); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } +} diff --git a/main/thirdparty/com/viewpagerindicator/TitleProvider.java b/main/thirdparty/com/viewpagerindicator/TitleProvider.java new file mode 100644 index 0000000..2a04b65 --- /dev/null +++ b/main/thirdparty/com/viewpagerindicator/TitleProvider.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 Patrik Akerfeldt + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.viewpagerindicator; + +/** + * A TitleProvider provides the title to display according to a view. + */ +public interface TitleProvider { + /** + * Returns the title of the view at position + * @param position + * @return + */ + public String getTitle(int position); +} diff --git a/main/thirdparty/gnu/android/app/appmanualclient/AppManualReaderClient.java b/main/thirdparty/gnu/android/app/appmanualclient/AppManualReaderClient.java new file mode 100644 index 0000000..af4c03e --- /dev/null +++ b/main/thirdparty/gnu/android/app/appmanualclient/AppManualReaderClient.java @@ -0,0 +1,375 @@ +package gnu.android.app.appmanualclient; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.util.Log; + +import java.util.List; + +/** + * The "App Manual Reader" client is a class to be used in applications which + * want to offer their users manuals through the gnu.android.appmanualreader + * application. Such applications do not need to include the whole + * "App Manual Reader" app but instead just have to include only this little + * package. This package then provides the mechanism to open suitable installed + * manuals. It does not include any manuals itself. + *

+ * + * (c) 2011 Geocrasher (geocrasher@gmx.eu) + *

+ * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + *

+ * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + *

+ * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + * @author Geocrasher + */ +public class AppManualReaderClient { + + /** + * The URI scheme used to identify application manual URIs when flinging + * Intents around within an Android device, in the hope that there are + * activities registered which will handle such application manual URIs. + * Usually, there won't be just a single activity registered but instead + * many, depending on how many manuals are installed on an Android device. + */ + public static final String URI_SCHEME_APPMANUAL = "appmanual"; + + /** + * Standardized topic for opening a manual at its beginning. + * + * @see #openManual(String, String, Context) + * @see #openManual(String, String, Context, String) + */ + public static final String TOPIC_HOME = "andtw-home"; + /** + * Standardized topic for opening the index of a manual. + * + * @see #openManual(String, String, Context) + * @see #openManual(String, String, Context, String) + */ + public static final String TOPIC_INDEX = "andtw-index"; + /** + * Standardized topic for opening a manual's "about" topic. + * + * @see #openManual(String, String, Context) + * @see #openManual(String, String, Context, String) + */ + public static final String TOPIC_ABOUT_MANUAL = "andtw-about"; + + /** + * Convenience function to open a manual at a specific topic. See + * {@link #openManual(String, String, Context, String)} for a detailed + * description. + * + * @param manualIdentifier + * the identifier of the manual to open. This identifier must + * uniquely identify the manual as such, independent of the + * particular locale the manual is intended for. + * @param topic + * the topic to open. Please do not use spaces for topic names. + * With respect to the TiddlyWiki infrastructure used for manuals + * the topic needs to the tag of a (single) tiddler. This way + * manuals can be localized (especially their topic titles) + * without breaking an app's knowledge about topics. Some + * standardized topics are predefined, such as {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and + * {@link #TOPIC_ABOUT_MANUAL}. + * @param context + * the context (usually an Activity) from which the manual is to + * be opened. In particular, this context is required to derive + * the proper current locale configuration in order to open + * appropriate localized manuals, if installed. + * + * @exception ActivityNotFoundException + * there is no suitable manual installed and all combinations + * of locale scope failed to activate any manual. + * + * @see #openManual(String, String, Context, String, boolean) + */ + public static void openManual(String manualIdentifier, String topic, + Context context) throws ActivityNotFoundException { + openManual(manualIdentifier, topic, context, null, false); + } + + /** + * Convenience function to open a manual at a specific topic. See + * {@link #openManual(String, String, Context, String)} for a detailed + * description. + * + * @param manualIdentifier + * the identifier of the manual to open. This identifier must + * uniquely identify the manual as such, independent of the + * particular locale the manual is intended for. + * @param topic + * the topic to open. Please do not use spaces for topic names. + * With respect to the TiddlyWiki infrastructure used for manuals + * the topic needs to the tag of a (single) tiddler. This way + * manuals can be localized (especially their topic titles) + * without breaking an app's knowledge about topics. Some + * standardized topics are predefined, such as {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and + * {@link #TOPIC_ABOUT_MANUAL}. + * @param context + * the context (usually an Activity) from which the manual is to + * be opened. In particular, this context is required to derive + * the proper current locale configuration in order to open + * appropriate localized manuals, if installed. + * @param fallbackUri + * either null or a fallback URI to be used in case + * the user has not installed any suitable manual. + * + * @exception ActivityNotFoundException + * there is no suitable manual installed and all combinations + * of locale scope failed to activate any manual. + * + * @see #openManual(String, String, Context, String, boolean) + */ + public static void openManual(String manualIdentifier, String topic, + Context context, String fallbackUri) + throws ActivityNotFoundException { + openManual(manualIdentifier, topic, context, fallbackUri, false); + } + + /** + * Opens a manual at a specific topic. At least it tries to open a manual. + * As manuals are (usually) installed separately and we use late binding in + * form of implicit intents, a lot of things can go wrong. + * + * We use late binding and the intent architecture in particular as follows: + * first, we use our own URI scheme called "appmanual". Second, we use the + * host field as a unique manual identifier (such as "c-geo" for the app + * manuals for a map which must not be named by the powers that wanna be). + * Third, a localized manual is differentiated as a path with a single + * element in form of (in this precedence) "/lang_country_variant", + * "/lang__variant", "/lang_country", "/lang", or "/". Fourth, the topic to + * open is encoded as the a fragment "#topic=mytopic". + * + * In order to support localization, manuals can register themselves with + * different URIs. + * + * @param manualIdentifier + * the identifier of the manual to open. This identifier must + * uniquely identify the manual as such, independent of the + * particular locale the manual is intended for. + * @param topic + * the topic to open. Please do not use spaces for topic names. + * With respect to the TiddlyWiki infrastructure used for manuals + * the topic needs to the tag of a (single) tiddler. This way + * manuals can be localized (especially their topic titles) + * without breaking an app's knowledge about topics. Some + * standardized topics are predefined, such as + * {@link #TOPIC_HOME}, {@link #TOPIC_INDEX}, and + * {@link #TOPIC_ABOUT_MANUAL}. + * @param context + * the context (usually an Activity) from which the manual is to + * be opened. In particular, this context is required to derive + * the proper current locale configuration in order to open + * appropriate localized manuals, if installed. + * @param fallbackUri + * either null or a fallback URI to be used in case + * the user has not installed any suitable manual. + * @param contextAffinity + * if true, then we try to open the manual within + * the context, if possible. That is, if the package of the + * calling context also offers suitable activity registrations, + * then we will prefer them over any other registrations. If you + * don't know what this means, then you probably don't need this + * very special capability and should specify false + * for this parameter. + * + * @exception ActivityNotFoundException + * there is no suitable manual installed and all combinations + * of locale scope failed to activate any manual and no + * {@literal fallbackUri} was given. + */ + public static void openManual(String manualIdentifier, String topic, + Context context, String fallbackUri, boolean contextAffinity) + throws ActivityNotFoundException { + // + // The path of an "appmanual:" URI consists simply of the locale + // information. This allows manual packages to register themselves + // for both very specific locales as well as very broad ones. + // + String localePath = "/" + + context.getResources().getConfiguration().locale.toString(); + // + // We later need this intent in order to try to launch an appropriate + // manual (respectively its manual viewer). And yes, we need to set + // the intent's category explicitly, even as we will later use + // startActivity(): if we don't do this, the proper activity won't be + // started albeit the filter almost matches. That dirty behavior (it is + // documented wrong) had cost me half a day until I noticed some + // informational log entry generated from the ActivityManager. Grrrr! + // + Intent intent = new Intent(Intent.ACTION_VIEW); + int defaultIntentFlags = intent.getFlags(); + intent.addCategory(Intent.CATEGORY_DEFAULT); + // + // Try to open the manual in the following order (subject to + // availability): + // 1. manualIdentifier_lang_country_variant (can also be + // manualIdentifier_lang__variant in some cases) + // 2. manualIdentifier_lang_country + // 3. manualIdentifier_lang + // 4. manualIdentifier + // Of course, manuals are free to register more than one Intent, + // in particular, the should register also the plain manualIdentifier + // as a suitable fallback strategy. Even when installing multiple + // manuals this doesn't matter, as the user then can choose which + // one to use on a single or permanent basis. + // + while (true) { + Uri uri = Uri.parse(URI_SCHEME_APPMANUAL + "://" + manualIdentifier + + localePath + "#topic='" + topic + "'"); + // Note: we do not use a MIME type for this. + intent.setData(uri); + intent.setFlags(defaultIntentFlags); + if ( contextAffinity ) { + // + // What is happening here? Well, here we try something that we + // would like to call "package affinity activity resolving". + // Given an implicit(!) intent we try to figure out whether the + // package of the context which is trying to open the manual is + // able to resolve the intent. If this is the case, then we + // simply turn the implicit intent into an explicit(!) intent. + // We do this by setting the concrete module, that is: package + // name (eventually the one of the calling context) and class + // name within the package. + // + List capableActivities = context + .getPackageManager() + .queryIntentActivityOptions(null, null, intent, + PackageManager.MATCH_DEFAULT_ONLY); + int capables = capableActivities.size(); + if ( capables > 1 ) { + for ( int idx = 0; idx < capables; ++idx ) { + ActivityInfo activityInfo = capableActivities.get(idx).activityInfo; + if ( activityInfo.packageName.contentEquals(context + .getPackageName()) ) { + intent.setClassName(activityInfo.packageName, + activityInfo.name); + // + // First match is okay, so we quit searching and + // continue with the usual attempt to start the + // activity. This should not fail, as we already + // found a match; yet the code is very forgiving in + // this respect and would just try another round + // with "downsized" locale requirements. + // + break; + } + } + } + // FIXME + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + } else { + // + // No context affinity required, thus we need to set some flags: + // + // ...NEW_TASK: we want to start the manual reader activity as a + // separate + // task so that it can be kept open, yet in the background when + // returning to the application from which the manual was + // opened. + // + // ...SINGLE_TOP: + // + // ...RESET_TASK_IF_NEEDED: clear the manual reader activities + // down to the root activity. We've set the required + // ...CLEAR_WHEN_TASK_RESET above when opening the meta-manual + // with the context affinity. + // + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_SINGLE_TOP + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + } + try { + String logTag = "appmanualclient"; + if ( Log.isLoggable(logTag, Log.INFO) ) { + Log.i(logTag, + "Trying to activate manual: uri=" + uri.toString()); + } + context.startActivity(intent); + // + // We could successfully activate the manual activity, so no + // further trials are required. + // + return; + } catch ( ActivityNotFoundException noActivity ) { + // + // Ensure that we switch back to implicit intent resolving for + // the next round. + // + intent.setComponent(null); + // + // As long as we still have some locale information, reduce it + // and try again a broader locale. + // + if ( localePath.length() > 1 ) { + int underscore = localePath.lastIndexOf('_'); + if ( underscore > 0 ) { + localePath = localePath.substring(0, underscore); + // + // Handle the case where we have a locale variant, yet + // no locale country, thus two underscores in immediate + // series. Get rid of both. + // + if ( localePath.endsWith("_") ) { + localePath = localePath + .substring(0, underscore - 1); + } + } else { + // + // Ready for the last round: try without any locale + // modifiers. + // + localePath = "/"; + } + } else { + // + // We've tried all combinations, so we've run out of them + // and bail out. + // + break; + } + } + // + // Okay, go for the next round, we've updated (or rather trimmed) + // the localeIdent, so let us try this. + // + } + // + // If we reach this code point then no suitable activity could be found + // and activated. In case the caller specified a fallback URI we will + // try to open that. As this will activate a suitable browser and this + // is an asynchronous activity we won't get back any negative results, + // such as 404's. Here we will only see such problems that prevented the + // start of a suitable browsing activity. + // + if ( fallbackUri != null ) { + intent = new Intent(Intent.ACTION_VIEW, Uri.parse(fallbackUri)); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + context.startActivity(intent); + } + // + // We could not activate any manual and there was no fallback URI to + // open, so we finally bail out unsuccessful with an exception. + // + throw new ActivityNotFoundException(); + } +} diff --git a/main/thirdparty/org/openintents/intents/FileManagerIntents.java b/main/thirdparty/org/openintents/intents/FileManagerIntents.java new file mode 100644 index 0000000..8ff10c8 --- /dev/null +++ b/main/thirdparty/org/openintents/intents/FileManagerIntents.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008 OpenIntents.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openintents.intents; + +/** + * Provides OpenIntents actions, extras, and categories used by providers. + *

These specifiers extend the standard Android specifiers.

+ */ +public final class FileManagerIntents { + + /** + * Activity Action: Pick a file through the file manager, or let user + * specify a custom file name. + * Data is the current file name or file name suggestion. + * Returns a new file name as file URI in data. + * + *

Constant Value: "org.openintents.action.PICK_FILE"

+ */ + public static final String ACTION_PICK_FILE = "org.openintents.action.PICK_FILE"; + + /** + * Activity Action: Pick a directory through the file manager, or let user + * specify a custom file name. + * Data is the current directory name or directory name suggestion. + * Returns a new directory name as file URI in data. + * + *

Constant Value: "org.openintents.action.PICK_DIRECTORY"

+ */ + public static final String ACTION_PICK_DIRECTORY = "org.openintents.action.PICK_DIRECTORY"; + + /** + * Activity Action: Move, copy or delete after select entries. + * Data is the current directory name or directory name suggestion. + * + *

Constant Value: "org.openintents.action.MULTI_SELECT"

+ */ + public static final String ACTION_MULTI_SELECT = "org.openintents.action.MULTI_SELECT"; + + public static final String ACTION_SEARCH_STARTED = "org.openintents.action.SEARCH_STARTED"; + + public static final String ACTION_SEARCH_FINISHED = "org.openintens.action.SEARCH_FINISHED"; + + /** + * The title to display. + * + *

This is shown in the title bar of the file manager.

+ * + *

Constant Value: "org.openintents.extra.TITLE"

+ */ + public static final String EXTRA_TITLE = "org.openintents.extra.TITLE"; + + /** + * The text on the button to display. + * + *

Depending on the use, it makes sense to set this to "Open" or "Save".

+ * + *

Constant Value: "org.openintents.extra.BUTTON_TEXT"

+ */ + public static final String EXTRA_BUTTON_TEXT = "org.openintents.extra.BUTTON_TEXT"; + + /** + * Flag indicating to show only writeable files and folders. + * + *

Constant Value: "org.openintents.extra.WRITEABLE_ONLY"

+ */ + public static final String EXTRA_WRITEABLE_ONLY = "org.openintents.extra.WRITEABLE_ONLY"; + + /** + * The path to prioritize in search. Usually denotes the path the user was on when the search was initiated. + * + *

Constant Value: "org.openintents.extra.SEARCH_INIT_PATH"

+ */ + public static final String EXTRA_SEARCH_INIT_PATH = "org.openintents.extra.SEARCH_INIT_PATH"; + + /** + * The search query as sent to SearchService. + * + *

Constant Value: "org.openintents.extra.SEARCH_QUERY"

+ */ + public static final String EXTRA_SEARCH_QUERY = "org.openintents.extra.SEARCH_QUERY"; + + /** + *

Constant Value: "org.openintents.extra.DIR_PATH"

+ */ + public static final String EXTRA_DIR_PATH = "org.openintents.extra.DIR_PATH"; + + /** + * Extension by which to filter. + * + *

Constant Value: "org.openintents.extra.FILTER_FILETYPE"

+ */ + public static final String EXTRA_FILTER_FILETYPE = "org.openintents.extra.FILTER_FILETYPE"; + + /** + * Mimetype by which to filter. + * + *

Constant Value: "org.openintents.extra.FILTER_MIMETYPE"

+ */ + public static final String EXTRA_FILTER_MIMETYPE = "org.openintents.extra.FILTER_MIMETYPE"; + + /** + * Only show directories. + * + *

Constant Value: "org.openintents.extra.DIRECTORIES_ONLY"

+ */ + public static final String EXTRA_DIRECTORIES_ONLY = "org.openintents.extra.DIRECTORIES_ONLY"; + + public static final String EXTRA_DIALOG_FILE_HOLDER = "org.openintents.extra.DIALOG_FILE"; + + public static final String EXTRA_IS_GET_CONTENT_INITIATED = "org.openintents.extra.ENABLE_ACTIONS"; + + public static final String EXTRA_FILENAME = "org.openintents.extra.FILENAME"; +} -- cgit v1.1 From 1b671477deb79543e4606feb51c45e1cbe912ff6 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 22 Apr 2013 08:57:16 +0200 Subject: code cleanup: remove JDT warnings --- main/src/cgeo/geocaching/cgeocaches.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'main') diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index e5176d5..7888b14 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -1444,7 +1444,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity * @param view * unused here but needed since this method is referenced from XML layout */ - public void selectList(@SuppressWarnings("unused") View view) { + public void selectList(View view) { if (type != CacheListType.OFFLINE) { return; } @@ -1543,7 +1543,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity * @param view * unused here but needed since this method is referenced from XML layout */ - public void goMap(@SuppressWarnings("unused") View view) { + public void goMap(View view) { if (search == null || CollectionUtils.isEmpty(cacheList)) { showToast(res.getString(R.string.warn_no_cache_coord)); -- cgit v1.1 From 6b421b17d247214c5fc9df494f9d2d5006cd7743 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Mon, 22 Apr 2013 09:10:54 +0200 Subject: fix Ant build * add secondary source path --- main/ant.properties | 1 + 1 file changed, 1 insertion(+) (limited to 'main') diff --git a/main/ant.properties b/main/ant.properties index c26774c..8216a77 100644 --- a/main/ant.properties +++ b/main/ant.properties @@ -17,3 +17,4 @@ proguard.config=proguard.cfg proguard.jar=support/proguard.jar +source.dir=src;thirdparty \ No newline at end of file -- cgit v1.1 From 92a7d243bba95870ff7b702fe46447817142f1c7 Mon Sep 17 00:00:00 2001 From: donEgro Date: Mon, 22 Apr 2013 19:00:03 +0200 Subject: Fixed Issue #708 - Refresh caches + no internet = normal progress. Checking refresh in CacheDetailActivity, CachePopup and cgeocaches. --- main/src/cgeo/geocaching/CacheDetailActivity.java | 5 +++++ main/src/cgeo/geocaching/CachePopup.java | 6 ++++++ 2 files changed, 11 insertions(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 43ce65f..bbc59e6 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -1354,6 +1354,11 @@ public class CacheDetailActivity extends AbstractViewPagerActivity Date: Fri, 26 Apr 2013 10:06:52 +0200 Subject: #2537 reduce memory usage of downloaded images --- main/src/cgeo/geocaching/network/HtmlImage.java | 1 + 1 file changed, 1 insertion(+) (limited to 'main') diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java index b08d36d..45cdbb5 100644 --- a/main/src/cgeo/geocaching/network/HtmlImage.java +++ b/main/src/cgeo/geocaching/network/HtmlImage.java @@ -65,6 +65,7 @@ public class HtmlImage implements Html.ImageGetter { bfOptions = new BitmapFactory.Options(); bfOptions.inTempStorage = new byte[16 * 1024]; + bfOptions.inPreferredConfig = Bitmap.Config.RGB_565; Point displaySize = Compatibility.getDisplaySize(); this.maxWidth = displaySize.x - 25; -- cgit v1.1 From 34c14bcdef79565d19b2fb7e176914294d8fa061 Mon Sep 17 00:00:00 2001 From: nebursc Date: Sat, 27 Apr 2013 13:17:39 +0300 Subject: One string translated and one fixed I added one string that was not translated until now. --- main/res/values-es/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'main') diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index 0fe60b5..0f7433d 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -251,6 +251,7 @@ ¿Quieres borrar todos los escondites guardados en el dispositivo? Descartar guardados Borrando escondites + Descartar todos y borrar lista Actualizar seleccionados Actualizar todos Mover seleccionados @@ -263,7 +264,7 @@ Continuar Filtrar Filtrar por - tamaó + tamaño tipo con rastreables limpiar filtros -- cgit v1.1 From a0f722b4ec8e4994e39c2723696d9a92f238b5de Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 28 Apr 2013 14:44:11 +0200 Subject: refactoring: rename cgeo activity to MainActivity * this avoids compiler errors when using fully qualified class names as they all start with cgeo.subpackage --- main/AndroidManifest.xml | 2 +- main/src/cgeo/geocaching/MainActivity.java | 796 +++++++++++++++++++++ main/src/cgeo/geocaching/SearchActivity.java | 2 +- .../cgeo/geocaching/activity/ActivityMixin.java | 4 +- main/src/cgeo/geocaching/apps/AbstractApp.java | 4 +- main/src/cgeo/geocaching/cgeo.java | 796 --------------------- main/src/cgeo/geocaching/cgeoapplication.java | 4 +- 7 files changed, 804 insertions(+), 804 deletions(-) create mode 100644 main/src/cgeo/geocaching/MainActivity.java delete mode 100644 main/src/cgeo/geocaching/cgeo.java (limited to 'main') diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index e69af11..8745ae8 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -31,7 +31,7 @@ android:name="com.google.android.backup.api_key" android:value="AEdPqrEAAAAIsvD_aUSDMwWOf9NkwwxZ4kJJI_AG2EaxjSu2jw" /> addresses = null; + private boolean addressObtaining = false; + private boolean initialized = false; + + final private UpdateLocation locationUpdater = new UpdateLocation(); + + private Handler updateUserInfoHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + + TextView userInfoView = (TextView) findViewById(R.id.user_info); + + StringBuilder userInfo = new StringBuilder("geocaching.com").append(Formatter.SEPARATOR); + if (Login.isActualLoginStatus()) { + userInfo.append(Login.getActualUserName()); + if (Login.getActualCachesFound() >= 0) { + userInfo.append(" (").append(String.valueOf(Login.getActualCachesFound())).append(')'); + } + userInfo.append(Formatter.SEPARATOR); + } + userInfo.append(Login.getActualStatus()); + + userInfoView.setText(userInfo.toString()); + } + }; + + private Handler obtainAddressHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + try { + if (CollectionUtils.isNotEmpty(addresses)) { + final Address address = addresses.get(0); + final StringBuilder addText = new StringBuilder(); + + if (address.getCountryName() != null) { + addText.append(address.getCountryName()); + } + if (address.getLocality() != null) { + if (addText.length() > 0) { + addText.append(", "); + } + addText.append(address.getLocality()); + } else if (address.getAdminArea() != null) { + if (addText.length() > 0) { + addText.append(", "); + } + addText.append(address.getAdminArea()); + } + + addCoords = app.currentGeo().getCoords(); + + TextView navLocation = (TextView) findViewById(R.id.nav_location); + navLocation.setText(addText.toString()); + } + } catch (Exception e) { + // nothing + } + + addresses = null; + } + }; + + private class SatellitesHandler extends GeoDirHandler { + + private boolean gpsEnabled = false; + private int satellitesFixed = 0; + private int satellitesVisible = 0; + + @Override + public void updateGeoData(final IGeoData data) { + if (data.getGpsEnabled() == gpsEnabled && + data.getSatellitesFixed() == satellitesFixed && + data.getSatellitesVisible() == satellitesVisible) { + return; + } + gpsEnabled = data.getGpsEnabled(); + satellitesFixed = data.getSatellitesFixed(); + satellitesVisible = data.getSatellitesVisible(); + + final TextView navSatellites = (TextView) findViewById(R.id.nav_satellites); + if (gpsEnabled) { + if (satellitesFixed > 0) { + navSatellites.setText(res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible); + } else if (satellitesVisible >= 0) { + navSatellites.setText(res.getString(R.string.loc_sat) + ": 0/" + satellitesVisible); + } + } else { + navSatellites.setText(res.getString(R.string.loc_gps_disabled)); + } + } + + } + + private SatellitesHandler satellitesHandler = new SatellitesHandler(); + + private Handler firstLoginHandler = new Handler() { + + @Override + public void handleMessage(Message msg) { + try { + final StatusCode reason = (StatusCode) msg.obj; + + if (reason != null && reason != StatusCode.NO_ERROR) { //LoginFailed + showToast(res.getString(reason == StatusCode.MAINTENANCE ? reason.getErrorString() : R.string.err_login_failed_toast)); + } + } catch (Exception e) { + Log.w("cgeo.firstLoginHander", e); + } + } + }; + + public MainActivity() { + super("c:geo-main-screen"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { + // If we had been open already, start from the last used activity. + finish(); + return; + } + + setContentView(R.layout.main); + setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // type to search + + version = Version.getVersionCode(this); + Log.i("Starting " + getPackageName() + ' ' + version + " a.k.a " + Version.getVersionName(this)); + + try { + if (!Settings.isHelpShown()) { + final RelativeLayout helper = (RelativeLayout) findViewById(R.id.helper); + if (helper != null) { + helper.setVisibility(View.VISIBLE); + helper.setClickable(true); + helper.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View view) { + ActivityMixin.goManual(MainActivity.this, "c:geo-intro"); + view.setVisibility(View.GONE); + } + }); + Settings.setHelpShown(); + } + } + } catch (Exception e) { + // nothing + } + + init(); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + init(); + } + + @Override + public void onResume() { + super.onResume(); + locationUpdater.startGeo(); + satellitesHandler.startGeo(); + updateUserInfoHandler.sendEmptyMessage(-1); + init(); + } + + @Override + public void onDestroy() { + initialized = false; + app.showLoginToast = true; + + super.onDestroy(); + } + + @Override + public void onStop() { + initialized = false; + super.onStop(); + } + + @Override + public void onPause() { + initialized = false; + locationUpdater.stopGeo(); + satellitesHandler.stopGeo(); + super.onPause(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_options, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + MenuItem item = menu.findItem(R.id.menu_scan); + if (item != null) { + item.setEnabled(isIntentAvailable(SCAN_INTENT)); + } + return true; + } + + public static boolean isIntentAvailable(String intent) { + final PackageManager packageManager = cgeoapplication.getInstance().getPackageManager(); + final List list = packageManager.queryIntentActivities( + new Intent(intent), PackageManager.MATCH_DEFAULT_ONLY); + + return CollectionUtils.isNotEmpty(list); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + final int id = item.getItemId(); + switch (id) { + case R.id.menu_about: + showAbout(null); + return true; + case R.id.menu_helpers: + startActivity(new Intent(this, UsefulAppsActivity.class)); + return true; + case R.id.menu_settings: + startActivity(new Intent(this, SettingsActivity.class)); + return true; + case R.id.menu_history: + cgeocaches.startActivityHistory(this); + return true; + case R.id.menu_scan: + startScannerApplication(); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + private void startScannerApplication() { + Intent intent = new Intent(SCAN_INTENT); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); // when resuming our app, cancel this activity + intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); + startActivityForResult(intent, SCAN_REQUEST_CODE); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + if (requestCode == SCAN_REQUEST_CODE) { + // Only handle positive results, don't do anything if cancelled. + if (resultCode == RESULT_OK) { + String scan = intent.getStringExtra("SCAN_RESULT"); + if (StringUtils.isBlank(scan)) { + return; + } + + SearchActivity.startActivityScan(scan, this); + } + } else if (requestCode == SEARCH_REQUEST_CODE) { + // SearchActivity activity returned without making a search + if (resultCode == RESULT_CANCELED) { + String query = intent.getStringExtra(SearchManager.QUERY); + if (query == null) { + query = ""; + } + new AlertDialog.Builder(this) + .setMessage(res.getString(R.string.unknown_scan) + "\n\n" + query) + .setPositiveButton(getString(android.R.string.ok), null) + .create() + .show(); + } + } + } + + private void setFilterTitle() { + if (filterTitle == null) { + filterTitle = (TextView) findViewById(R.id.filter_button_title); + } + filterTitle.setText(Settings.getCacheType().getL10n()); + } + + private void init() { + if (initialized) { + return; + } + + initialized = true; + + Settings.setLanguage(Settings.isUseEnglish()); + Settings.getLogin(); + + if (app.firstRun) { + (new FirstLoginThread()).start(); + } + + final View findOnMap = findViewById(R.id.map); + findOnMap.setClickable(true); + findOnMap.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + cgeoFindOnMap(v); + } + }); + + final View findByOffline = findViewById(R.id.search_offline); + findByOffline.setClickable(true); + findByOffline.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + cgeoFindByOffline(v); + } + }); + findByOffline.setOnLongClickListener(new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + new StoredList.UserInterface(MainActivity.this).promptForListSelection(R.string.list_title, new RunnableWithArgument() { + + @Override + public void run(Integer selectedListId) { + Settings.saveLastList(selectedListId); + cgeocaches.startActivityOffline(MainActivity.this); + } + }); + return true; + } + }); + findByOffline.setLongClickable(true); + + final View advanced = findViewById(R.id.advanced_button); + advanced.setClickable(true); + advanced.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + cgeoSearch(v); + } + }); + + final View any = findViewById(R.id.any_button); + any.setClickable(true); + any.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + cgeoPoint(v); + } + }); + + final View filter = findViewById(R.id.filter_button); + filter.setClickable(true); + filter.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + selectGlobalTypeFilter(); + } + }); + filter.setOnLongClickListener(new View.OnLongClickListener() { + + @Override + public boolean onLongClick(View v) { + selectGlobalTypeFilter(); + return true; + } + }); + + updateCacheCounter(); + + setFilterTitle(); + checkRestore(); + (new CleanDatabaseThread()).start(); + } + + protected void selectGlobalTypeFilter() { + final List cacheTypes = new ArrayList(); + + //first add the most used types + cacheTypes.add(CacheType.ALL); + cacheTypes.add(CacheType.TRADITIONAL); + cacheTypes.add(CacheType.MULTI); + cacheTypes.add(CacheType.MYSTERY); + + // then add all other cache types sorted alphabetically + List sorted = new ArrayList(); + sorted.addAll(Arrays.asList(CacheType.values())); + sorted.removeAll(cacheTypes); + + Collections.sort(sorted, new Comparator() { + + @Override + public int compare(CacheType left, CacheType right) { + return left.getL10n().compareToIgnoreCase(right.getL10n()); + } + }); + + cacheTypes.addAll(sorted); + + int checkedItem = cacheTypes.indexOf(Settings.getCacheType()); + if (checkedItem < 0) { + checkedItem = 0; + } + + String[] items = new String[cacheTypes.size()]; + for (int i = 0; i < cacheTypes.size(); i++) { + items[i] = cacheTypes.get(i).getL10n(); + } + + Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.menu_filter); + builder.setSingleChoiceItems(items, checkedItem, new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int position) { + CacheType cacheType = cacheTypes.get(position); + Settings.setCacheType(cacheType); + setFilterTitle(); + dialog.dismiss(); + } + + }); + builder.create().show(); + } + + void updateCacheCounter() { + (new CountBubbleUpdateThread()).start(); + } + + private void checkRestore() { + if (!cgData.isNewlyCreatedDatebase() || null == cgData.getRestoreFile()) { + return; + } + new AlertDialog.Builder(this) + .setTitle(res.getString(R.string.init_backup_restore)) + .setMessage(res.getString(R.string.init_restore_confirm)) + .setCancelable(false) + .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + cgData.resetNewlyCreatedDatabase(); + app.restoreDatabase(MainActivity.this); + } + }) + .setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int id) { + dialog.cancel(); + cgData.resetNewlyCreatedDatabase(); + } + }) + .create() + .show(); + } + + private class UpdateLocation extends GeoDirHandler { + + @Override + public void updateGeoData(final IGeoData geo) { + final View nearestView = findViewById(R.id.nearest); + final TextView navType = (TextView) findViewById(R.id.nav_type); + final TextView navAccuracy = (TextView) findViewById(R.id.nav_accuracy); + final TextView navLocation = (TextView) findViewById(R.id.nav_location); + try { + if (geo.getCoords() != null) { + if (!nearestView.isClickable()) { + nearestView.setFocusable(true); + nearestView.setClickable(true); + nearestView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + cgeoFindNearest(v); + } + }); + nearestView.setBackgroundResource(R.drawable.main_nearby); + } + + navType.setText(res.getString(geo.getLocationProvider().resourceId)); + + if (geo.getAccuracy() >= 0) { + int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000; + navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()) + Formatter.SEPARATOR + Units.getSpeed(speed)); + } else { + navAccuracy.setText(null); + } + + if (Settings.isShowAddress()) { + if (addCoords == null) { + navLocation.setText(res.getString(R.string.loc_no_addr)); + } + if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5 && !addressObtaining)) { + (new ObtainAddressThread()).start(); + } + } else { + if (geo.getAltitude() != 0.0) { + final String humanAlt = Units.getDistanceFromKilometers((float) geo.getAltitude() / 1000); + navLocation.setText(geo.getCoords() + " | " + humanAlt); + } else { + navLocation.setText(geo.getCoords().toString()); + } + } + } else { + if (nearestView.isClickable()) { + nearestView.setFocusable(false); + nearestView.setClickable(false); + nearestView.setOnClickListener(null); + nearestView.setBackgroundResource(R.drawable.main_nearby_disabled); + } + navType.setText(null); + navAccuracy.setText(null); + navLocation.setText(res.getString(R.string.loc_trying)); + } + } catch (Exception e) { + Log.w("Failed to update location."); + } + } + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoFindOnMap(View v) { + findViewById(R.id.map).setPressed(true); + CGeoMap.startActivityLiveMap(this); + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoFindNearest(View v) { + if (app.currentGeo().getCoords() == null) { + return; + } + + findViewById(R.id.nearest).setPressed(true); + cgeocaches.startActivityNearest(this, app.currentGeo().getCoords()); + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoFindByOffline(View v) { + findViewById(R.id.search_offline).setPressed(true); + cgeocaches.startActivityOffline(this); + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoSearch(View v) { + findViewById(R.id.advanced_button).setPressed(true); + startActivity(new Intent(this, SearchActivity.class)); + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoPoint(View v) { + findViewById(R.id.any_button).setPressed(true); + startActivity(new Intent(this, NavigateAnyPointActivity.class)); + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoFilter(View v) { + findViewById(R.id.filter_button).setPressed(true); + findViewById(R.id.filter_button).performClick(); + } + + /** + * @param v + * unused here but needed since this method is referenced from XML layout + */ + public void cgeoNavSettings(View v) { + startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); + } + + private class CountBubbleUpdateThread extends Thread { + private Handler countBubbleHandler = new Handler() { + private TextView countBubble = null; + + @Override + public void handleMessage(Message msg) { + try { + if (countBubble == null) { + countBubble = (TextView) findViewById(R.id.offline_count); + } + + if (countBubbleCnt == 0) { + countBubble.setVisibility(View.GONE); + } else { + countBubble.setText(Integer.toString(countBubbleCnt)); + countBubble.bringToFront(); + countBubble.setVisibility(View.VISIBLE); + } + } catch (Exception e) { + Log.w("cgeo.countBubbleHander", e); + } + } + }; + + @Override + public void run() { + if (app == null) { + return; + } + + int checks = 0; + while (!cgData.isInitialized()) { + try { + wait(500); + checks++; + } catch (Exception e) { + // nothing; + } + + if (checks > 10) { + return; + } + } + + countBubbleCnt = cgData.getAllCachesCount(); + + countBubbleHandler.sendEmptyMessage(0); + } + } + + private class CleanDatabaseThread extends Thread { + + @Override + public void run() { + if (app == null) { + return; + } + if (cleanupRunning) { + return; + } + + boolean more = false; + if (version != Settings.getVersion()) { + Log.i("Initializing hard cleanup - version changed from " + Settings.getVersion() + " to " + version + "."); + + more = true; + } + + cleanupRunning = true; + cgData.clean(more); + cleanupRunning = false; + + if (version > 0) { + Settings.setVersion(version); + } + } + } + + private class FirstLoginThread extends Thread { + + @Override + public void run() { + if (app == null) { + return; + } + + // login + final StatusCode status = Login.login(); + + if (status == StatusCode.NO_ERROR) { + app.firstRun = false; + Login.detectGcCustomDate(); + updateUserInfoHandler.sendEmptyMessage(-1); + } + + if (app.showLoginToast) { + firstLoginHandler.sendMessage(firstLoginHandler.obtainMessage(0, status)); + app.showLoginToast = false; + + // invoke settings activity to insert login details + if (status == StatusCode.NO_LOGIN_INFO_STORED) { + SettingsActivity.startActivity(MainActivity.this); + } + } + } + } + + private class ObtainAddressThread extends Thread { + + public ObtainAddressThread() { + setPriority(Thread.MIN_PRIORITY); + } + + @Override + public void run() { + if (addressObtaining) { + return; + } + addressObtaining = true; + + try { + final Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault()); + final Geopoint coords = app.currentGeo().getCoords(); + addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1); + } catch (Exception e) { + Log.i("Failed to obtain address"); + } + + obtainAddressHandler.sendEmptyMessage(0); + + addressObtaining = false; + } + } + + /** + * @param view + * unused here but needed since this method is referenced from XML layout + */ + public void showAbout(View view) { + startActivity(new Intent(this, AboutActivity.class)); + } + + /** + * @param view + * unused here but needed since this method is referenced from XML layout + */ + public void goSearch(View view) { + onSearchRequested(); + } + +} diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index 6fdff5a..ecbd2b2 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -432,6 +432,6 @@ public class SearchActivity extends AbstractActivity { searchIntent.setAction(Intent.ACTION_SEARCH). putExtra(SearchManager.QUERY, scan). putExtra(Intents.EXTRA_KEYWORD_SEARCH, false); - fromActivity.startActivityForResult(searchIntent, cgeo.SEARCH_REQUEST_CODE); + fromActivity.startActivityForResult(searchIntent, MainActivity.SEARCH_REQUEST_CODE); } } diff --git a/main/src/cgeo/geocaching/activity/ActivityMixin.java b/main/src/cgeo/geocaching/activity/ActivityMixin.java index c97cb9a..8432243 100644 --- a/main/src/cgeo/geocaching/activity/ActivityMixin.java +++ b/main/src/cgeo/geocaching/activity/ActivityMixin.java @@ -2,7 +2,7 @@ package cgeo.geocaching.activity; import cgeo.geocaching.R; import cgeo.geocaching.Settings; -import cgeo.geocaching.cgeo; +import cgeo.geocaching.MainActivity; import cgeo.geocaching.compatibility.Compatibility; import org.apache.commons.lang3.StringUtils; @@ -26,7 +26,7 @@ import gnu.android.app.appmanualclient.AppManualReaderClient; public final class ActivityMixin { public final static void goHome(final Activity fromActivity) { - final Intent intent = new Intent(fromActivity, cgeo.class); + final Intent intent = new Intent(fromActivity, MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); fromActivity.startActivity(intent); diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java index c95e8b4..ef56f87 100644 --- a/main/src/cgeo/geocaching/apps/AbstractApp.java +++ b/main/src/cgeo/geocaching/apps/AbstractApp.java @@ -1,7 +1,7 @@ package cgeo.geocaching.apps; import cgeo.geocaching.Geocache; -import cgeo.geocaching.cgeo; +import cgeo.geocaching.MainActivity; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.utils.ProcessUtils; @@ -29,7 +29,7 @@ public abstract class AbstractApp implements App { if (ProcessUtils.isInstalled(packageName)) { return true; } - return cgeo.isIntentAvailable(intent); + return MainActivity.isIntentAvailable(intent); } protected Intent getLaunchIntent() { diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java deleted file mode 100644 index 0140c3a..0000000 --- a/main/src/cgeo/geocaching/cgeo.java +++ /dev/null @@ -1,796 +0,0 @@ -package cgeo.geocaching; - -import cgeo.geocaching.activity.AbstractActivity; -import cgeo.geocaching.activity.ActivityMixin; -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.Units; -import cgeo.geocaching.maps.CGeoMap; -import cgeo.geocaching.ui.Formatter; -import cgeo.geocaching.utils.GeoDirHandler; -import cgeo.geocaching.utils.Log; -import cgeo.geocaching.utils.RunnableWithArgument; -import cgeo.geocaching.utils.Version; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; - -import android.app.AlertDialog; -import android.app.AlertDialog.Builder; -import android.app.SearchManager; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Configuration; -import android.location.Address; -import android.location.Geocoder; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Locale; - -public class cgeo extends AbstractActivity { - - private static final String SCAN_INTENT = "com.google.zxing.client.android.SCAN"; - private static final int SCAN_REQUEST_CODE = 1; - public static final int SEARCH_REQUEST_CODE = 2; - - private int version = 0; - private TextView filterTitle = null; - private boolean cleanupRunning = false; - private int countBubbleCnt = 0; - private Geopoint addCoords = null; - private List
addresses = null; - private boolean addressObtaining = false; - private boolean initialized = false; - - final private UpdateLocation locationUpdater = new UpdateLocation(); - - private Handler updateUserInfoHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - - TextView userInfoView = (TextView) findViewById(R.id.user_info); - - StringBuilder userInfo = new StringBuilder("geocaching.com").append(Formatter.SEPARATOR); - if (Login.isActualLoginStatus()) { - userInfo.append(Login.getActualUserName()); - if (Login.getActualCachesFound() >= 0) { - userInfo.append(" (").append(String.valueOf(Login.getActualCachesFound())).append(')'); - } - userInfo.append(Formatter.SEPARATOR); - } - userInfo.append(Login.getActualStatus()); - - userInfoView.setText(userInfo.toString()); - } - }; - - private Handler obtainAddressHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - try { - if (CollectionUtils.isNotEmpty(addresses)) { - final Address address = addresses.get(0); - final StringBuilder addText = new StringBuilder(); - - if (address.getCountryName() != null) { - addText.append(address.getCountryName()); - } - if (address.getLocality() != null) { - if (addText.length() > 0) { - addText.append(", "); - } - addText.append(address.getLocality()); - } else if (address.getAdminArea() != null) { - if (addText.length() > 0) { - addText.append(", "); - } - addText.append(address.getAdminArea()); - } - - addCoords = app.currentGeo().getCoords(); - - TextView navLocation = (TextView) findViewById(R.id.nav_location); - navLocation.setText(addText.toString()); - } - } catch (Exception e) { - // nothing - } - - addresses = null; - } - }; - - private class SatellitesHandler extends GeoDirHandler { - - private boolean gpsEnabled = false; - private int satellitesFixed = 0; - private int satellitesVisible = 0; - - @Override - public void updateGeoData(final IGeoData data) { - if (data.getGpsEnabled() == gpsEnabled && - data.getSatellitesFixed() == satellitesFixed && - data.getSatellitesVisible() == satellitesVisible) { - return; - } - gpsEnabled = data.getGpsEnabled(); - satellitesFixed = data.getSatellitesFixed(); - satellitesVisible = data.getSatellitesVisible(); - - final TextView navSatellites = (TextView) findViewById(R.id.nav_satellites); - if (gpsEnabled) { - if (satellitesFixed > 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible); - } else if (satellitesVisible >= 0) { - navSatellites.setText(res.getString(R.string.loc_sat) + ": 0/" + satellitesVisible); - } - } else { - navSatellites.setText(res.getString(R.string.loc_gps_disabled)); - } - } - - } - - private SatellitesHandler satellitesHandler = new SatellitesHandler(); - - private Handler firstLoginHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - try { - final StatusCode reason = (StatusCode) msg.obj; - - if (reason != null && reason != StatusCode.NO_ERROR) { //LoginFailed - showToast(res.getString(reason == StatusCode.MAINTENANCE ? reason.getErrorString() : R.string.err_login_failed_toast)); - } - } catch (Exception e) { - Log.w("cgeo.firstLoginHander", e); - } - } - }; - - public cgeo() { - super("c:geo-main-screen"); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { - // If we had been open already, start from the last used activity. - finish(); - return; - } - - setContentView(R.layout.main); - setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // type to search - - version = Version.getVersionCode(this); - Log.i("Starting " + getPackageName() + ' ' + version + " a.k.a " + Version.getVersionName(this)); - - try { - if (!Settings.isHelpShown()) { - final RelativeLayout helper = (RelativeLayout) findViewById(R.id.helper); - if (helper != null) { - helper.setVisibility(View.VISIBLE); - helper.setClickable(true); - helper.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View view) { - ActivityMixin.goManual(cgeo.this, "c:geo-intro"); - view.setVisibility(View.GONE); - } - }); - Settings.setHelpShown(); - } - } - } catch (Exception e) { - // nothing - } - - init(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - init(); - } - - @Override - public void onResume() { - super.onResume(); - locationUpdater.startGeo(); - satellitesHandler.startGeo(); - updateUserInfoHandler.sendEmptyMessage(-1); - init(); - } - - @Override - public void onDestroy() { - initialized = false; - app.showLoginToast = true; - - super.onDestroy(); - } - - @Override - public void onStop() { - initialized = false; - super.onStop(); - } - - @Override - public void onPause() { - initialized = false; - locationUpdater.stopGeo(); - satellitesHandler.stopGeo(); - super.onPause(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_options, menu); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - MenuItem item = menu.findItem(R.id.menu_scan); - if (item != null) { - item.setEnabled(isIntentAvailable(SCAN_INTENT)); - } - return true; - } - - public static boolean isIntentAvailable(String intent) { - final PackageManager packageManager = cgeoapplication.getInstance().getPackageManager(); - final List list = packageManager.queryIntentActivities( - new Intent(intent), PackageManager.MATCH_DEFAULT_ONLY); - - return CollectionUtils.isNotEmpty(list); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - final int id = item.getItemId(); - switch (id) { - case R.id.menu_about: - showAbout(null); - return true; - case R.id.menu_helpers: - startActivity(new Intent(this, UsefulAppsActivity.class)); - return true; - case R.id.menu_settings: - startActivity(new Intent(this, SettingsActivity.class)); - return true; - case R.id.menu_history: - cgeocaches.startActivityHistory(this); - return true; - case R.id.menu_scan: - startScannerApplication(); - return true; - default: - return super.onOptionsItemSelected(item); - } - - } - - private void startScannerApplication() { - Intent intent = new Intent(SCAN_INTENT); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); // when resuming our app, cancel this activity - intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); - startActivityForResult(intent, SCAN_REQUEST_CODE); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - if (requestCode == SCAN_REQUEST_CODE) { - // Only handle positive results, don't do anything if cancelled. - if (resultCode == RESULT_OK) { - String scan = intent.getStringExtra("SCAN_RESULT"); - if (StringUtils.isBlank(scan)) { - return; - } - - SearchActivity.startActivityScan(scan, this); - } - } else if (requestCode == SEARCH_REQUEST_CODE) { - // SearchActivity activity returned without making a search - if (resultCode == RESULT_CANCELED) { - String query = intent.getStringExtra(SearchManager.QUERY); - if (query == null) { - query = ""; - } - new AlertDialog.Builder(this) - .setMessage(res.getString(R.string.unknown_scan) + "\n\n" + query) - .setPositiveButton(getString(android.R.string.ok), null) - .create() - .show(); - } - } - } - - private void setFilterTitle() { - if (filterTitle == null) { - filterTitle = (TextView) findViewById(R.id.filter_button_title); - } - filterTitle.setText(Settings.getCacheType().getL10n()); - } - - private void init() { - if (initialized) { - return; - } - - initialized = true; - - Settings.setLanguage(Settings.isUseEnglish()); - Settings.getLogin(); - - if (app.firstRun) { - (new FirstLoginThread()).start(); - } - - final View findOnMap = findViewById(R.id.map); - findOnMap.setClickable(true); - findOnMap.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - cgeoFindOnMap(v); - } - }); - - final View findByOffline = findViewById(R.id.search_offline); - findByOffline.setClickable(true); - findByOffline.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - cgeoFindByOffline(v); - } - }); - findByOffline.setOnLongClickListener(new View.OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - new StoredList.UserInterface(cgeo.this).promptForListSelection(R.string.list_title, new RunnableWithArgument() { - - @Override - public void run(Integer selectedListId) { - Settings.saveLastList(selectedListId); - cgeocaches.startActivityOffline(cgeo.this); - } - }); - return true; - } - }); - findByOffline.setLongClickable(true); - - final View advanced = findViewById(R.id.advanced_button); - advanced.setClickable(true); - advanced.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - cgeoSearch(v); - } - }); - - final View any = findViewById(R.id.any_button); - any.setClickable(true); - any.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - cgeoPoint(v); - } - }); - - final View filter = findViewById(R.id.filter_button); - filter.setClickable(true); - filter.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - selectGlobalTypeFilter(); - } - }); - filter.setOnLongClickListener(new View.OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - selectGlobalTypeFilter(); - return true; - } - }); - - updateCacheCounter(); - - setFilterTitle(); - checkRestore(); - (new CleanDatabaseThread()).start(); - } - - protected void selectGlobalTypeFilter() { - final List cacheTypes = new ArrayList(); - - //first add the most used types - cacheTypes.add(CacheType.ALL); - cacheTypes.add(CacheType.TRADITIONAL); - cacheTypes.add(CacheType.MULTI); - cacheTypes.add(CacheType.MYSTERY); - - // then add all other cache types sorted alphabetically - List sorted = new ArrayList(); - sorted.addAll(Arrays.asList(CacheType.values())); - sorted.removeAll(cacheTypes); - - Collections.sort(sorted, new Comparator() { - - @Override - public int compare(CacheType left, CacheType right) { - return left.getL10n().compareToIgnoreCase(right.getL10n()); - } - }); - - cacheTypes.addAll(sorted); - - int checkedItem = cacheTypes.indexOf(Settings.getCacheType()); - if (checkedItem < 0) { - checkedItem = 0; - } - - String[] items = new String[cacheTypes.size()]; - for (int i = 0; i < cacheTypes.size(); i++) { - items[i] = cacheTypes.get(i).getL10n(); - } - - Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.menu_filter); - builder.setSingleChoiceItems(items, checkedItem, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int position) { - CacheType cacheType = cacheTypes.get(position); - Settings.setCacheType(cacheType); - setFilterTitle(); - dialog.dismiss(); - } - - }); - builder.create().show(); - } - - void updateCacheCounter() { - (new CountBubbleUpdateThread()).start(); - } - - private void checkRestore() { - if (!cgData.isNewlyCreatedDatebase() || null == cgData.getRestoreFile()) { - return; - } - new AlertDialog.Builder(this) - .setTitle(res.getString(R.string.init_backup_restore)) - .setMessage(res.getString(R.string.init_restore_confirm)) - .setCancelable(false) - .setPositiveButton(getString(android.R.string.yes), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - cgData.resetNewlyCreatedDatabase(); - app.restoreDatabase(cgeo.this); - } - }) - .setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - cgData.resetNewlyCreatedDatabase(); - } - }) - .create() - .show(); - } - - private class UpdateLocation extends GeoDirHandler { - - @Override - public void updateGeoData(final IGeoData geo) { - final View nearestView = findViewById(R.id.nearest); - final TextView navType = (TextView) findViewById(R.id.nav_type); - final TextView navAccuracy = (TextView) findViewById(R.id.nav_accuracy); - final TextView navLocation = (TextView) findViewById(R.id.nav_location); - try { - if (geo.getCoords() != null) { - if (!nearestView.isClickable()) { - nearestView.setFocusable(true); - nearestView.setClickable(true); - nearestView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - cgeoFindNearest(v); - } - }); - nearestView.setBackgroundResource(R.drawable.main_nearby); - } - - navType.setText(res.getString(geo.getLocationProvider().resourceId)); - - if (geo.getAccuracy() >= 0) { - int speed = Math.round(geo.getSpeed()) * 60 * 60 / 1000; - navAccuracy.setText("±" + Units.getDistanceFromMeters(geo.getAccuracy()) + Formatter.SEPARATOR + Units.getSpeed(speed)); - } else { - navAccuracy.setText(null); - } - - if (Settings.isShowAddress()) { - if (addCoords == null) { - navLocation.setText(res.getString(R.string.loc_no_addr)); - } - if (addCoords == null || (geo.getCoords().distanceTo(addCoords) > 0.5 && !addressObtaining)) { - (new ObtainAddressThread()).start(); - } - } else { - if (geo.getAltitude() != 0.0) { - final String humanAlt = Units.getDistanceFromKilometers((float) geo.getAltitude() / 1000); - navLocation.setText(geo.getCoords() + " | " + humanAlt); - } else { - navLocation.setText(geo.getCoords().toString()); - } - } - } else { - if (nearestView.isClickable()) { - nearestView.setFocusable(false); - nearestView.setClickable(false); - nearestView.setOnClickListener(null); - nearestView.setBackgroundResource(R.drawable.main_nearby_disabled); - } - navType.setText(null); - navAccuracy.setText(null); - navLocation.setText(res.getString(R.string.loc_trying)); - } - } catch (Exception e) { - Log.w("Failed to update location."); - } - } - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoFindOnMap(View v) { - findViewById(R.id.map).setPressed(true); - CGeoMap.startActivityLiveMap(this); - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoFindNearest(View v) { - if (app.currentGeo().getCoords() == null) { - return; - } - - findViewById(R.id.nearest).setPressed(true); - cgeocaches.startActivityNearest(this, app.currentGeo().getCoords()); - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoFindByOffline(View v) { - findViewById(R.id.search_offline).setPressed(true); - cgeocaches.startActivityOffline(this); - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoSearch(View v) { - findViewById(R.id.advanced_button).setPressed(true); - startActivity(new Intent(this, SearchActivity.class)); - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoPoint(View v) { - findViewById(R.id.any_button).setPressed(true); - startActivity(new Intent(this, NavigateAnyPointActivity.class)); - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoFilter(View v) { - findViewById(R.id.filter_button).setPressed(true); - findViewById(R.id.filter_button).performClick(); - } - - /** - * @param v - * unused here but needed since this method is referenced from XML layout - */ - public void cgeoNavSettings(View v) { - startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)); - } - - private class CountBubbleUpdateThread extends Thread { - private Handler countBubbleHandler = new Handler() { - private TextView countBubble = null; - - @Override - public void handleMessage(Message msg) { - try { - if (countBubble == null) { - countBubble = (TextView) findViewById(R.id.offline_count); - } - - if (countBubbleCnt == 0) { - countBubble.setVisibility(View.GONE); - } else { - countBubble.setText(Integer.toString(countBubbleCnt)); - countBubble.bringToFront(); - countBubble.setVisibility(View.VISIBLE); - } - } catch (Exception e) { - Log.w("cgeo.countBubbleHander", e); - } - } - }; - - @Override - public void run() { - if (app == null) { - return; - } - - int checks = 0; - while (!cgData.isInitialized()) { - try { - wait(500); - checks++; - } catch (Exception e) { - // nothing; - } - - if (checks > 10) { - return; - } - } - - countBubbleCnt = cgData.getAllCachesCount(); - - countBubbleHandler.sendEmptyMessage(0); - } - } - - private class CleanDatabaseThread extends Thread { - - @Override - public void run() { - if (app == null) { - return; - } - if (cleanupRunning) { - return; - } - - boolean more = false; - if (version != Settings.getVersion()) { - Log.i("Initializing hard cleanup - version changed from " + Settings.getVersion() + " to " + version + "."); - - more = true; - } - - cleanupRunning = true; - cgData.clean(more); - cleanupRunning = false; - - if (version > 0) { - Settings.setVersion(version); - } - } - } - - private class FirstLoginThread extends Thread { - - @Override - public void run() { - if (app == null) { - return; - } - - // login - final StatusCode status = Login.login(); - - if (status == StatusCode.NO_ERROR) { - app.firstRun = false; - Login.detectGcCustomDate(); - updateUserInfoHandler.sendEmptyMessage(-1); - } - - if (app.showLoginToast) { - firstLoginHandler.sendMessage(firstLoginHandler.obtainMessage(0, status)); - app.showLoginToast = false; - - // invoke settings activity to insert login details - if (status == StatusCode.NO_LOGIN_INFO_STORED) { - SettingsActivity.startActivity(cgeo.this); - } - } - } - } - - private class ObtainAddressThread extends Thread { - - public ObtainAddressThread() { - setPriority(Thread.MIN_PRIORITY); - } - - @Override - public void run() { - if (addressObtaining) { - return; - } - addressObtaining = true; - - try { - final Geocoder geocoder = new Geocoder(cgeo.this, Locale.getDefault()); - final Geopoint coords = app.currentGeo().getCoords(); - addresses = geocoder.getFromLocation(coords.getLatitude(), coords.getLongitude(), 1); - } catch (Exception e) { - Log.i("Failed to obtain address"); - } - - obtainAddressHandler.sendEmptyMessage(0); - - addressObtaining = false; - } - } - - /** - * @param view - * unused here but needed since this method is referenced from XML layout - */ - public void showAbout(View view) { - startActivity(new Intent(this, AboutActivity.class)); - } - - /** - * @param view - * unused here but needed since this method is referenced from XML layout - */ - public void goSearch(View view) { - onSearchRequested(); - } - -} diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java index a1fd7d1..b8f63ee 100644 --- a/main/src/cgeo/geocaching/cgeoapplication.java +++ b/main/src/cgeo/geocaching/cgeoapplication.java @@ -103,8 +103,8 @@ public class cgeoapplication extends Application { boolean restored = atomic.get(); String message = restored ? res.getString(R.string.init_restore_success) : res.getString(R.string.init_restore_failed); ActivityMixin.helpDialog(fromActivity, res.getString(R.string.init_backup_restore), message); - if (fromActivity instanceof cgeo) { - ((cgeo) fromActivity).updateCacheCounter(); + if (fromActivity instanceof MainActivity) { + ((MainActivity) fromActivity).updateCacheCounter(); } } }; -- cgit v1.1 From 3f4d5dc01e3b6a7395e1f79aab0e807e3f4c9ba2 Mon Sep 17 00:00:00 2001 From: Marco Jacob Date: Thu, 25 Apr 2013 22:50:42 +0200 Subject: fixes #2533 - added image scaling modifications suggested by Bananeweizen next recommended changes and scaling now on leaving ImageSelectActivity fixed wrong spelling --- main/res/layout/visit_image.xml | 7 ++++ main/res/values-de/strings.xml | 10 ++++- main/res/values/strings.xml | 8 ++++ main/res/values/strings_not_translatable.xml | 12 +++++- main/src/cgeo/geocaching/ImageSelectActivity.java | 50 +++++++++++++++++++++++ main/src/cgeo/geocaching/Settings.java | 15 +++++++ main/src/cgeo/geocaching/utils/ImageHelper.java | 38 ++++++++++++++++- 7 files changed, 137 insertions(+), 3 deletions(-) (limited to 'main') diff --git a/main/res/layout/visit_image.xml b/main/res/layout/visit_image.xml index 7997406..c9d4be2 100644 --- a/main/res/layout/visit_image.xml +++ b/main/res/layout/visit_image.xml @@ -98,6 +98,13 @@ android:minLines="5" android:singleLine="false" /> + + Neu Überschrift Beschreibung - + Skalierung + + Keine Skalierung + 512 px + 640 px + 800 px + 1024 px + + Übersetze in %s Übersetze in Englisch diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index d35a982..28a57e0 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -126,6 +126,14 @@ New Caption Description + Scaling + + No scaling + 512 px + 640 px + 800 px + 1024 px + Translate to %s diff --git a/main/res/values/strings_not_translatable.xml b/main/res/values/strings_not_translatable.xml index b392d73..1eddfc6 100644 --- a/main/res/values/strings_not_translatable.xml +++ b/main/res/values/strings_not_translatable.xml @@ -28,6 +28,15 @@ + + + -1 + 512 + 640 + 800 + 1024 + + \n · carnero as the father of c:geo\n @@ -89,7 +98,8 @@ \n Next release\n\n New Features/Functions:\n - · ...\n + · Log images can be scaled before upload to save traffic + · \n \n Bugfixing:\n · Do not apply encryption/decryption when clicking on a link in a log\n diff --git a/main/src/cgeo/geocaching/ImageSelectActivity.java b/main/src/cgeo/geocaching/ImageSelectActivity.java index 347cd86..597a7bd 100644 --- a/main/src/cgeo/geocaching/ImageSelectActivity.java +++ b/main/src/cgeo/geocaching/ImageSelectActivity.java @@ -2,6 +2,7 @@ package cgeo.geocaching; import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.compatibility.Compatibility; +import cgeo.geocaching.utils.ImageHelper; import cgeo.geocaching.utils.Log; import org.apache.commons.lang3.StringUtils; @@ -10,14 +11,18 @@ import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.provider.MediaStore.MediaColumns; import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; +import android.widget.Spinner; import java.io.File; import java.text.SimpleDateFormat; @@ -28,20 +33,24 @@ public class ImageSelectActivity extends AbstractActivity { static final String EXTRAS_CAPTION = "caption"; static final String EXTRAS_DESCRIPTION = "description"; static final String EXTRAS_URI_AS_STRING = "uri"; + static final String EXTRAS_SCALE = "scale"; private static final String SAVED_STATE_IMAGE_CAPTION = "cgeo.geocaching.saved_state_image_caption"; private static final String SAVED_STATE_IMAGE_DESCRIPTION = "cgeo.geocaching.saved_state_image_description"; private static final String SAVED_STATE_IMAGE_URI = "cgeo.geocaching.saved_state_image_uri"; + private static final String SAVED_STATE_IMAGE_SCALE = "cgeo.geocaching.saved_state_image_scale"; private static final int SELECT_NEW_IMAGE = 1; private static final int SELECT_STORED_IMAGE = 2; private EditText captionView; private EditText descriptionView; + private Spinner scaleView; // Data to be saved while reconfiguring private String imageCaption; private String imageDescription; + private int scaleChoiceIndex; private Uri imageUri; public ImageSelectActivity() { @@ -56,6 +65,7 @@ public class ImageSelectActivity extends AbstractActivity { setContentView(R.layout.visit_image); setTitle(res.getString(R.string.log_image)); + scaleChoiceIndex = Settings.getLogImageScale(); imageCaption = ""; imageDescription = ""; imageUri = Uri.EMPTY; @@ -66,6 +76,7 @@ public class ImageSelectActivity extends AbstractActivity { imageCaption = extras.getString(EXTRAS_CAPTION); imageDescription = extras.getString(EXTRAS_DESCRIPTION); imageUri = Uri.parse(extras.getString(EXTRAS_URI_AS_STRING)); + scaleChoiceIndex = extras.getInt(EXTRAS_SCALE, scaleChoiceIndex); } // Restore previous state @@ -73,6 +84,7 @@ public class ImageSelectActivity extends AbstractActivity { imageCaption = savedInstanceState.getString(SAVED_STATE_IMAGE_CAPTION); imageDescription = savedInstanceState.getString(SAVED_STATE_IMAGE_DESCRIPTION); imageUri = Uri.parse(savedInstanceState.getString(SAVED_STATE_IMAGE_URI)); + scaleChoiceIndex = savedInstanceState.getInt(SAVED_STATE_IMAGE_SCALE); } final Button cameraButton = (Button) findViewById(R.id.camera); @@ -103,6 +115,20 @@ public class ImageSelectActivity extends AbstractActivity { descriptionView.setText(imageDescription); } + scaleView = (Spinner) findViewById(R.id.logImageScale); + scaleView.setSelection(scaleChoiceIndex); + scaleView.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView arg0, View arg1, int arg2, long arg3) { + scaleChoiceIndex = scaleView.getSelectedItemPosition(); + Settings.setLogImageScale(scaleChoiceIndex); + } + + @Override + public void onNothingSelected(AdapterView arg0) { + } + }); + final Button saveButton = (Button) findViewById(R.id.save); saveButton.setOnClickListener(new View.OnClickListener() { @@ -131,15 +157,19 @@ public class ImageSelectActivity extends AbstractActivity { outState.putString(SAVED_STATE_IMAGE_CAPTION, imageCaption); outState.putString(SAVED_STATE_IMAGE_DESCRIPTION, imageDescription); outState.putString(SAVED_STATE_IMAGE_URI, imageUri != null ? imageUri.getPath() : StringUtils.EMPTY); + outState.putInt(SAVED_STATE_IMAGE_SCALE, scaleChoiceIndex); } public void saveImageInfo(boolean saveInfo) { if (saveInfo) { + String filename = writeScaledImage(imageUri.getPath()); + imageUri = Uri.parse(filename); Intent intent = new Intent(); syncEditTexts(); intent.putExtra(EXTRAS_CAPTION, imageCaption); intent.putExtra(EXTRAS_DESCRIPTION, imageDescription); intent.putExtra(EXTRAS_URI_AS_STRING, imageUri.toString()); + intent.putExtra(EXTRAS_SCALE, scaleChoiceIndex); setResult(RESULT_OK, intent); } else { @@ -152,6 +182,7 @@ public class ImageSelectActivity extends AbstractActivity { private void syncEditTexts() { imageCaption = captionView.getText().toString(); imageDescription = descriptionView.getText().toString(); + scaleChoiceIndex = scaleView.getSelectedItemPosition(); } private void selectImageFromCamera() { @@ -231,6 +262,25 @@ public class ImageSelectActivity extends AbstractActivity { loadImagePreview(); } + /** + * Scales and writes the scaled image. + * + * @param filePath + * @return + */ + private String writeScaledImage(String filePath) { + Bitmap image = BitmapFactory.decodeFile(filePath); + scaleChoiceIndex = scaleView.getSelectedItemPosition(); + int maxXY = getResources().getIntArray(R.array.log_image_scale_values)[scaleChoiceIndex]; + String uploadFilename = filePath; + if (maxXY > 0) { + BitmapDrawable scaledImage = ImageHelper.scaleBitmapTo(image, maxXY, maxXY); + uploadFilename = getOutputImageFile().getPath(); + ImageHelper.storeBitmap(scaledImage.getBitmap(), Bitmap.CompressFormat.JPEG, 75, uploadFilename); + } + return uploadFilename; + } + private void showFailure() { showToast(getResources().getString(R.string.err_aquire_image_failed)); } diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java index 93bfa9b..b5c8a6e 100644 --- a/main/src/cgeo/geocaching/Settings.java +++ b/main/src/cgeo/geocaching/Settings.java @@ -112,6 +112,7 @@ public final class Settings { private static final String KEY_MAP_DIRECTORY = "mapDirectory"; private static final String KEY_CONNECTOR_OC_ACTIVE = "connectorOCActive"; private static final String KEY_CONNECTOR_OC_USER = "connectorOCUser"; + private static final String KEY_LOG_IMAGE_SCALE = "logImageScale"; private final static int unitsMetric = 1; @@ -1439,4 +1440,18 @@ public final class Settings { public static void setCacheTwitterMessage(final String message) { cacheTwitterMessage = message; } + + public static int getLogImageScale() { + return sharedPrefs.getInt(KEY_LOG_IMAGE_SCALE, -1); + } + + public static void setLogImageScale(final int scale) { + editSharedSettings(new PrefRunnable() { + + @Override + public void edit(Editor edit) { + edit.putInt(KEY_LOG_IMAGE_SCALE, scale); + } + }); + } } diff --git a/main/src/cgeo/geocaching/utils/ImageHelper.java b/main/src/cgeo/geocaching/utils/ImageHelper.java index 98cad64..ec77018 100644 --- a/main/src/cgeo/geocaching/utils/ImageHelper.java +++ b/main/src/cgeo/geocaching/utils/ImageHelper.java @@ -8,6 +8,9 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; +import java.io.BufferedOutputStream; +import java.io.FileOutputStream; + public class ImageHelper { // Do not let this class be instantiated, this is a utility class. @@ -22,11 +25,21 @@ public class ImageHelper { * @return BitmapDrawable The scaled image */ public static BitmapDrawable scaleBitmapToFitDisplay(final Bitmap image) { - final cgeoapplication app = cgeoapplication.getInstance(); Point displaySize = Compatibility.getDisplaySize(); final int maxWidth = displaySize.x - 25; final int maxHeight = displaySize.y - 25; + return scaleBitmapTo(image, maxWidth, maxHeight); + } + /** + * Scales a bitmap to the given bounds if it is larger, otherwise returns the original bitmap. + * + * @param image + * The bitmap to scale + * @return BitmapDrawable The scaled image + */ + public static BitmapDrawable scaleBitmapTo(final Bitmap image, final int maxWidth, final int maxHeight) { + final cgeoapplication app = cgeoapplication.getInstance(); Bitmap result = image; int width = image.getWidth(); int height = image.getHeight(); @@ -43,4 +56,27 @@ public class ImageHelper { return resultDrawable; } + /** + * Store a bitmap to file. + * + * @param bitmap + * The bitmap to store + * @param format + * The image format + * @param quality + * The image quality + * @param pathOfOutputImage + * Path to store to + */ + public static void storeBitmap(final Bitmap bitmap, final Bitmap.CompressFormat format, final int quality, final String pathOfOutputImage) { + try { + FileOutputStream out = new FileOutputStream(pathOfOutputImage); + BufferedOutputStream bos = new BufferedOutputStream(out); + bitmap.compress(format, quality, bos); + bos.flush(); + bos.close(); + } catch (Exception e) { + Log.e("Image", e); + } + } } -- cgit v1.1 From 9f21d5569f1a954660d9e7fadc39565802fcb996 Mon Sep 17 00:00:00 2001 From: nebursc Date: Mon, 29 Apr 2013 19:18:05 +0300 Subject: Localization review according to regular Spanish and GC.com in Spanish (1st part) This is the first part of my review for the Spanish localization. I have done three actions: add missed strings in Spanish from English XML; review existing strings to adapt them to "usual Spanish spoken in Spain" and used at GC.com in Spanish; and fix some little errors (misprints). My main skills to do this: I'm Spanish from Spain and I play geocaching since 2006 (user: Nebur). Of course, I'm also a programmer in several languages :) Modules reviewed in this proposal: - Basics - Caches - Cache sizes - Waypoints - Logs --- main/res/values-es/strings.xml | 88 ++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 30 deletions(-) (limited to 'main') diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index 0f7433d..b3096eb 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -11,6 +11,8 @@ ¿Qué instalar? Sobre c:geo Si quieres aprender cosas sobre c:geo?\nEcha un ojo a nuestro manual. + Latitud + Longitud Compartir enlace a escondite @@ -19,19 +21,20 @@ Todos los escondites Tradicionales Multis - Desconocidos + Desconocidos/Mistery Buzón híbrido - Por pistas - Mega-eventos + Eventos + Mega-Eventos Educativos (Earth) - Limpieza de escondites + Eventos Limpieza(CITO) Webcams Virtuales Wherigo - Perdidos y encontrados + Eventos Perdidos y Encontrados Proyecto APE Groundspeak HQ - Exhibición de escondites GPS + Exhibición de escondites GPS + De tipo desconocido micro @@ -46,36 +49,43 @@ Ubicación final Etapa de multi escondite - Preguntar sin contestar + Preguntar a contestar Zona de aparcamiento Sendero Punto de referencia + Coordenadas originales Encontrado No encontrado Nota Publicado - Activo - Inactivo - Iré + Activado + Desactivado + Asistiré Asistí - Obtenido - Colocado - Guardado en alguna parte + Recogido + Depositado + Recogido de alguna parte + Mover a la colección + Mover al inventario Mantenimiento efectuado Necesita mantenimiento Coordenadas actualizadas Archivado + Desarchivado Necesita ser archivado Descubierto Nota del revisor + Retirar ficha del escondite + Marcado como perdido No hacer nada - Visita - Colocar aquí + Visitado + Dejar aquí Cambiar todo Guardar - Guardando registo… + Enviando registo… + Enviando registro y subiendo imagen… Limpiar Enviar registro Enviar registro y puntuación @@ -84,27 +94,45 @@ Puntuación Sin puntuación 1 estrella -1,5 estrellas + 1,5 estrellas 2 estrellas - 2,5 estrellas + 2,5 estrellas 3 estrellas - 3,5 estrellas + 3,5 estrellas 4 estrellas - 4,5 estrellas + 4,5 estrellas 5 estrellas -poor - fairly poor - below average - not so bad - average - not bad at all - better than average - very good - awesome + malísimo + muy malo + malo + un poco malo + aceptable + algo bueno + bueno + muy bueno + buenísimo Foto de webcam tomada Registro Texto del registro Aviso + Hoy + Ayer + Emoticonos + Imagen + Adjuntar imagen + Editar imagen + Galería + Tomar foto + Título + Descripción + Redimensionamiento + + Sin redimensionar + 512 px + 640 px + 800 px + 1024 px + Aceptar @@ -402,7 +430,7 @@ Atributos Inventario Registro desconectado - Imagen de resgistro + Imagen de registro Foto Nota personal Descripción -- cgit v1.1 From 74fce89a36e8d130851145941459966aed1176c3 Mon Sep 17 00:00:00 2001 From: Bananeweizen Date: Sun, 28 Apr 2013 14:18:29 +0200 Subject: #2684: use view injection library * If you have compile errors after pulling, please consult the issue on github. --- main/.classpath | 5 + main/.factorypath | 3 + main/.settings/org.eclipse.jdt.apt.core.prefs | 4 + main/.settings/org.eclipse.jdt.core.prefs | 735 +++++++++++---------- main/AndroidManifest.xml | 46 +- main/libs/butterknife-1.3.2.jar | Bin 0 -> 12597 bytes main/proguard.cfg | 4 + main/src/cgeo/geocaching/AboutActivity.java | 17 +- .../src/cgeo/geocaching/AbstractPopupActivity.java | 1 - main/src/cgeo/geocaching/AddressListActivity.java | 6 +- main/src/cgeo/geocaching/CacheDetailActivity.java | 7 +- main/src/cgeo/geocaching/EditWaypointActivity.java | 84 ++- main/src/cgeo/geocaching/GpxFileListActivity.java | 5 - main/src/cgeo/geocaching/ImageSelectActivity.java | 6 +- main/src/cgeo/geocaching/LogTrackableActivity.java | 6 +- main/src/cgeo/geocaching/MainActivity.java | 58 +- .../cgeo/geocaching/NavigateAnyPointActivity.java | 6 +- main/src/cgeo/geocaching/SearchActivity.java | 1 - .../src/cgeo/geocaching/SelectMapfileActivity.java | 5 - main/src/cgeo/geocaching/SettingsActivity.java | 8 +- main/src/cgeo/geocaching/StaticMapsActivity.java | 6 +- main/src/cgeo/geocaching/TrackableActivity.java | 6 +- main/src/cgeo/geocaching/UsefulAppsActivity.java | 30 +- main/src/cgeo/geocaching/VisitCacheActivity.java | 6 +- .../cgeo/geocaching/activity/AbstractActivity.java | 50 +- .../geocaching/activity/AbstractListActivity.java | 21 +- .../cgeo/geocaching/activity/ActivityMixin.java | 4 +- main/src/cgeo/geocaching/cgeonavigate.java | 6 +- .../geocaching/files/AbstractFileListActivity.java | 6 - .../cgeo/geocaching/files/SimpleDirChooser.java | 11 +- .../twitter/TwitterAuthorizationActivity.java | 12 +- 31 files changed, 568 insertions(+), 597 deletions(-) create mode 100644 main/.factorypath create mode 100644 main/.settings/org.eclipse.jdt.apt.core.prefs create mode 100644 main/libs/butterknife-1.3.2.jar (limited to 'main') diff --git a/main/.classpath b/main/.classpath index 2905a42..d7bcabc 100644 --- a/main/.classpath +++ b/main/.classpath @@ -11,6 +11,11 @@ + + + + + diff --git a/main/.factorypath b/main/.factorypath new file mode 100644 index 0000000..d54f9b4 --- /dev/null +++ b/main/.factorypath @@ -0,0 +1,3 @@ + + + diff --git a/main/.settings/org.eclipse.jdt.apt.core.prefs b/main/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..813e822 --- /dev/null +++ b/main/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=true +org.eclipse.jdt.apt.genSrcDir=annotation_gen +org.eclipse.jdt.apt.reconcileEnabled=true diff --git a/main/.settings/org.eclipse.jdt.core.prefs b/main/.settings/org.eclipse.jdt.core.prefs index 3c08e45..41c73f0 100644 --- a/main/.settings/org.eclipse.jdt.core.prefs +++ b/main/.settings/org.eclipse.jdt.core.prefs @@ -1,367 +1,368 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.doc.comment.support=enabled -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning -org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning -org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled -org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning -org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore -org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled -org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public -org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag -org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore -org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled -org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled -org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning -org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning -org.eclipse.jdt.core.compiler.problem.unusedParameter=warning -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.6 -org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0 -org.eclipse.jdt.core.formatter.alignment_for_assignment=0 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=0 -org.eclipse.jdt.core.formatter.alignment_for_compact_if=0 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=0 -org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -org.eclipse.jdt.core.formatter.comment.format_header=true -org.eclipse.jdt.core.formatter.comment.format_html=true -org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=false -org.eclipse.jdt.core.formatter.comment.format_source_code=true -org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true -org.eclipse.jdt.core.formatter.comment.indent_root_tags=true -org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert -org.eclipse.jdt.core.formatter.comment.line_length=120 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_empty_lines=false -org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true -org.eclipse.jdt.core.formatter.indentation.size=4 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert -org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.join_lines_in_comments=false -org.eclipse.jdt.core.formatter.join_wrapped_lines=false -org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false -org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false -org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -org.eclipse.jdt.core.formatter.lineSplit=120 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=no_tag +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.processAnnotations=enabled +org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=0 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=0 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=0 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=0 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=true +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=false +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=false +org.eclipse.jdt.core.formatter.join_wrapped_lines=false +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/main/AndroidManifest.xml b/main/AndroidManifest.xml index 8745ae8..3fb5ff1 100644 --- a/main/AndroidManifest.xml +++ b/main/AndroidManifest.xml @@ -43,7 +43,7 @@ @@ -63,49 +63,49 @@ @@ -124,27 +124,27 @@ + android:label="@string/map_map" > + android:label="@string/map_map" > + android:label="@string/map_map" > + android:label="@string/map_static_title" > + android:label="@string/log_new_log"> @@ -181,7 +181,7 @@ @@ -204,32 +204,32 @@ + android:label="@string/compass_title"> + android:label="@string/simple_dir_chooser_title"> + android:label="@string/log_image"> diff --git a/main/libs/butterknife-1.3.2.jar b/main/libs/butterknife-1.3.2.jar new file mode 100644 index 0000000..1bd6fe6 Binary files /dev/null and b/main/libs/butterknife-1.3.2.jar differ diff --git a/main/proguard.cfg b/main/proguard.cfg index ee4d81a..4a8ef4b 100644 --- a/main/proguard.cfg +++ b/main/proguard.cfg @@ -63,3 +63,7 @@ -keepclassmembers class cgeo.geocaching.compatibility.AndroidLevel8 { public static ; } + +# Butter knife view injection, see http://jakewharton.github.io/butterknife/ +-dontwarn butterknife.Views$InjectViewProcessor +-keepclassmembers class **$$ViewInjector \ No newline at end of file diff --git a/main/src/cgeo/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java index c154ffb..3b76b6c 100644 --- a/main/src/cgeo/geocaching/AboutActivity.java +++ b/main/src/cgeo/geocaching/AboutActivity.java @@ -1,5 +1,7 @@ package cgeo.geocaching; +import butterknife.InjectView; + import cgeo.geocaching.activity.AbstractActivity; import cgeo.geocaching.utils.Version; @@ -11,18 +13,17 @@ import android.view.View; import android.widget.TextView; public class AboutActivity extends AbstractActivity { + @InjectView(R.id.about_version_string) protected TextView version; + @InjectView(R.id.contributors) protected TextView contributors; + @InjectView(R.id.changelog) protected TextView changeLog; @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setTheme(); - setContentView(R.layout.about_activity); - setTitle(res.getString(R.string.about)); + super.onCreate(savedInstanceState, R.layout.about_activity); - ((TextView) findViewById(R.id.about_version_string)).setText(Version.getVersionName(this)); - ((TextView) findViewById(R.id.contributors)).setMovementMethod(LinkMovementMethod.getInstance()); - ((TextView) findViewById(R.id.changelog)).setMovementMethod(LinkMovementMethod.getInstance()); + version.setText(Version.getVersionName(this)); + contributors.setMovementMethod(LinkMovementMethod.getInstance()); + changeLog.setMovementMethod(LinkMovementMethod.getInstance()); } /** diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java index 44acfc5..5769887 100644 --- a/main/src/cgeo/geocaching/AbstractPopupActivity.java +++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java @@ -144,7 +144,6 @@ public abstract class AbstractPopupActivity extends AbstractActivity { this.setTheme(ActivityMixin.getDialogTheme()); // set layout setContentView(layout); - setTitle(res.getString(R.string.detail)); // get parameters final Bundle extras = getIntent().getExtras(); diff --git a/main/src/cgeo/geocaching/AddressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java index b1de065..150bbc5 100644 --- a/main/src/cgeo/geocaching/AddressListActivity.java +++ b/main/src/cgeo/geocaching/AddressListActivity.java @@ -20,11 +20,7 @@ public class AddressListActivity extends AbstractListActivity { @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setTheme(); - setContentView(R.layout.addresses); - setTitle(res.getString(R.string.search_address_result)); + super.onCreate(savedInstanceState, R.layout.addresses); // get parameters final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD); diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index 074f111..d9ef503 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -199,12 +199,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity wayPointNames = new ArrayList(); for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) { wayPointNames.add(wpt.getL10n()); } - AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.name); ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, wayPointNames); - textView.setAdapter(adapter); + waypointName.setAdapter(adapter); if (id > 0) { - Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type); waypointTypeSelector.setVisibility(View.GONE); waitDialog = ProgressDialog.show(this, null, res.getString(R.string.waypoint_loading), true); @@ -171,7 +178,6 @@ public class EditWaypointActivity extends AbstractActivity { IConnector con = ConnectorFactory.getConnector(geocode); setCoordsModificationVisibility(con, cache); } - CheckBox visitedCheckBox = ((CheckBox) findViewById(R.id.wpt_visited_checkbox)); visitedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { @@ -181,16 +187,16 @@ public class EditWaypointActivity extends AbstractActivity { initializeDistanceUnitSelector(); - disableSuggestions((EditText) findViewById(R.id.distance)); + disableSuggestions(distanceView); } private void setCoordsModificationVisibility(IConnector con, Geocache cache) { if (cache != null && (cache.getType() == CacheType.MYSTERY || cache.getType() == CacheType.MULTI)) { - findViewById(R.id.modify_cache_coordinates_group).setVisibility(View.VISIBLE); - findViewById(R.id.modify_cache_coordinates_local_and_remote).setVisibility(con.supportsOwnCoordinates() ? View.VISIBLE : View.GONE); + coordinatesGroup.setVisibility(View.VISIBLE); + modifyBoth.setVisibility(con.supportsOwnCoordinates() ? View.VISIBLE : View.GONE); } else { - findViewById(R.id.modify_cache_coordinates_group).setVisibility(View.GONE); - findViewById(R.id.modify_cache_coordinates_local_and_remote).setVisibility(View.GONE); + coordinatesGroup.setVisibility(View.GONE); + modifyBoth.setVisibility(View.GONE); } } @@ -227,9 +233,6 @@ public class EditWaypointActivity extends AbstractActivity { } private void initializeWaypointTypeSelector() { - - Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type); - wpTypes = new ArrayList(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL); ArrayAdapter wpAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, wpTypes.toArray(new WaypointType[wpTypes.size()])); wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); @@ -247,9 +250,6 @@ public class EditWaypointActivity extends AbstractActivity { } private void initializeDistanceUnitSelector() { - - Spinner distanceUnitSelector = (Spinner) findViewById(R.id.distanceUnit); - if (StringUtils.isBlank(distanceUnit)) { if (Settings.isUseMetricUnits()) { distanceUnitSelector.setSelection(0); // m @@ -271,10 +271,8 @@ public class EditWaypointActivity extends AbstractActivity { } try { - Button bLat = (Button) findViewById(R.id.buttonLatitude); - Button bLon = (Button) findViewById(R.id.buttonLongitude); - bLat.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); - bLon.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); + buttonLat.setHint(geo.getCoords().format(GeopointFormatter.Format.LAT_DECMINUTE_RAW)); + buttonLon.setHint(geo.getCoords().format(GeopointFormatter.Format.LON_DECMINUTE_RAW)); } catch (final Exception e) { Log.e("failed to update location", e); } @@ -311,8 +309,8 @@ public class EditWaypointActivity extends AbstractActivity { coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() { @Override public void update(final Geopoint gp) { - ((Button) findViewById(R.id.buttonLatitude)).setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); - ((Button) findViewById(R.id.buttonLongitude)).setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); + buttonLat.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE)); + buttonLon.setText(gp.format(GeopointFormatter.Format.LON_DECMINUTE)); if (waypoint != null) { waypoint.setCoords(gp); } else { @@ -378,11 +376,11 @@ public class EditWaypointActivity extends AbstractActivity { @Override public void onClick(View arg0) { - final String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString(); + final String bearingText = bearing.getText().toString(); // combine distance from EditText and distanceUnit saved from Spinner - final String distanceText = ((EditText) findViewById(R.id.distance)).getText().toString() + distanceUnit; - final String latText = ((Button) findViewById(R.id.buttonLatitude)).getText().toString(); - final String lonText = ((Button) findViewById(R.id.buttonLongitude)).getText().toString(); + final String distanceText = distanceView.getText().toString() + distanceUnit; + final String latText = buttonLat.getText().toString(); + final String lonText = buttonLon.getText().toString(); if (StringUtils.isBlank(bearingText) && StringUtils.isBlank(distanceText) && StringUtils.isBlank(latText) && StringUtils.isBlank(lonText)) { @@ -430,9 +428,9 @@ public class EditWaypointActivity extends AbstractActivity { } // if no name is given, just give the waypoint its number as name - final String givenName = ((EditText) findViewById(R.id.name)).getText().toString().trim(); + final String givenName = waypointName.getText().toString().trim(); final String name = StringUtils.isNotEmpty(givenName) ? givenName : res.getString(R.string.waypoint) + " " + (wpCount + 1); - final String note = ((EditText) findViewById(R.id.note)).getText().toString().trim(); + final String noteText = note.getText().toString().trim(); final Geopoint coordsToSave = coords; final ProgressDialog progress = ProgressDialog.show(EditWaypointActivity.this, getString(R.string.cache), getString(R.string.waypoint_being_saved), true); final Handler finishHandler = new Handler() { @@ -483,7 +481,7 @@ public class EditWaypointActivity extends AbstractActivity { waypoint.setPrefix(prefix); waypoint.setLookup(lookup); waypoint.setCoords(coordsToSave); - waypoint.setNote(note); + waypoint.setNote(noteText); waypoint.setVisited(visited); waypoint.setId(id); @@ -501,8 +499,6 @@ public class EditWaypointActivity extends AbstractActivity { StaticMapsProvider.storeWaypointStaticMap(cache, waypoint, false); } } - final RadioButton modifyLocal = (RadioButton) findViewById(R.id.modify_cache_coordinates_local); - final RadioButton modifyBoth = (RadioButton) findViewById(R.id.modify_cache_coordinates_local_and_remote); if (modifyLocal.isChecked() || modifyBoth.isChecked()) { if (!cache.hasUserModifiedCoords()) { final Waypoint origWaypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false); diff --git a/main/src/cgeo/geocaching/GpxFileListActivity.java b/main/src/cgeo/geocaching/GpxFileListActivity.java index f12a30c..201565e 100644 --- a/main/src/cgeo/geocaching/GpxFileListActivity.java +++ b/main/src/cgeo/geocaching/GpxFileListActivity.java @@ -31,11 +31,6 @@ public class GpxFileListActivity extends AbstractFileListActivity 0) { navSatellites.setText(res.getString(R.string.loc_sat) + ": " + satellitesFixed + '/' + satellitesVisible); @@ -175,7 +187,10 @@ public class MainActivity extends AbstractActivity { @Override public void onCreate(Bundle savedInstanceState) { + // don't call the super implementation with the layout argument, as that would set the wrong theme super.onCreate(savedInstanceState); + setContentView(R.layout.main); + Views.inject(this); if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) { // If we had been open already, start from the last used activity. @@ -183,7 +198,6 @@ public class MainActivity extends AbstractActivity { return; } - setContentView(R.layout.main); setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); // type to search version = Version.getVersionCode(this); @@ -191,7 +205,6 @@ public class MainActivity extends AbstractActivity { try { if (!Settings.isHelpShown()) { - final RelativeLayout helper = (RelativeLayout) findViewById(R.id.helper); if (helper != null) { helper.setVisibility(View.VISIBLE); helper.setClickable(true); @@ -337,9 +350,6 @@ public class MainActivity extends AbstractActivity { } private void setFilterTitle() { - if (filterTitle == null) { - filterTitle = (TextView) findViewById(R.id.filter_button_title); - } filterTitle.setText(Settings.getCacheType().getL10n()); } @@ -357,7 +367,6 @@ public class MainActivity extends AbstractActivity { (new FirstLoginThread()).start(); } - final View findOnMap = findViewById(R.id.map); findOnMap.setClickable(true); findOnMap.setOnClickListener(new OnClickListener() { @Override @@ -366,7 +375,6 @@ public class MainActivity extends AbstractActivity { } }); - final View findByOffline = findViewById(R.id.search_offline); findByOffline.setClickable(true); findByOffline.setOnClickListener(new OnClickListener() { @Override @@ -391,7 +399,6 @@ public class MainActivity extends AbstractActivity { }); findByOffline.setLongClickable(true); - final View advanced = findViewById(R.id.advanced_button); advanced.setClickable(true); advanced.setOnClickListener(new OnClickListener() { @Override @@ -400,7 +407,6 @@ public class MainActivity extends AbstractActivity { } }); - final View any = findViewById(R.id.any_button); any.setClickable(true); any.setOnClickListener(new OnClickListener() { @Override @@ -409,7 +415,6 @@ public class MainActivity extends AbstractActivity { } }); - final View filter = findViewById(R.id.filter_button); filter.setClickable(true); filter.setOnClickListener(new View.OnClickListener() { @Override @@ -518,10 +523,6 @@ public class MainActivity extends AbstractActivity { @Override public void updateGeoData(final IGeoData geo) { - final View nearestView = findViewById(R.id.nearest); - final TextView navType = (TextView) findViewById(R.id.nav_type); - final TextView navAccuracy = (TextView) findViewById(R.id.nav_accuracy); - final TextView navLocation = (TextView) findViewById(R.id.nav_location); try { if (geo.getCoords() != null) { if (!nearestView.isClickable()) { @@ -582,7 +583,7 @@ public class MainActivity extends AbstractActivity { * unused here but needed since this method is referenced from XML layout */ public void cgeoFindOnMap(View v) { - findViewById(R.id.map).setPressed(true); + findOnMap.setPressed(true); CGeoMap.startActivityLiveMap(this); } @@ -595,7 +596,7 @@ public class MainActivity extends AbstractActivity { return; } - findViewById(R.id.nearest).setPressed(true); + nearestView.setPressed(true); cgeocaches.startActivityNearest(this, app.currentGeo().getCoords()); } @@ -604,7 +605,7 @@ public class MainActivity extends AbstractActivity { * unused here but needed since this method is referenced from XML layout */ public void cgeoFindByOffline(View v) { - findViewById(R.id.search_offline).setPressed(true); + findByOffline.setPressed(true); cgeocaches.startActivityOffline(this); } @@ -613,7 +614,7 @@ public class MainActivity extends AbstractActivity { * unused here but needed since this method is referenced from XML layout */ public void cgeoSearch(View v) { - findViewById(R.id.advanced_button).setPressed(true); + advanced.setPressed(true); startActivity(new Intent(this, SearchActivity.class)); } @@ -622,7 +623,7 @@ public class MainActivity extends AbstractActivity { * unused here but needed since this method is referenced from XML layout */ public void cgeoPoint(View v) { - findViewById(R.id.any_button).setPressed(true); + any.setPressed(true); startActivity(new Intent(this, NavigateAnyPointActivity.class)); } @@ -631,8 +632,8 @@ public class MainActivity extends AbstractActivity { * unused here but needed since this method is referenced from XML layout */ public void cgeoFilter(View v) { - findViewById(R.id.filter_button).setPressed(true); - findViewById(R.id.filter_button).performClick(); + filter.setPressed(true); + filter.performClick(); } /** @@ -645,15 +646,10 @@ public class MainActivity extends AbstractActivity { private class CountBubbleUpdateThread extends Thread { private Handler countBubbleHandler = new Handler() { - private TextView countBubble = null; @Override public void handleMessage(Message msg) { try { - if (countBubble == null) { - countBubble = (TextView) findViewById(R.id.offline_count); - } - if (countBubbleCnt == 0) { countBubble.setVisibility(View.GONE); } else { diff --git a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java index 74f656b..746842d 100644 --- a/main/src/cgeo/geocaching/NavigateAnyPointActivity.java +++ b/main/src/cgeo/geocaching/NavigateAnyPointActivity.java @@ -108,11 +108,7 @@ public class NavigateAnyPointActivity extends AbstractActivity { @Override public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setTheme(); - setContentView(R.layout.point); - setTitle(res.getString(R.string.search_destination)); + super.onCreate(savedInstanceState, R.layout.point); createHistoryView(); diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java index ecbd2b2..a3a0797 100644 --- a/main/src/cgeo/geocaching/SearchActivity.java +++ b/main/src/cgeo/geocaching/SearchActivity.java @@ -64,7 +64,6 @@ public class SearchActivity extends AbstractActivity { setTheme(); setContentView(R.layout.search); - setTitle(res.getString(R.string.search)); init(); } diff --git a/main/src/cgeo/geocaching/SelectMapfileActivity.java b/main/src/cgeo/geocaching/SelectMapfileActivity.java index 9557f3e..aa6d46a 100644 --- a/main/src/cgeo/geocaching/SelectMapfileActivity.java +++ b/main/src/cgeo/geocaching/SelectMapfileActivity.java @@ -55,11 +55,6 @@ public class SelectMapfileActivity extends AbstractFileListActivity> ext setTheme(); setContentView(R.layout.gpx); - setTitle(); Bundle extras = getIntent().getExtras(); if (extras != null) { @@ -146,11 +145,6 @@ public abstract class AbstractFileListActivity> ext */ protected abstract List getBaseFolders(); - /** - * Triggers the deriving class to set the title - */ - protected abstract void setTitle(); - private class SearchFilesThread extends Thread { private final FileListSelector selector = new FileListSelector(); diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java index 844287c..824173c 100644 --- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java +++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java @@ -2,11 +2,11 @@ package cgeo.geocaching.files; import cgeo.geocaching.Intents; import cgeo.geocaching.R; +import cgeo.geocaching.activity.AbstractListActivity; import cgeo.geocaching.activity.ActivityMixin; import org.apache.commons.lang3.StringUtils; -import android.app.ListActivity; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -31,7 +31,7 @@ import java.util.List; /** * Dialog for choosing a file or directory. */ -public class SimpleDirChooser extends ListActivity { +public class SimpleDirChooser extends AbstractListActivity { private static final String PARENT_DIR = ".. "; private File currentDir; private FileArrayAdapter adapter; @@ -46,7 +46,6 @@ public class SimpleDirChooser extends ListActivity { ActivityMixin.setTheme(this); setContentView(R.layout.simple_dir_chooser); - setTitle(this.getResources().getString(R.string.simple_dir_chooser_title)); fill(currentDir); @@ -106,13 +105,13 @@ public class SimpleDirChooser extends ListActivity { public class FileArrayAdapter extends ArrayAdapter Označení oblíbenosti keše selhalo. Výběr obrázku pro zápis selhal. - Získání obrázku selhalo. + Získání obrázku selhalo. c:geo nemůže zobrazit sledovatelný předmět. Je to opravdu sledovatelný předmět? c:geo nemůže otevřít podrobnosti ke sledovatelnému předmětu. @@ -563,10 +563,10 @@ Přidávání keše do tvého Watchlistu… Watchlist Odstraňování keše z tvého Watchlistu… - Oblíbené - Přidávání keše do Oblíbených… - Oblíbené - Odstraňování keše z Oblíbených… + Oblíbené + Přidávání keše do Oblíbených… + Oblíbené + Odstraňování keše z Oblíbených… Navigovat Navigace (Řízení) Navigace (Chůze) @@ -608,7 +608,7 @@ Hodnocení Vlastní hodnocení z - Oblíbená + Oblíbená Zakladatel Skryta Datum diff --git a/main/res/values-de/strings.xml b/main/res/values-de/strings.xml index 37aa5aa..26fd2d3 100644 --- a/main/res/values-de/strings.xml +++ b/main/res/values-de/strings.xml @@ -558,10 +558,10 @@ Füge den Cache deiner Watchlist hinzu… Watchlist Entferne den Cache von deiner Watchlist… - Favorit - Füge den Cache als dein Favorit hinzu… - Favorit - Entferne den Cache von deinen Favoriten… + Favorit + Füge den Cache zu Favoriten hinzu… + Favorit + Entferne den Cache von deinen Favoriten… Navigieren Navigation (Fahren) Navigation (Gehen) @@ -604,7 +604,7 @@ Bewertung Eigene Bewertung von - Favorit + Favorit Besitzer Versteckt Zeitangabe diff --git a/main/res/values-es/strings.xml b/main/res/values-es/strings.xml index b3096eb..f029d9b 100644 --- a/main/res/values-es/strings.xml +++ b/main/res/values-es/strings.xml @@ -485,7 +485,7 @@ Terreno Puntuación de - Favorito + Favorito Propietario Oculto Fecha diff --git a/main/res/values-fr/strings.xml b/main/res/values-fr/strings.xml index f7a6fde..a0f86e6 100644 --- a/main/res/values-fr/strings.xml +++ b/main/res/values-fr/strings.xml @@ -175,7 +175,7 @@ Veuillez saisir un nom pour votre appareil avant l\'enregistrement. c:geo ne peut pas changer le status de favori. La sélection d\'une image pour la note a échoué. - L\'acquisition d\'une nouvelle image pour la note a échoué. + L\'acquisition d\'une nouvelle image pour la note a échoué. "c:geo ne peut pas afficher l\'objet voyageur demandé. Est-ce vraiment un objet voyageur? c:geo ne peut pas ouvrir le détail de l\'objet voyageur. @@ -561,10 +561,10 @@ Ajout de la cache à votre liste de suivi… Liste de suivi Retrait de la cache de votre liste de suivi… - Favori - Ajout de la cache à vos favoris… - Favori - Suppression de la cache de vos favoris… + Favori + Ajout de la cache à vos favoris… + Favori + Suppression de la cache de vos favoris… Navigation Navigation (voiture) Navigation (piéton) @@ -606,7 +606,7 @@ Note Note personnelle de - Favori + Favori Propriétaire Cachée Date diff --git a/main/res/values-hu/strings.xml b/main/res/values-hu/strings.xml index 353aa10..e7018f9 100644 --- a/main/res/values-hu/strings.xml +++ b/main/res/values-hu/strings.xml @@ -568,7 +568,7 @@ Osztályzat Saját értékelés / - Kedvenc + Kedvenc Tulajdonos Elrejtve Dátum diff --git a/main/res/values-it/strings.xml b/main/res/values-it/strings.xml index 98a3f9c..ab43e86 100644 --- a/main/res/values-it/strings.xml +++ b/main/res/values-it/strings.xml @@ -176,7 +176,7 @@ Errore nella modifica dello stato preferiti. La selezione dell\'immagine per il log è fallita. - Acquisizione immagine fallita. + Acquisizione immagine fallita. c:geo non riesce a visualizzare il trackable che vuoi. È veramente un trackable? c:geo non riesce ad aprire i dettagli del trackable. @@ -556,10 +556,10 @@ Aggiunto il cache alla watchlist in corso… Watchlist Rimozione dei cache dalla tua watchlist… - Preferiti - Aggiungi il cache ai tuoi preferiti… - Preferiti - Rimozione cache dai tuoi preferiti… + Preferiti + Aggiungi il cache ai tuoi preferiti… + Preferiti + Rimozione cache dai tuoi preferiti… Naviga Naviga (in auto) Naviga (a piedi) @@ -601,7 +601,7 @@ Voto Il tuo voto di - Popolarità + Popolarità Proprietario Nascosto il Data diff --git a/main/res/values-ja/strings.xml b/main/res/values-ja/strings.xml index 27ffbd3..5d7759e 100644 --- a/main/res/values-ja/strings.xml +++ b/main/res/values-ja/strings.xml @@ -540,10 +540,10 @@ ウォッチリストに追加中… ウォッチリスト ウォッチリストから削除中… - お気に入り - お気に入りに追加中… - お気に入り - お気に入りから削除中… + お気に入り + お気に入りに追加中… + お気に入り + お気に入りから削除中… ナビゲーション ナビゲーション(自動車) ナビゲーション(徒歩) @@ -586,7 +586,7 @@ 評価 Own Rating / - お気に入り + お気に入り 所有者 隠した日 イベント日付 diff --git a/main/res/values-nl/strings.xml b/main/res/values-nl/strings.xml index 557aa79..8ce95a5 100644 --- a/main/res/values-nl/strings.xml +++ b/main/res/values-nl/strings.xml @@ -546,10 +546,10 @@ Voeg cache toe aan watchlist… Watchlist Verwijder cache van watchlist… - Favoriet - Voeg cache toe aan favorieten… - Favoriet - Verwijder cache van je favorieten… + Favoriet + Voeg cache toe aan favorieten… + Favoriet + Verwijder cache van je favorieten… Navigeer Navigeer (rijden) Navigeer (lopen) @@ -591,7 +591,7 @@ Waardering Eigen waardering van - Favoriet + Favoriet Eigenaar Verstopt Datum diff --git a/main/res/values-pl/strings.xml b/main/res/values-pl/strings.xml index 1f23f63..b4fbca7 100644 --- a/main/res/values-pl/strings.xml +++ b/main/res/values-pl/strings.xml @@ -533,10 +533,10 @@ Dodaję skrzynkę do listy obserwowanych… Lista obserwowanych Usuwam skrzynkę z listy obserwowanych… - Ulubione - Dodaję skrzynkę do listy ulubionych… - Ulubione - Usuwam skrzynkę z listy ulubionych… + Ulubione + Dodaję skrzynkę do listy ulubionych… + Ulubione + Usuwam skrzynkę z listy ulubionych… Nawiguj Nawigacja (jazda) Nawigacja (pieszo) @@ -578,7 +578,7 @@ Ocena Własna ocena od - Ulubiona + Ulubiona Właściciel Ukryta Data diff --git a/main/res/values-pt/strings.xml b/main/res/values-pt/strings.xml index d6ee413..e4bcfd4 100644 --- a/main/res/values-pt/strings.xml +++ b/main/res/values-pt/strings.xml @@ -571,7 +571,7 @@ Pontuação A minha pontuação de - Favorita + Favorita Dono Escondida Data diff --git a/main/res/values-sk/strings.xml b/main/res/values-sk/strings.xml index ef316ea..616bd44 100644 --- a/main/res/values-sk/strings.xml +++ b/main/res/values-sk/strings.xml @@ -570,7 +570,7 @@ Hodnotenie Vlastné hodnotenie z - Obľúbené + Obľúbené Vlastník Skrytá Dátum diff --git a/main/res/values-sv/strings.xml b/main/res/values-sv/strings.xml index b68de4c..0f23eed 100644 --- a/main/res/values-sv/strings.xml +++ b/main/res/values-sv/strings.xml @@ -176,7 +176,7 @@ Misslyckades att ändra favoritstatus. Misslyckades att välja bild till loggen. - Hämtning av bilden misslyckades. + Hämtning av bilden misslyckades. Tyvärr kan c:geo inte visa den trackable du önskar. Är den verkligen trackable? Tyvärr kan c:geo inte öppna detaljer för trackable. Tyvärr glömde c:geo vilken trackable du såg. @@ -561,10 +561,10 @@ Lägger till cachen till din watchlist… Watchlist Tar bort cachen från din watchlist… - Favorit - Lägger till cachen till dina favoriter… - Favorit - Tar bort cachen från dina favoriter… + Favorit + Lägger till cachen till dina favoriter… + Favorit + Tar bort cachen från dina favoriter… Navigera Navigering (med bil) Navigering (till fots) @@ -606,7 +606,7 @@ Betyg Eget betyg av - Favorit + Favorit Ägare Gömd Datum diff --git a/main/res/values/attrs.xml b/main/res/values/attrs.xml index 558c353..092d307 100644 --- a/main/res/values/attrs.xml +++ b/main/res/values/attrs.xml @@ -22,10 +22,10 @@ - - - - + + + + diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml index b7e1f8d..42abb8f 100644 --- a/main/res/values/strings.xml +++ b/main/res/values/strings.xml @@ -183,7 +183,7 @@ Please enter a device name before registering. Changing favorite status failed. Selecting an image for the log failed. - Acquiring an image failed. + Acquiring an image failed. c:geo can\'t display trackable you want. Is it really a trackable? c:geo can\'t open trackable details. @@ -569,10 +569,10 @@ Adding cache to your watchlist… Watchlist Removing cache from your watchlist… - Favourite - Adding cache to your favourites… - Favourite - Removing cache from your favourites… + Favorite + Adding cache to your favorites… + Favorite + Removing cache from your favorites… Navigate Navigation (Driving) Navigation (Walking) @@ -616,7 +616,7 @@ Rating Own Rating of - Favorite + Favorite Owner Hidden Date diff --git a/main/res/values/themes.xml b/main/res/values/themes.xml index fdc2eeb..655d9e1 100644 --- a/main/res/values/themes.xml +++ b/main/res/values/themes.xml @@ -36,10 +36,10 @@ @drawable/action_button_dark @drawable/input_bcg_dark @drawable/inventory_background_dark - @drawable/favourite_background_dark - @drawable/favourite_background_red_dark - @drawable/favourite_background_orange_dark - @drawable/favourite_background_green_dark + @drawable/favorite_background_dark + @drawable/favorite_background_red_dark + @drawable/favorite_background_orange_dark + @drawable/favorite_background_green_dark @drawable/map_close_dark @drawable/log_img_dark @drawable/actionbar_compass_dark @@ -67,10 +67,10 @@ @drawable/action_button_light @drawable/input_bcg_light @drawable/inventory_background_light - @drawable/favourite_background_light - @drawable/favourite_background_red_light - @drawable/favourite_background_orange_light - @drawable/favourite_background_green_light + @drawable/favorite_background_light + @drawable/favorite_background_red_light + @drawable/favorite_background_orange_light + @drawable/favorite_background_green_light @drawable/map_close_light @drawable/log_img_light @drawable/actionbar_compass_light @@ -109,10 +109,10 @@ @drawable/action_button_dark @drawable/input_bcg_dark @drawable/inventory_background_dark - @drawable/favourite_background_dark - @drawable/favourite_background_red_dark - @drawable/favourite_background_orange_dark - @drawable/favourite_background_green_dark + @drawable/favorite_background_dark + @drawable/favorite_background_red_dark + @drawable/favorite_background_orange_dark + @drawable/favorite_background_green_dark @drawable/map_close_dark @drawable/log_img_dark @drawable/actionbar_compass_dark @@ -141,10 +141,10 @@ @drawable/action_button_light @drawable/input_bcg_light @drawable/inventory_background_light - @drawable/favourite_background_light - @drawable/favourite_background_red_light - @drawable/favourite_background_orange_light - @drawable/favourite_background_green_light + @drawable/favorite_background_light + @drawable/favorite_background_red_light + @drawable/favorite_background_orange_light + @drawable/favorite_background_green_light @drawable/map_close_light @drawable/log_img_light @drawable/actionbar_compass_light diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java index 5769887..5ad89fb 100644 --- a/main/src/cgeo/geocaching/AbstractPopupActivity.java +++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java @@ -278,8 +278,8 @@ public abstract class AbstractPopupActivity extends AbstractActivity { aquireGCVote(); } - // favourite count - details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×"); + // favorite count + details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×"); // more details final Button buttonMore = (Button) findViewById(R.id.more_details); diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java index d9ef503..fd42f07 100644 --- a/main/src/cgeo/geocaching/CacheDetailActivity.java +++ b/main/src/cgeo/geocaching/CacheDetailActivity.java @@ -1163,7 +1163,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity 0) { - details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×"); + details.add(R.string.cache_favorite, cache.getFavoritePoints() + "×"); } // own rating @@ -1487,7 +1487,7 @@ public class CacheDetailActivity extends AbstractViewPagerActivity - - - - - - - - - - - - + - - - - - - - - + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_button_compass.xml b/main/res/layout/actionbar_button_compass.xml new file mode 100644 index 0000000..932444b --- /dev/null +++ b/main/res/layout/actionbar_button_compass.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_button_manual.xml b/main/res/layout/actionbar_button_manual.xml new file mode 100644 index 0000000..86965f1 --- /dev/null +++ b/main/res/layout/actionbar_button_manual.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_button_map.xml b/main/res/layout/actionbar_button_map.xml new file mode 100644 index 0000000..9b2138a --- /dev/null +++ b/main/res/layout/actionbar_button_map.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_button_myposition.xml b/main/res/layout/actionbar_button_myposition.xml new file mode 100644 index 0000000..3604345 --- /dev/null +++ b/main/res/layout/actionbar_button_myposition.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_button_search.xml b/main/res/layout/actionbar_button_search.xml new file mode 100644 index 0000000..2aa1a50 --- /dev/null +++ b/main/res/layout/actionbar_button_search.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_progress.xml b/main/res/layout/actionbar_progress.xml new file mode 100644 index 0000000..a39d103 --- /dev/null +++ b/main/res/layout/actionbar_progress.xml @@ -0,0 +1,4 @@ + + \ No newline at end of file diff --git a/main/res/layout/actionbar_title.xml b/main/res/layout/actionbar_title.xml new file mode 100644 index 0000000..4fa5348 --- /dev/null +++ b/main/res/layout/actionbar_title.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/actionbar_with_manual.xml b/main/res/layout/actionbar_with_manual.xml new file mode 100644 index 0000000..d56c14e --- /dev/null +++ b/main/res/layout/actionbar_with_manual.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/main/res/layout/addresses.xml b/main/res/layout/addresses.xml index 2be131d..08f5bc1 100644 --- a/main/res/layout/addresses.xml +++ b/main/res/layout/addresses.xml @@ -4,16 +4,7 @@ android:layout_height="fill_parent" android:orientation="vertical" > - - - - - - - - + - + + + + + - - - - - - - - - - - - - + diff --git a/main/res/layout/cacheview.xml b/main/res/layout/cacheview.xml index 89d7152..ec30672 100644 --- a/main/res/layout/cacheview.xml +++ b/main/res/layout/cacheview.xml @@ -8,29 +8,11 @@ - + - + - - - - - - - - - + - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - + - - - - - - - - - - - - + - + - - - - - + - + - + - - - - - - - - - - - + + + diff --git a/main/res/layout/map_mapsforge.xml b/main/res/layout/map_mapsforge.xml index f3b183e..27d6e0d 100644 --- a/main/res/layout/map_mapsforge.xml +++ b/main/res/layout/map_mapsforge.xml @@ -6,30 +6,13 @@ - + - + - + - - - - - - - - - + diff --git a/main/res/layout/map_mapsforge_old.xml b/main/res/layout/map_mapsforge_old.xml index 44b3387..f2cb175 100644 --- a/main/res/layout/map_mapsforge_old.xml +++ b/main/res/layout/map_mapsforge_old.xml @@ -6,30 +6,13 @@ - + - + - - - - - - - - - - - + + + diff --git a/main/res/layout/map_static.xml b/main/res/layout/map_static.xml index ff0435c..edf6c6e 100644 --- a/main/res/layout/map_static.xml +++ b/main/res/layout/map_static.xml @@ -4,16 +4,7 @@ android:layout_height="fill_parent" android:orientation="vertical" > - - - - - - - - + - - - - - - - - - - - - + - - - - - - - - - - - - + - - - - - - - + + + - - - - - - - - - - - - + - - - - - - - - + diff --git a/main/res/layout/touch.xml b/main/res/layout/touch.xml index 09a8033..17553d1 100644 --- a/main/res/layout/touch.xml +++ b/main/res/layout/touch.xml @@ -7,24 +7,11 @@ - + - + - - - - - - - + - - - - - - - - - - - - + - - - - - - - - + - - - - - - - - + - + - + - - - - - - - + - + - + - - - - - - - + - - - - - - - + + + - - - - diff --git a/main/res/values/styles.xml b/main/res/values/styles.xml index caa884a..0116577 100644 --- a/main/res/values/styles.xml +++ b/main/res/values/styles.xml @@ -81,7 +81,6 @@