aboutsummaryrefslogtreecommitdiffstats
path: root/main/src
diff options
context:
space:
mode:
Diffstat (limited to 'main/src')
-rw-r--r--main/src/android/support/v4/app/FragmentListActivity.java316
-rw-r--r--main/src/cgeo/geocaching/AboutActivity.java2
-rw-r--r--main/src/cgeo/geocaching/AbstractLoggingActivity.java6
-rw-r--r--main/src/cgeo/geocaching/AbstractPopupActivity.java23
-rw-r--r--main/src/cgeo/geocaching/AddressListActivity.java (renamed from main/src/cgeo/geocaching/AdressListActivity.java)10
-rw-r--r--main/src/cgeo/geocaching/CacheCache.java16
-rw-r--r--main/src/cgeo/geocaching/CacheDetailActivity.java1161
-rw-r--r--main/src/cgeo/geocaching/CachePopup.java76
-rw-r--r--main/src/cgeo/geocaching/Destination.java8
-rw-r--r--main/src/cgeo/geocaching/DirectionProvider.java18
-rw-r--r--main/src/cgeo/geocaching/EditWaypointActivity.java199
-rw-r--r--main/src/cgeo/geocaching/Geocache.java (renamed from main/src/cgeo/geocaching/cgCache.java)352
-rw-r--r--main/src/cgeo/geocaching/ICache.java8
-rw-r--r--main/src/cgeo/geocaching/IWaypoint.java8
-rw-r--r--main/src/cgeo/geocaching/Image.java (renamed from main/src/cgeo/geocaching/cgImage.java)18
-rw-r--r--main/src/cgeo/geocaching/ImagesActivity.java15
-rw-r--r--main/src/cgeo/geocaching/Intents.java28
-rw-r--r--main/src/cgeo/geocaching/LiveMapInfo.java52
-rw-r--r--main/src/cgeo/geocaching/LogEntry.java18
-rw-r--r--main/src/cgeo/geocaching/LogTrackableActivity.java30
-rw-r--r--main/src/cgeo/geocaching/SearchActivity.java31
-rw-r--r--main/src/cgeo/geocaching/SearchResult.java109
-rw-r--r--main/src/cgeo/geocaching/Settings.java74
-rw-r--r--main/src/cgeo/geocaching/SettingsActivity.java163
-rw-r--r--main/src/cgeo/geocaching/StaticMapsActivity.java22
-rw-r--r--main/src/cgeo/geocaching/StaticMapsProvider.java81
-rw-r--r--main/src/cgeo/geocaching/StatusFragment.java110
-rw-r--r--main/src/cgeo/geocaching/StoredList.java54
-rw-r--r--main/src/cgeo/geocaching/Trackable.java (renamed from main/src/cgeo/geocaching/cgTrackable.java)14
-rw-r--r--main/src/cgeo/geocaching/TrackableActivity.java681
-rw-r--r--main/src/cgeo/geocaching/VisitCacheActivity.java746
-rw-r--r--main/src/cgeo/geocaching/Waypoint.java (renamed from main/src/cgeo/geocaching/cgWaypoint.java)60
-rw-r--r--main/src/cgeo/geocaching/WaypointPopup.java19
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractActivity.java6
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractListActivity.java4
-rw-r--r--main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java276
-rw-r--r--main/src/cgeo/geocaching/activity/FilteredActivity.java11
-rw-r--r--main/src/cgeo/geocaching/activity/Progress.java2
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/AbstractLocusApp.java27
-rw-r--r--main/src/cgeo/geocaching/apps/App.java4
-rw-r--r--main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java24
-rw-r--r--main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java9
-rw-r--r--main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java11
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GccApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GeneralApp.java12
-rw-r--r--main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java48
-rw-r--r--main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java26
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java12
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java17
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java6
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java12
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java12
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java48
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java63
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java12
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java18
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java66
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java10
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java12
-rw-r--r--main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java6
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java6
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java4
-rw-r--r--main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java4
-rw-r--r--main/src/cgeo/geocaching/cgData.java1433
-rw-r--r--main/src/cgeo/geocaching/cgSelectMapfile.java2
-rw-r--r--main/src/cgeo/geocaching/cgeo.java288
-rw-r--r--main/src/cgeo/geocaching/cgeoapplication.java341
-rw-r--r--main/src/cgeo/geocaching/cgeocaches.java532
-rw-r--r--main/src/cgeo/geocaching/cgeogpxes.java19
-rw-r--r--main/src/cgeo/geocaching/cgeonavigate.java5
-rw-r--r--main/src/cgeo/geocaching/cgeopoint.java19
-rw-r--r--main/src/cgeo/geocaching/cgeotrackable.java575
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java (renamed from main/src/cgeo/geocaching/compatibility/AndroidLevel11Dummy.java)4
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel13.java31
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java33
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java11
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel8.java20
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java16
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java30
-rw-r--r--main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java1
-rw-r--r--main/src/cgeo/geocaching/compatibility/Compatibility.java51
-rw-r--r--main/src/cgeo/geocaching/connector/AbstractConnector.java54
-rw-r--r--main/src/cgeo/geocaching/connector/ConnectorFactory.java57
-rw-r--r--main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java10
-rw-r--r--main/src/cgeo/geocaching/connector/GeopeitusConnector.java10
-rw-r--r--main/src/cgeo/geocaching/connector/IConnector.java69
-rw-r--r--main/src/cgeo/geocaching/connector/UnknownConnector.java10
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java1
-rw-r--r--main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConnector.java105
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCConstants.java12
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCMap.java37
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCParser.java313
-rw-r--r--main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/IconDecoder.java566
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Login.java15
-rw-r--r--main/src/cgeo/geocaching/connector/gc/Tile.java102
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGrid.java2
-rw-r--r--main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java5
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java716
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCApiConnector.java12
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCConnector.java16
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java60
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OCXMLClient.java115
-rw-r--r--main/src/cgeo/geocaching/connector/oc/OkapiClient.java34
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OXConnector.java16
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OXGPXParser.java4
-rw-r--r--main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java12
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheAttribute.java233
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheRealm.java22
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheSize.java7
-rw-r--r--main/src/cgeo/geocaching/enumerations/CacheType.java31
-rw-r--r--main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/LocationProviderType.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogType.java50
-rw-r--r--main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java2
-rw-r--r--main/src/cgeo/geocaching/enumerations/WaypointType.java12
-rw-r--r--main/src/cgeo/geocaching/export/Export.java10
-rw-r--r--main/src/cgeo/geocaching/export/ExportFactory.java6
-rw-r--r--main/src/cgeo/geocaching/export/FieldnoteExport.java139
-rw-r--r--main/src/cgeo/geocaching/export/GpxExport.java393
-rw-r--r--main/src/cgeo/geocaching/files/FileList.java23
-rw-r--r--main/src/cgeo/geocaching/files/FileParser.java8
-rw-r--r--main/src/cgeo/geocaching/files/GPXImporter.java36
-rw-r--r--main/src/cgeo/geocaching/files/GPXParser.java92
-rw-r--r--main/src/cgeo/geocaching/files/LocParser.java82
-rw-r--r--main/src/cgeo/geocaching/files/LocalStorage.java6
-rw-r--r--main/src/cgeo/geocaching/files/ParserException.java4
-rw-r--r--main/src/cgeo/geocaching/files/SimpleDirChooser.java20
-rw-r--r--main/src/cgeo/geocaching/filter/AbstractFilter.java10
-rw-r--r--main/src/cgeo/geocaching/filter/AbstractRangeFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/AttributeFilter.java7
-rw-r--r--main/src/cgeo/geocaching/filter/DifficultyFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/FilterUserInterface.java2
-rw-r--r--main/src/cgeo/geocaching/filter/IFilter.java6
-rw-r--r--main/src/cgeo/geocaching/filter/ModifiedFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/SizeFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/StateFilter.java14
-rw-r--r--main/src/cgeo/geocaching/filter/TerrainFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/TrackablesFilter.java4
-rw-r--r--main/src/cgeo/geocaching/filter/TypeFilter.java4
-rw-r--r--main/src/cgeo/geocaching/gcvote/GCVote.java61
-rw-r--r--main/src/cgeo/geocaching/geopoint/DistanceParser.java12
-rw-r--r--main/src/cgeo/geocaching/geopoint/Geopoint.java32
-rw-r--r--main/src/cgeo/geocaching/geopoint/GeopointFormatter.java21
-rw-r--r--main/src/cgeo/geocaching/geopoint/GeopointParser.java37
-rw-r--r--main/src/cgeo/geocaching/geopoint/Viewport.java5
-rw-r--r--main/src/cgeo/geocaching/loaders/UrlLoader.java35
-rw-r--r--main/src/cgeo/geocaching/maps/AbstractMapSource.java2
-rw-r--r--main/src/cgeo/geocaching/maps/CGeoMap.java419
-rw-r--r--main/src/cgeo/geocaching/maps/CachesOverlay.java21
-rw-r--r--main/src/cgeo/geocaching/maps/MapProviderFactory.java2
-rw-r--r--main/src/cgeo/geocaching/maps/PositionOverlay.java9
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java7
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java14
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleMapView.java4
-rw-r--r--main/src/cgeo/geocaching/maps/google/GoogleOverlay.java3
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java8
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java11
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java4
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java3
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java8
-rw-r--r--main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java4
-rw-r--r--main/src/cgeo/geocaching/network/HtmlImage.java16
-rw-r--r--main/src/cgeo/geocaching/network/Network.java91
-rw-r--r--main/src/cgeo/geocaching/network/Parameters.java5
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java2
-rw-r--r--main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java10
-rw-r--r--main/src/cgeo/geocaching/sorting/CacheComparator.java4
-rw-r--r--main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java2
-rw-r--r--main/src/cgeo/geocaching/sorting/DateComparator.java8
-rw-r--r--main/src/cgeo/geocaching/sorting/DifficultyComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/DistanceComparator.java28
-rw-r--r--main/src/cgeo/geocaching/sorting/FindsComparator.java14
-rw-r--r--main/src/cgeo/geocaching/sorting/GeocodeComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/InventoryComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/InverseComparator.java22
-rw-r--r--main/src/cgeo/geocaching/sorting/NameComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/PopularityComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/RatingComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/SizeComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/StateComparator.java8
-rw-r--r--main/src/cgeo/geocaching/sorting/StorageTimeComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/TerrainComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/VisitComparator.java6
-rw-r--r--main/src/cgeo/geocaching/sorting/VoteComparator.java6
-rw-r--r--main/src/cgeo/geocaching/twitter/Twitter.java11
-rw-r--r--main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java34
-rw-r--r--main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java32
-rw-r--r--main/src/cgeo/geocaching/ui/CacheDetailsCreator.java27
-rw-r--r--main/src/cgeo/geocaching/ui/CacheListAdapter.java101
-rw-r--r--main/src/cgeo/geocaching/ui/CompassMiniView.java6
-rw-r--r--main/src/cgeo/geocaching/ui/CompassView.java7
-rw-r--r--main/src/cgeo/geocaching/ui/Formatter.java24
-rw-r--r--main/src/cgeo/geocaching/ui/ImagesList.java27
-rw-r--r--main/src/cgeo/geocaching/ui/LoggingUI.java17
-rw-r--r--main/src/cgeo/geocaching/ui/WeakReferenceHandler.java27
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java (renamed from main/src/cgeo/geocaching/cgeocoords.java)14
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/CustomProgressDialog.java (renamed from main/src/cgeo/geocaching/ui/CustomProgressDialog.java)2
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/DateDialog.java (renamed from main/src/cgeo/geocaching/ui/DateDialog.java)2
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/EditorDialog.java (renamed from main/src/cgeo/geocaching/ui/EditorDialog.java)4
-rw-r--r--main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java43
-rw-r--r--main/src/cgeo/geocaching/utils/AngleUtils.java8
-rw-r--r--main/src/cgeo/geocaching/utils/CryptUtils.java18
-rw-r--r--main/src/cgeo/geocaching/utils/IOUtils.java20
-rw-r--r--main/src/cgeo/geocaching/utils/ImageHelper.java11
-rw-r--r--main/src/cgeo/geocaching/utils/LazyInitializedList.java98
-rw-r--r--main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java2
-rw-r--r--main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java21
-rw-r--r--main/src/cgeo/geocaching/utils/Log.java34
-rw-r--r--main/src/cgeo/geocaching/utils/LogTemplateProvider.java22
-rw-r--r--main/src/cgeo/geocaching/utils/MatcherWrapper.java91
-rw-r--r--main/src/cgeo/geocaching/utils/PeriodicHandler.java2
-rw-r--r--main/src/cgeo/geocaching/utils/TranslationUtils.java5
-rw-r--r--main/src/cgeo/geocaching/utils/XmlUtils.java41
-rw-r--r--main/src/com/viewpagerindicator/TitlePageIndicator.java6
-rw-r--r--main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java8
-rw-r--r--main/src/org/openintents/intents/FileManagerIntents.java127
223 files changed, 8369 insertions, 5866 deletions
diff --git a/main/src/android/support/v4/app/FragmentListActivity.java b/main/src/android/support/v4/app/FragmentListActivity.java
new file mode 100644
index 0000000..e3ed42c
--- /dev/null
+++ b/main/src/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.
+ * <p>
+ * 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.
+ * <p>
+ * <strong>Screen Layout</strong>
+ * </p>
+ * <p>
+ * 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)
+ * <p>
+ * 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.
+ * <p>
+ * The following code demonstrates an (ugly) custom screen layout. It has a list
+ * with a green background, and an alternate red "no data" message.
+ * </p>
+ *
+ * <pre>
+ * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+ * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:orientation=&quot;vertical&quot;
+ * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_height=&quot;fill_parent&quot;
+ * android:paddingLeft=&quot;8dp&quot;
+ * android:paddingRight=&quot;8dp&quot;&gt;
+ *
+ * &lt;ListView android:id=&quot;@id/android:list&quot;
+ * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_height=&quot;fill_parent&quot;
+ * android:background=&quot;#00FF00&quot;
+ * android:layout_weight=&quot;1&quot;
+ * android:drawSelectorOnTop=&quot;false&quot;/&gt;
+ *
+ * &lt;TextView android:id=&quot;@id/android:empty&quot;
+ * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_height=&quot;fill_parent&quot;
+ * android:background=&quot;#FF0000&quot;
+ * android:text=&quot;No data&quot;/&gt;
+ * &lt;/LinearLayout&gt;
+ * </pre>
+ *
+ * <p>
+ * <strong>Row Layout</strong>
+ * </p>
+ * <p>
+ * 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).
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * <pre>
+ * &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
+ * &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_height=&quot;wrap_content&quot;
+ * android:orientation=&quot;vertical&quot;&gt;
+ *
+ * &lt;TextView android:id=&quot;@+id/text1&quot;
+ * android:textSize=&quot;16sp&quot;
+ * android:textStyle=&quot;bold&quot;
+ * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_height=&quot;wrap_content&quot;/&gt;
+ *
+ * &lt;TextView android:id=&quot;@+id/text2&quot;
+ * android:textSize=&quot;16sp&quot;
+ * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_height=&quot;wrap_content&quot;/&gt;
+ * &lt;/LinearLayout&gt;
+ * </pre>
+ *
+ * <p>
+ * You must identify the data bound to each TextView object in this layout. The
+ * syntax for this is discussed in the next section.
+ * </p>
+ * <p>
+ * <strong>Binding to Data</strong>
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ * <p>
+ * 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.
+ * </p>
+ *
+ * <pre>
+ * public class MyListAdapter extends FragmentListActivity {
+ *
+ * &#064;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);
+ * }
+ * }
+ * </pre>
+ *
+ * @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/geocaching/AboutActivity.java b/main/src/cgeo/geocaching/AboutActivity.java
index b7a14ff..c154ffb 100644
--- a/main/src/cgeo/geocaching/AboutActivity.java
+++ b/main/src/cgeo/geocaching/AboutActivity.java
@@ -17,7 +17,7 @@ public class AboutActivity extends AbstractActivity {
super.onCreate(savedInstanceState);
setTheme();
- setContentView(R.layout.about);
+ setContentView(R.layout.about_activity);
setTitle(res.getString(R.string.about));
((TextView) findViewById(R.id.about_version_string)).setText(Version.getVersionName(this));
diff --git a/main/src/cgeo/geocaching/AbstractLoggingActivity.java b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
index 62cb5cb..37c3643 100644
--- a/main/src/cgeo/geocaching/AbstractLoggingActivity.java
+++ b/main/src/cgeo/geocaching/AbstractLoggingActivity.java
@@ -20,7 +20,7 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
private static final int MENU_SIGNATURE = 1;
private static final int MENU_SMILEY = 2;
- public AbstractLoggingActivity(String helpTopic) {
+ protected AbstractLoggingActivity(String helpTopic) {
super(helpTopic);
}
@@ -51,11 +51,11 @@ public abstract class AbstractLoggingActivity extends AbstractActivity {
menu.findItem(MENU_SIGNATURE).setVisible(signatureAvailable);
boolean smileyVisible = false;
- final cgCache cache = getLogContext().getCache();
+ final Geocache cache = getLogContext().getCache();
if (cache != null && ConnectorFactory.getConnector(cache).equals(GCConnector.getInstance())) {
smileyVisible = true;
}
- final cgTrackable trackable = getLogContext().getTrackable();
+ final Trackable trackable = getLogContext().getTrackable();
if (trackable != null && ConnectorFactory.getConnector(trackable).equals(GCConnector.getInstance())) {
smileyVisible = true;
}
diff --git a/main/src/cgeo/geocaching/AbstractPopupActivity.java b/main/src/cgeo/geocaching/AbstractPopupActivity.java
index 830d61a..c38d5ea 100644
--- a/main/src/cgeo/geocaching/AbstractPopupActivity.java
+++ b/main/src/cgeo/geocaching/AbstractPopupActivity.java
@@ -37,9 +37,8 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
private static final int MENU_NAVIGATION = 3;
private static final int MENU_DEFAULT_NAVIGATION = 2;
private static final int MENU_SHOW_IN_BROWSER = 7;
- protected static final String EXTRA_GEOCODE = "geocode";
- protected cgCache cache = null;
+ protected Geocache cache = null;
protected String geocode = null;
protected CacheDetailsCreator details;
@@ -73,7 +72,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
}
};
- public AbstractPopupActivity(String helpTopic, int layout) {
+ protected AbstractPopupActivity(String helpTopic, int layout) {
super(helpTopic);
this.layout = layout;
}
@@ -109,7 +108,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
}
protected void init() {
- cache = app.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
if (cache == null) {
showToast(res.getString(R.string.err_detail_cache_find));
@@ -118,7 +117,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
return;
}
- geocode = cache.getGeocode().toUpperCase();
+ geocode = cache.getGeocode();
}
private void showInBrowser() {
@@ -137,7 +136,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
// get parameters
final Bundle extras = getIntent().getExtras();
if (extras != null) {
- geocode = extras.getString(EXTRA_GEOCODE);
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
}
if (StringUtils.isBlank(geocode)) {
@@ -186,10 +185,10 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
case MENU_SHOW_IN_BROWSER:
showInBrowser();
return true;
- }
-
- if (LoggingUI.onMenuItemSelected(item, this, cache)) {
- return true;
+ default:
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
}
return true;
@@ -251,7 +250,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
final String cacheSize = cache.getSize() != CacheSize.UNKNOWN ? " (" + cache.getSize().getL10n() + ")" : "";
details.add(R.string.cache_type, cacheType + cacheSize);
- details.add(R.string.cache_geocode, cache.getGeocode().toUpperCase());
+ details.add(R.string.cache_geocode, cache.getGeocode());
details.addCacheState(cache);
details.addDistance(cache, cacheDistance);
@@ -276,7 +275,7 @@ public abstract class AbstractPopupActivity extends AbstractActivity {
@Override
public void onClick(View arg0) {
- CacheDetailActivity.startActivity(AbstractPopupActivity.this, geocode.toUpperCase());
+ CacheDetailActivity.startActivity(AbstractPopupActivity.this, geocode);
finish();
}
});
diff --git a/main/src/cgeo/geocaching/AdressListActivity.java b/main/src/cgeo/geocaching/AddressListActivity.java
index 8ce16dd..b1de065 100644
--- a/main/src/cgeo/geocaching/AdressListActivity.java
+++ b/main/src/cgeo/geocaching/AddressListActivity.java
@@ -16,7 +16,7 @@ import android.os.Bundle;
import java.util.List;
import java.util.Locale;
-public class AdressListActivity extends AbstractListActivity {
+public class AddressListActivity extends AbstractListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -27,7 +27,7 @@ public class AdressListActivity extends AbstractListActivity {
setTitle(res.getString(R.string.search_address_result));
// get parameters
- final String keyword = getIntent().getStringExtra("keyword");
+ final String keyword = getIntent().getStringExtra(Intents.EXTRA_KEYWORD);
if (keyword == null) {
showToast(res.getString(R.string.err_search_address_forgot));
@@ -46,7 +46,7 @@ public class AdressListActivity extends AbstractListActivity {
@Override
protected List<Address> doInBackground(Void... params) {
- final Geocoder geocoder = new Geocoder(AdressListActivity.this, Locale.getDefault());
+ final Geocoder geocoder = new Geocoder(AddressListActivity.this, Locale.getDefault());
try {
return geocoder.getFromLocationName(keyword, 20);
} catch (Exception e) {
@@ -55,7 +55,7 @@ public class AdressListActivity extends AbstractListActivity {
Log.i("No geocoder available");
}
else {
- Log.e("AdressListActivity.doInBackground", e);
+ Log.e("AddressListActivity.doInBackground", e);
}
return null;
}
@@ -70,7 +70,7 @@ public class AdressListActivity extends AbstractListActivity {
}
} else {
finish();
- cgeocaches.startActivityAddress(AdressListActivity.this, null, keyword);
+ cgeocaches.startActivityAddress(AddressListActivity.this, null, keyword);
}
}
diff --git a/main/src/cgeo/geocaching/CacheCache.java b/main/src/cgeo/geocaching/CacheCache.java
index e027a8a..e70b7a0 100644
--- a/main/src/cgeo/geocaching/CacheCache.java
+++ b/main/src/cgeo/geocaching/CacheCache.java
@@ -20,10 +20,10 @@ import java.util.Set;
public class CacheCache {
private static final int MAX_CACHED_CACHES = 1000;
- final private LeastRecentlyUsedMap<String, cgCache> cachesCache;
+ final private LeastRecentlyUsedMap<String, Geocache> cachesCache;
public CacheCache() {
- cachesCache = new LeastRecentlyUsedMap.LruCache<String, cgCache>(MAX_CACHED_CACHES);
+ cachesCache = new LeastRecentlyUsedMap.LruCache<String, Geocache>(MAX_CACHED_CACHES);
cachesCache.setRemoveHandler(new CacheRemoveHandler());
}
@@ -51,7 +51,7 @@ public class CacheCache {
* Cache
*
*/
- public void putCacheInCache(final cgCache cache) {
+ public void putCacheInCache(final Geocache cache) {
if (cache == null) {
throw new IllegalArgumentException("cache must not be null");
}
@@ -69,7 +69,7 @@ public class CacheCache {
* Geocode of the cache to retrieve from the cache
* @return cache if found, null else
*/
- public cgCache getCacheFromCache(final String geocode) {
+ public Geocache getCacheFromCache(final String geocode) {
if (StringUtils.isBlank(geocode)) {
throw new IllegalArgumentException("geocode must not be empty");
}
@@ -80,14 +80,14 @@ public class CacheCache {
public synchronized Set<String> getInViewport(final Viewport viewport, final CacheType cacheType) {
final Set<String> geocodes = new HashSet<String>();
- for (final cgCache cache : cachesCache.values()) {
+ for (final Geocache cache : cachesCache.values()) {
if (cache.getCoords() == null) {
// FIXME: this kludge must be removed, it is only present to help us debug the cases where
// caches contain null coordinates.
Log.e("CacheCache.getInViewport: got cache with null coordinates: " + cache.getGeocode());
continue;
}
- if ((CacheType.ALL == cacheType || cache.getType() == cacheType) && viewport.contains(cache)) {
+ if (cacheType.contains(cache) && viewport.contains(cache)) {
geocodes.add(cache.getGeocode());
}
}
@@ -99,10 +99,10 @@ public class CacheCache {
return StringUtils.join(cachesCache.keySet(), ' ');
}
- private static class CacheRemoveHandler implements RemoveHandler<cgCache> {
+ private static class CacheRemoveHandler implements RemoveHandler<Geocache> {
@Override
- public void onRemove(final cgCache removed) {
+ public void onRemove(final Geocache removed) {
// FIXME: as above, we sometimes get caches with null coordinates, that may then provoke
// a NullPointerException down the invocation chain.
if (removed.getCoords() != null) {
diff --git a/main/src/cgeo/geocaching/CacheDetailActivity.java b/main/src/cgeo/geocaching/CacheDetailActivity.java
index 0eb13c9..f35d599 100644
--- a/main/src/cgeo/geocaching/CacheDetailActivity.java
+++ b/main/src/cgeo/geocaching/CacheDetailActivity.java
@@ -1,10 +1,10 @@
package cgeo.geocaching;
import cgeo.calendar.ICalendar;
-import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractViewPagerActivity;
import cgeo.geocaching.activity.Progress;
-import cgeo.geocaching.apps.cache.GeneralAppsFactory;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
+import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.connector.gc.GCConnector;
@@ -12,18 +12,22 @@ import cgeo.geocaching.enumerations.CacheAttribute;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.network.HtmlImage;
+import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.ui.DecryptTextClickListener;
-import cgeo.geocaching.ui.EditorDialog;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.ui.ImagesList;
import cgeo.geocaching.ui.ImagesList.ImageType;
import cgeo.geocaching.ui.LoggingUI;
+import cgeo.geocaching.ui.WeakReferenceHandler;
+import cgeo.geocaching.ui.dialog.EditorDialog;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.ClipboardUtils;
@@ -32,23 +36,26 @@ import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.HtmlUtils;
import cgeo.geocaching.utils.ImageHelper;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
+import cgeo.geocaching.utils.RunnableWithArgument;
import cgeo.geocaching.utils.TranslationUtils;
import cgeo.geocaching.utils.UnknownTagsHandler;
-import com.viewpagerindicator.TitlePageIndicator;
-import com.viewpagerindicator.TitleProvider;
-
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
import android.R.color;
import android.app.AlertDialog;
+import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
@@ -58,10 +65,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.os.Parcelable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
@@ -76,11 +79,11 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
-import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
@@ -93,17 +96,14 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.TextView.BufferType;
-import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
@@ -111,9 +111,8 @@ import java.util.regex.Pattern;
*
* e.g. details, description, logs, waypoints, inventory...
*/
-public class CacheDetailActivity extends AbstractActivity {
+public class CacheDetailActivity extends AbstractViewPagerActivity<CacheDetailActivity.Page> {
- private static final String EXTRAS_PAGE = "page";
private static final int MENU_FIELD_COPY = 1;
private static final int MENU_FIELD_TRANSLATE = 2;
private static final int MENU_FIELD_TRANSLATE_EN = 3;
@@ -130,10 +129,12 @@ public class CacheDetailActivity extends AbstractActivity {
private static final int CONTEXT_MENU_WAYPOINT_NAVIGATE = 1238;
private static final int CONTEXT_MENU_WAYPOINT_CACHES_AROUND = 1239;
private static final int CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION = 1240;
+ private static final int CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES = 1241;
private static final Pattern DARK_COLOR_PATTERN = Pattern.compile(Pattern.quote("color=\"#") + "(0[0-9]){3}" + "\"");
+ public static final String STATE_PAGE_INDEX = "cgeo.geocaching.pageIndex";
- private cgCache cache;
+ private Geocache cache;
private final Progress progress = new Progress();
private SearchResult search;
@@ -170,33 +171,6 @@ public class CacheDetailActivity extends AbstractActivity {
private int contextMenuWPIndex = -1;
/**
- * A {@link List} of all available pages.
- *
- * TODO Move to adapter
- */
- private final List<Page> pageOrder = new ArrayList<Page>();
-
- /**
- * Instances of all {@link PageViewCreator}.
- */
- private final Map<Page, PageViewCreator> viewCreators = new HashMap<Page, PageViewCreator>();
-
- /**
- * The {@link ViewPager} for this activity.
- */
- private ViewPager viewPager;
-
- /**
- * The {@link ViewPagerAdapter} for this activity.
- */
- private ViewPagerAdapter viewPagerAdapter;
-
- /**
- * The {@link TitlePageIndicator} for this activity.
- */
- private TitlePageIndicator titleIndicator;
-
- /**
* If another activity is called and can modify the data of this activity, we refresh it on resume.
*/
private boolean refreshOnResume = false;
@@ -227,8 +201,6 @@ public class CacheDetailActivity extends AbstractActivity {
setTitle(res.getString(R.string.cache));
String geocode = null;
- String guid = null;
- String name = null;
// TODO Why can it happen that search is not null? onCreate should be called only once and it is not set before.
if (search != null) {
@@ -243,16 +215,18 @@ public class CacheDetailActivity extends AbstractActivity {
final Uri uri = getIntent().getData();
// try to get data from extras
+ String name = null;
+ String guid = null;
if (geocode == null && extras != null) {
- geocode = extras.getString("geocode");
- name = extras.getString("name");
- guid = extras.getString("guid");
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
+ name = extras.getString(Intents.EXTRA_NAME);
+ guid = extras.getString(Intents.EXTRA_GUID);
}
// try to get data from URI
if (geocode == null && guid == null && uri != null) {
- String uriHost = uri.getHost().toLowerCase();
- String uriPath = uri.getPath().toLowerCase();
+ String uriHost = uri.getHost().toLowerCase(Locale.US);
+ String uriPath = uri.getPath().toLowerCase(Locale.US);
String uriQuery = uri.getQuery();
if (uriQuery != null) {
@@ -266,11 +240,11 @@ public class CacheDetailActivity extends AbstractActivity {
guid = uri.getQueryParameter("guid");
if (StringUtils.isNotBlank(geocode)) {
- geocode = geocode.toUpperCase();
+ geocode = geocode.toUpperCase(Locale.US);
guid = null;
} else if (StringUtils.isNotBlank(guid)) {
geocode = null;
- guid = guid.toLowerCase();
+ guid = guid.toLowerCase(Locale.US);
} else {
showToast(res.getString(R.string.err_detail_open));
finish();
@@ -278,7 +252,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
} else if (uriHost.contains("coord.info")) {
if (uriPath != null && uriPath.startsWith("/gc")) {
- geocode = uriPath.substring(1).toUpperCase();
+ geocode = uriPath.substring(1).toUpperCase(Locale.US);
} else {
showToast(res.getString(R.string.err_detail_open));
finish();
@@ -301,7 +275,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (StringUtils.isNotBlank(name)) {
title = name;
} else if (null != geocode && StringUtils.isNotBlank(geocode)) { // can't be null, but the compiler doesn't understand StringUtils.isNotBlank()
- title = geocode.toUpperCase();
+ title = geocode;
}
progress.show(this, title, res.getString(R.string.cache_dialog_loading_details), true, loadCacheHandler.cancelMessage());
} catch (Exception e) {
@@ -317,55 +291,34 @@ public class CacheDetailActivity extends AbstractActivity {
}
});
- // initialize ViewPager
- viewPager = (ViewPager) findViewById(R.id.viewpager);
- viewPagerAdapter = new ViewPagerAdapter();
- viewPager.setAdapter(viewPagerAdapter);
+ final int pageToOpen = savedInstanceState != null ?
+ savedInstanceState.getInt(STATE_PAGE_INDEX, 0) :
+ Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1;
+ createViewPager(pageToOpen, new OnPageSelectedListener() {
- titleIndicator = (TitlePageIndicator) findViewById(R.id.pager_indicator);
- titleIndicator.setViewPager(viewPager);
- titleIndicator.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
if (Settings.isOpenLastDetailsPage()) {
Settings.setLastDetailsPage(position);
}
// lazy loading of cache images
- if (pageOrder.get(position) == Page.IMAGES) {
+ if (getPage(position) == Page.IMAGES) {
loadCacheImages();
}
}
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- }
});
- // switch to entry page (last used or 2)
- int entryPageIndex;
- if (extras != null && extras.get(EXTRAS_PAGE) != null) {
- entryPageIndex = extras.getInt(EXTRAS_PAGE);
- }
- else {
- entryPageIndex = Settings.isOpenLastDetailsPage() ? Settings.getLastDetailsPage() : 1;
- }
- if (viewPagerAdapter.getCount() < entryPageIndex) {
- for (int i = 0; i <= entryPageIndex; i++) {
- // we can't switch to a page that is out of bounds, so we add null-pages
- pageOrder.add(null);
- }
- }
- viewPager.setCurrentItem(entryPageIndex, false);
-
// Initialization done. Let's load the data with the given information.
new LoadCacheThread(geocode, guid, loadCacheHandler).start();
}
@Override
+ public void onSaveInstanceState(final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(STATE_PAGE_INDEX, getCurrentItem());
+ }
+
+ @Override
public void onResume() {
super.onResume();
@@ -396,9 +349,10 @@ public class CacheDetailActivity extends AbstractActivity {
final int viewId = view.getId();
contextMenuWPIndex = -1;
switch (viewId) {
- case R.id.value: // coordinates
+ case R.id.value: // coordinates, gc-code, name
clickedItemText = ((TextView) view).getText();
- buildOptionsContextmenu(menu, viewId, res.getString(R.string.cache_coordinates), true);
+ String itemTitle = (String) ((TextView) ((View) view.getParent()).findViewById(R.id.name)).getText();
+ buildOptionsContextmenu(menu, viewId, itemTitle, true);
break;
case R.id.shortdesc:
clickedItemText = ((TextView) view).getText();
@@ -432,15 +386,19 @@ public class CacheDetailActivity extends AbstractActivity {
final ViewGroup parent = ((ViewGroup) view.getParent());
for (int i = 0; i < parent.getChildCount(); i++) {
if (parent.getChildAt(i) == view) {
- final List<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.getWaypoints());
+ final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints());
Collections.sort(sortedWaypoints);
- final cgWaypoint waypoint = sortedWaypoints.get(i);
+ final Waypoint waypoint = sortedWaypoints.get(i);
final int index = cache.getWaypoints().indexOf(waypoint);
menu.setHeaderTitle(res.getString(R.string.waypoint));
- menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit);
- menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate);
+ if (waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) {
+ menu.add(CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES, index, 0, R.string.waypoint_reset_cache_coords);
+ } else {
+ menu.add(CONTEXT_MENU_WAYPOINT_EDIT, index, 0, R.string.waypoint_edit);
+ menu.add(CONTEXT_MENU_WAYPOINT_DUPLICATE, index, 0, R.string.waypoint_duplicate);
+ }
contextMenuWPIndex = index;
- if (waypoint.isUserDefined()) {
+ if (waypoint.isUserDefined() && !waypoint.getWaypointType().equals(WaypointType.ORIGINAL)) {
menu.add(CONTEXT_MENU_WAYPOINT_DELETE, index, 0, R.string.waypoint_delete);
}
if (waypoint.getCoords() != null) {
@@ -512,54 +470,63 @@ public class CacheDetailActivity extends AbstractActivity {
}
break;
- case CONTEXT_MENU_WAYPOINT_EDIT: {
- final cgWaypoint waypoint = cache.getWaypoint(index);
- if (waypoint != null) {
- EditWaypointActivity.startActivityEditWaypoint(this, waypoint.getId());
+ case CONTEXT_MENU_WAYPOINT_EDIT:
+ final Waypoint waypointEdit = cache.getWaypoint(index);
+ if (waypointEdit != null) {
+ EditWaypointActivity.startActivityEditWaypoint(this, waypointEdit.getId());
refreshOnResume = true;
}
break;
- }
case CONTEXT_MENU_WAYPOINT_DUPLICATE:
- if (cache.duplicateWaypoint(index)) {
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ final Waypoint waypointDuplicate = cache.getWaypoint(index);
+ if (cache.duplicateWaypoint(waypointDuplicate)) {
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
break;
case CONTEXT_MENU_WAYPOINT_DELETE:
- if (cache.deleteWaypoint(index)) {
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ final Waypoint waypointDelete = cache.getWaypoint(index);
+ if (cache.deleteWaypoint(waypointDelete)) {
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
notifyDataSetChanged();
}
break;
- case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION: {
- final cgWaypoint waypoint = cache.getWaypoint(index);
- if (waypoint != null) {
- NavigationAppFactory.startDefaultNavigationApplication(1, this, waypoint);
+ case CONTEXT_MENU_WAYPOINT_DEFAULT_NAVIGATION:
+ final Waypoint waypointNavigation = cache.getWaypoint(index);
+ if (waypointNavigation != null) {
+ NavigationAppFactory.startDefaultNavigationApplication(1, this, waypointNavigation);
}
- }
break;
- case CONTEXT_MENU_WAYPOINT_NAVIGATE: {
- final cgWaypoint waypoint = cache.getWaypoint(contextMenuWPIndex);
- if (waypoint != null) {
- NavigationAppFactory.showNavigationMenu(this, null, waypoint, null);
+ case CONTEXT_MENU_WAYPOINT_NAVIGATE:
+ final Waypoint waypointNav = cache.getWaypoint(contextMenuWPIndex);
+ if (waypointNav != null) {
+ NavigationAppFactory.showNavigationMenu(this, null, waypointNav, null);
}
- }
break;
- case CONTEXT_MENU_WAYPOINT_CACHES_AROUND: {
- final cgWaypoint waypoint = cache.getWaypoint(index);
- if (waypoint != null) {
- cgeocaches.startActivityCoordinates(this, waypoint.getCoords());
+ case CONTEXT_MENU_WAYPOINT_CACHES_AROUND:
+ final Waypoint waypointAround = cache.getWaypoint(index);
+ if (waypointAround != null) {
+ cgeocaches.startActivityCoordinates(this, waypointAround.getCoords());
}
- }
break;
- default: {
+
+ case CONTEXT_MENU_WAYPOINT_RESET_ORIGINAL_CACHE_COORDINATES:
+ final Waypoint waypointReset = cache.getWaypoint(index);
+ if (ConnectorFactory.getConnector(cache).supportsOwnCoordinates()) {
+ createResetCacheCoordinatesDialog(cache, waypointReset).show();
+ }
+ else {
+ final ProgressDialog progressDialog = ProgressDialog.show(this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
+ final HandlerResetCoordinates handler = new HandlerResetCoordinates(this, progressDialog, false);
+ new ResetCoordsThread(cache, handler, waypointReset, true, false, progressDialog).start();
+ }
+ break;
+
+ default:
if (imagesList != null && imagesList.onContextItemSelected(item)) {
return true;
}
-
return onOptionsItemSelected(item);
- }
}
return false;
}
@@ -571,7 +538,6 @@ public class CacheDetailActivity extends AbstractActivity {
final SubMenu subMenu = menu.addSubMenu(0, 0, 0, res.getString(R.string.cache_menu_navigate)).setIcon(R.drawable.ic_menu_mapmode);
NavigationAppFactory.addMenuItems(subMenu, cache);
- GeneralAppsFactory.addMenuItems(subMenu, cache);
menu.add(0, MENU_CALENDAR, 0, res.getString(R.string.cache_menu_event)).setIcon(R.drawable.ic_menu_agenda); // add event to calendar
LoggingUI.addMenuItems(menu, cache);
@@ -584,10 +550,12 @@ public class CacheDetailActivity extends AbstractActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords());
- menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar());
- menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
- menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
+ if (cache != null) {
+ menu.findItem(MENU_DEFAULT_NAVIGATION).setVisible(null != cache.getCoords());
+ menu.findItem(MENU_CALENDAR).setVisible(cache.canBeAddedToCalendar());
+ menu.findItem(MENU_CACHES_AROUND).setVisible(null != cache.getCoords() && cache.supportsCachesAround());
+ menu.findItem(MENU_BROWSER).setVisible(cache.canOpenInBrowser());
+ }
return super.onPrepareOptionsMenu(menu);
}
@@ -595,7 +563,7 @@ public class CacheDetailActivity extends AbstractActivity {
public boolean onOptionsItemSelected(MenuItem item) {
final int menuItem = item.getItemId();
- switch(menuItem) {
+ switch (menuItem) {
case 0:
// no menu selected, but a new sub menu shown
return false;
@@ -617,16 +585,14 @@ public class CacheDetailActivity extends AbstractActivity {
return true;
}
return false;
- }
- if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
- return true;
- }
- if (GeneralAppsFactory.onMenuItemSelected(item, this, cache)) {
- return true;
- }
- if (LoggingUI.onMenuItemSelected(item, this, cache)) {
- refreshOnResume = true;
- return true;
+ default:
+ if (NavigationAppFactory.onMenuItemSelected(item, this, cache)) {
+ return true;
+ }
+ if (LoggingUI.onMenuItemSelected(item, this, cache)) {
+ refreshOnResume = true;
+ return true;
+ }
}
return true;
@@ -641,6 +607,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (search == null) {
showToast(res.getString(R.string.err_dwld_details_failed));
+ progress.dismiss();
finish();
return;
}
@@ -648,6 +615,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (search.getError() != null) {
showToast(res.getString(R.string.err_dwld_details_failed) + " " + search.getError().getErrorString(res) + ".");
+ progress.dismiss();
finish();
return;
}
@@ -689,51 +657,18 @@ public class CacheDetailActivity extends AbstractActivity {
// allow cache to notify CacheDetailActivity when it changes so it can be reloaded
cache.setChangeNotificationHandler(cacheChangeNotificationHandler);
- // notify all creators that the data has changed
- for (PageViewCreator creator : viewCreators.values()) {
- creator.notifyDataSetChanged();
- }
-
- // action bar: title and icon (default: mystery icon)
+ // action bar: title and icon
if (StringUtils.isNotBlank(cache.getName())) {
- setTitle(cache.getName() + " (" + cache.getGeocode().toUpperCase() + ')');
+ setTitle(cache.getName() + " (" + cache.getGeocode() + ')');
} else {
- setTitle(cache.getGeocode().toUpperCase());
+ setTitle(cache.getGeocode());
}
((TextView) findViewById(R.id.actionbar_title)).setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(cache.getType().markerId), null, null, null);
- // add available pages (remove old pages first)
- pageOrder.clear();
-
- pageOrder.add(Page.WAYPOINTS);
- pageOrder.add(Page.DETAILS);
- final int detailsIndex = pageOrder.size() - 1;
- pageOrder.add(Page.DESCRIPTION);
- if (cache.getLogs().isNotEmpty()) {
- pageOrder.add(Page.LOGS);
- }
- if (CollectionUtils.isNotEmpty(cache.getFriendsLogs())) {
- pageOrder.add(Page.LOGSFRIENDS);
- }
- if (CollectionUtils.isNotEmpty(cache.getInventory())) {
- pageOrder.add(Page.INVENTORY);
- }
- if (CollectionUtils.isNotEmpty(cache.getImages())) {
- pageOrder.add(Page.IMAGES);
- }
-
- // switch to details page, if we're out of bounds
- if (viewPager.getCurrentItem() < 0 || viewPager.getCurrentItem() >= viewPagerAdapter.getCount()) {
- viewPager.setCurrentItem(detailsIndex, false);
- }
-
- // notify the adapter that the data has changed
- viewPagerAdapter.notifyDataSetChanged();
-
- // notify the indicator that the data has changed
- titleIndicator.notifyDataSetChanged();
+ reinitializeViewPager();
// rendering done! remove progress popup if any there
+ invalidateOptionsMenuCompatible();
progress.dismiss();
}
@@ -752,6 +687,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) {
showToast(res.getString(R.string.err_detail_cache_forgot));
+ progress.dismiss();
finish();
return;
}
@@ -762,7 +698,7 @@ public class CacheDetailActivity extends AbstractActivity {
@Override
public void run() {
- search = cgCache.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler);
+ search = Geocache.searchByGeocode(geocode, StringUtils.isBlank(geocode) ? guid : null, 0, false, handler);
handler.sendMessage(Message.obtain());
}
}
@@ -842,14 +778,14 @@ public class CacheDetailActivity extends AbstractActivity {
}
/**
- * Tries to navigate to the {@link cgCache} of this activity.
+ * Tries to navigate to the {@link Geocache} of this activity.
*/
private void startDefaultNavigation() {
NavigationAppFactory.startDefaultNavigationApplication(1, this, cache);
}
/**
- * Tries to navigate to the {@link cgCache} of this activity.
+ * Tries to navigate to the {@link Geocache} of this activity.
*/
private void startDefaultNavigation2() {
NavigationAppFactory.startDefaultNavigationApplication(2, this, cache);
@@ -918,7 +854,8 @@ public class CacheDetailActivity extends AbstractActivity {
private void showUserActionsDialog(final CharSequence name) {
final CharSequence[] items = { res.getString(R.string.user_menu_view_hidden),
res.getString(R.string.user_menu_view_found),
- res.getString(R.string.user_menu_open_browser)
+ res.getString(R.string.user_menu_open_browser),
+ res.getString(R.string.user_menu_send_message)
};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
@@ -934,7 +871,10 @@ public class CacheDetailActivity extends AbstractActivity {
cgeocaches.startActivityUserName(CacheDetailActivity.this, name.toString());
return;
case 2:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + URLEncoder.encode(name.toString()))));
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(name.toString()))));
+ return;
+ case 3:
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(name.toString()))));
return;
default:
break;
@@ -949,7 +889,7 @@ public class CacheDetailActivity extends AbstractActivity {
if (imagesList != null) {
return;
}
- PageViewCreator creator = viewCreators.get(Page.IMAGES);
+ PageViewCreator creator = getViewCreator(Page.IMAGES);
if (creator == null) {
return;
}
@@ -957,139 +897,17 @@ public class CacheDetailActivity extends AbstractActivity {
if (imageView == null) {
return;
}
- imagesList = new ImagesList(CacheDetailActivity.this, cache.getGeocode());
+ imagesList = new ImagesList(this, cache.getGeocode());
imagesList.loadImages(imageView, cache.getImages(), ImageType.AllImages, false);
}
public static void startActivity(final Context context, final String geocode) {
final Intent detailIntent = new Intent(context, CacheDetailActivity.class);
- detailIntent.putExtra("geocode", geocode.toUpperCase());
- context.startActivity(detailIntent);
- }
-
- public static void startActivity(final Context context, final String geocode, final int page) {
- final Intent detailIntent = new Intent(context, CacheDetailActivity.class);
- detailIntent.putExtra("geocode", geocode.toUpperCase());
- detailIntent.putExtra(EXTRAS_PAGE, page);
+ detailIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
context.startActivity(detailIntent);
}
/**
- * The ViewPagerAdapter for scrolling through pages of the CacheDetailActivity.
- */
- private class ViewPagerAdapter extends PagerAdapter implements TitleProvider {
-
- @Override
- public void destroyItem(View container, int position, Object object) {
- ((ViewPager) container).removeView((View) object);
- }
-
- @Override
- public void finishUpdate(View container) {
- }
-
- @Override
- public int getCount() {
- return pageOrder.size();
- }
-
- @Override
- public Object instantiateItem(View container, int position) {
- final Page page = pageOrder.get(position);
-
- PageViewCreator creator = viewCreators.get(page);
-
- if (null == creator && null != page) {
- // The creator is not instantiated yet, let's do it.
- switch (page) {
- case DETAILS:
- creator = new DetailsViewCreator();
- break;
-
- case DESCRIPTION:
- creator = new DescriptionViewCreator();
- break;
-
- case LOGS:
- creator = new LogsViewCreator(true);
- break;
-
- case LOGSFRIENDS:
- creator = new LogsViewCreator(false);
- break;
-
- case WAYPOINTS:
- creator = new WaypointsViewCreator();
- break;
-
- case INVENTORY:
- creator = new InventoryViewCreator();
- break;
-
- case IMAGES:
- creator = new ImagesViewCreator();
- break;
- }
- viewCreators.put(page, creator);
- }
-
- View view = null;
-
- try {
- if (null != creator) {
- // Result from getView() is maybe cached, but it should be valid because the
- // creator should be informed about data-changes with notifyDataSetChanged()
- view = creator.getView();
- ((ViewPager) container).addView(view, 0);
- }
- } catch (Exception e) {
- Log.e("ViewPagerAdapter.instantiateItem ", e);
- }
-
- return view;
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return view == object;
- }
-
- @Override
- public void restoreState(Parcelable arg0, ClassLoader arg1) {
- }
-
- @Override
- public Parcelable saveState() {
- return null;
- }
-
- @Override
- public void startUpdate(View arg0) {
- }
-
- @Override
- public int getItemPosition(Object object) {
- // We are doing the caching. So pretend that the view is gone.
- // The ViewPager will get it back in instantiateItem()
- return POSITION_NONE;
- }
-
- @Override
- public String getTitle(int position) {
- final Page page = pageOrder.get(position);
- if (null == page) {
- return "";
- }
- // show number of waypoints directly in waypoint title
- if (page == Page.WAYPOINTS) {
- final int waypointCount = cache.getWaypoints().size();
- return res.getQuantityString(R.plurals.waypoints, waypointCount, waypointCount);
- }
- return res.getString(page.titleStringId);
- }
- }
-
- /**
* Enum of all possible pages with methods to get the view and a title.
*/
public enum Page {
@@ -1103,7 +921,7 @@ public class CacheDetailActivity extends AbstractActivity {
final private int titleStringId;
- private Page(final int titleStringId) {
+ Page(final int titleStringId) {
this.titleStringId = titleStringId;
}
}
@@ -1113,9 +931,7 @@ public class CacheDetailActivity extends AbstractActivity {
private ViewGroup attributeDescriptionsLayout; // layout for attribute descriptions
private boolean attributesShowAsIcons = true; // default: show icons
/**
- * True, if the cache was imported with an older version of c:geo.
- * These older versions parsed the attribute description from the tooltip in the web
- * page and put them into the DB. No icons can be matched for these.
+ * If the cache is from a non GC source, it might be without icons. Disable switching in those cases.
*/
private boolean noAttributeIconsFound = false;
private int attributeBoxMaxWidth;
@@ -1125,8 +941,7 @@ public class CacheDetailActivity extends AbstractActivity {
attributeBox.removeAllViews();
// maximum width for attribute icons is screen width - paddings of parents
- attributeBoxMaxWidth = ((WindowManager) getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay().getWidth();
+ attributeBoxMaxWidth = Compatibility.getDisplayWidth();
ViewParent child = attributeBox;
do {
if (child instanceof View) {
@@ -1233,8 +1048,8 @@ public class CacheDetailActivity extends AbstractActivity {
}
final boolean strikethru = !CacheAttribute.isEnabled(attributeName);
- final CacheAttribute attrib = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attributeName));
- if (attrib != CacheAttribute.UNKNOWN) {
+ final CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ if (attrib != null) {
noAttributeIconsFound = false;
Drawable d = res.getDrawable(attrib.drawableId);
iv.setImageDrawable(d);
@@ -1248,7 +1063,7 @@ public class CacheDetailActivity extends AbstractActivity {
fl.addView(strikethruImage);
}
} else {
- Drawable d = res.getDrawable(R.drawable.attribute_icon_not_found);
+ Drawable d = res.getDrawable(R.drawable.attribute_unknown);
iv.setImageDrawable(d);
}
@@ -1275,56 +1090,27 @@ public class CacheDetailActivity extends AbstractActivity {
for (String attributeName : cache.getAttributes()) {
final boolean enabled = CacheAttribute.isEnabled(attributeName);
// search for a translation of the attribute
- CacheAttribute attrib = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attributeName));
- if (attrib != CacheAttribute.UNKNOWN) {
- attributeName = attrib.getL10n(enabled);
+ CacheAttribute attrib = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attributeName));
+ if (attrib == null) {
+ attrib = CacheAttribute.UNKNOWN;
}
+ attributeName = attrib.getL10n(enabled);
if (buffer.length() > 0) {
buffer.append('\n');
}
buffer.append(attributeName);
}
- if (noAttributeIconsFound) {
- buffer.append("\n\n").append(res.getString(R.string.cache_attributes_no_icons));
- }
-
attribView.setText(buffer);
return descriptions;
}
}
- private interface PageViewCreator {
- /**
- * Returns a validated view.
- *
- * @return
- */
- public View getDispatchedView();
-
- /**
- * Returns a (maybe cached) view.
- *
- * @return
- */
- public View getView();
-
- /**
- * Handles changed data-sets.
- */
- public void notifyDataSetChanged();
- }
-
/**
* Creator for details-view.
*/
- private class DetailsViewCreator implements PageViewCreator {
- /**
- * The main view for this creator
- */
- private ScrollView view;
-
+ private class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
/**
* Reference to the details list, so that the helper-method can access it without an additional argument
*/
@@ -1336,22 +1122,7 @@ public class CacheDetailActivity extends AbstractActivity {
private Thread watchlistThread;
@Override
- public void notifyDataSetChanged() {
- // There is a lot of data in this view, let's update everything
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ScrollView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ScrollView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -1376,10 +1147,10 @@ public class CacheDetailActivity extends AbstractActivity {
span.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, span.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
- details.add(R.string.cache_name, span);
+ registerForContextMenu(details.add(R.string.cache_name, span));
details.add(R.string.cache_type, cache.getType().getL10n());
details.addSize(cache);
- details.add(R.string.cache_geocode, cache.getGeocode().toUpperCase());
+ registerForContextMenu(details.add(R.string.cache_geocode, cache.getGeocode()));
details.addCacheState(cache);
details.addDistance(cache, cacheDistanceView);
@@ -1389,8 +1160,10 @@ public class CacheDetailActivity extends AbstractActivity {
details.addTerrain(cache);
details.addRating(cache);
- // favourite count
- details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ // favorite count
+ if (cache.getFavoritePoints() > 0) {
+ details.add(R.string.cache_favourite, cache.getFavoritePoints() + "×");
+ }
// own rating
if (cache.getMyVote() > 0) {
@@ -1429,32 +1202,32 @@ public class CacheDetailActivity extends AbstractActivity {
if (cache.getCoords() != null) {
TextView valueView = details.add(R.string.cache_coordinates, cache.getCoords().toString());
valueView.setOnClickListener(new View.OnClickListener() {
- private int position = 0;
- private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] {
- GeopointFormatter.Format.LAT_LON_DECMINUTE,
- GeopointFormatter.Format.LAT_LON_DECSECOND,
- GeopointFormatter.Format.LAT_LON_DECDEGREE
- };
-
- // rotate coordinate formats on click
- @Override
- public void onClick(View view) {
- position = (position + 1) % availableFormats.length;
+ private int position = 0;
+ private GeopointFormatter.Format[] availableFormats = new GeopointFormatter.Format[] {
+ GeopointFormatter.Format.LAT_LON_DECMINUTE,
+ GeopointFormatter.Format.LAT_LON_DECSECOND,
+ GeopointFormatter.Format.LAT_LON_DECDEGREE
+ };
+
+ // rotate coordinate formats on click
+ @Override
+ public void onClick(View view) {
+ position = (position + 1) % availableFormats.length;
- final TextView valueView = (TextView) view.findViewById(R.id.value);
- valueView.setText(cache.getCoords().format(availableFormats[position]));
- }
- });
+ final TextView valueView = (TextView) view.findViewById(R.id.value);
+ valueView.setText(cache.getCoords().format(availableFormats[position]));
+ }
+ });
registerForContextMenu(valueView);
}
// cache attributes
- if (cache.getAttributes().isNotEmpty()) {
+ if (!cache.getAttributes().isEmpty()) {
new AttributeViewBuilder().fillView((LinearLayout) view.findViewById(R.id.attributes_innerbox));
view.findViewById(R.id.attributes_box).setVisibility(View.VISIBLE);
}
- updateOfflineBox();
+ updateOfflineBox(view, cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
// watchlist
Button buttonWatchlistAdd = (Button) view.findViewById(R.id.add_to_watchlist);
@@ -1466,23 +1239,15 @@ public class CacheDetailActivity extends AbstractActivity {
// favorite points
Button buttonFavPointAdd = (Button) view.findViewById(R.id.add_to_favpoint);
Button buttonFavPointRemove = (Button) view.findViewById(R.id.remove_from_favpoint);
- buttonFavPointAdd.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- GCConnector.addToFavorites(cache);
- updateFavPointBox();
- }
- });
- buttonFavPointRemove.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- GCConnector.removeFromFavorites(cache);
- updateFavPointBox();
- }
- });
-
+ buttonFavPointAdd.setOnClickListener(new FavoriteAddClickListener());
+ buttonFavPointRemove.setOnClickListener(new FavoriteRemoveClickListener());
updateFavPointBox();
+ // list
+ Button buttonChangeList = (Button) view.findViewById(R.id.change_list);
+ buttonChangeList.setOnClickListener(new ChangeListClickListener());
+ updateListBox();
+
// data license
IConnector connector = ConnectorFactory.getConnector(cache);
if (connector != null) {
@@ -1552,6 +1317,21 @@ public class CacheDetailActivity extends AbstractActivity {
return;
}
+ if (Settings.getChooseList()) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ storeCache(selectedListId);
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ storeCache(StoredList.TEMPORARY_LIST_ID);
+ }
+ }
+
+ protected void storeCache(int listId) {
final StoreCacheHandler storeCacheHandler = new StoreCacheHandler();
progress.show(CacheDetailActivity.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
@@ -1560,7 +1340,7 @@ public class CacheDetailActivity extends AbstractActivity {
storeThread.interrupt();
}
- storeThread = new StoreCacheThread(storeCacheHandler);
+ storeThread = new StoreCacheThread(listId, storeCacheHandler);
storeThread.start();
}
}
@@ -1587,15 +1367,17 @@ public class CacheDetailActivity extends AbstractActivity {
}
private class StoreCacheThread extends Thread {
+ final private int listId;
final private CancellableHandler handler;
- public StoreCacheThread(final CancellableHandler handler) {
+ public StoreCacheThread(final int listId, final CancellableHandler handler) {
+ this.listId = listId;
this.handler = handler;
}
@Override
public void run() {
- cache.store(handler);
+ cache.store(listId, handler);
}
}
@@ -1715,6 +1497,102 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
+ /** Thread to add this cache to the favourite list of the user */
+ private class FavoriteAddThread extends Thread {
+ private final Handler handler;
+
+ public FavoriteAddThread(Handler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public void run() {
+ handler.sendEmptyMessage(GCConnector.addToFavorites(cache) ? 1 : -1);
+ }
+ }
+
+ /** Thread to remove this cache to the favourite list of the user */
+ private class FavoriteRemoveThread extends Thread {
+ private final Handler handler;
+
+ public FavoriteRemoveThread(Handler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public void run() {
+ handler.sendEmptyMessage(GCConnector.removeFromFavorites(cache) ? 1 : -1);
+ }
+ }
+
+ private class FavoriteUpdateHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ progress.dismiss();
+ if (msg.what == -1) {
+ showToast(res.getString(R.string.err_favorite_failed));
+ } else {
+ CacheDetailActivity.this.notifyDataSetChanged(); // reload cache details
+ }
+ }
+ }
+
+ /**
+ * Listener for "add to favourites" button
+ */
+ private class FavoriteAddClickListener extends AbstractWatchlistClickListener {
+ @Override
+ public void onClick(View arg0) {
+ doExecute(R.string.cache_dialog_favourite_add_title,
+ R.string.cache_dialog_favourite_add_message,
+ new FavoriteAddThread(new FavoriteUpdateHandler()));
+ }
+ }
+
+ /**
+ * Listener for "remove from favourites" button
+ */
+ private class FavoriteRemoveClickListener extends AbstractWatchlistClickListener {
+ @Override
+ public void onClick(View arg0) {
+ doExecute(R.string.cache_dialog_favourite_remove_title,
+ R.string.cache_dialog_favourite_remove_message,
+ new FavoriteRemoveThread(new FavoriteUpdateHandler()));
+ }
+ }
+
+ /**
+ * Listener for "change list" button
+ */
+ private class ChangeListClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(View view) {
+ new StoredList.UserInterface(CacheDetailActivity.this).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ switchListById(selectedListId);
+ }
+ }, true, cache.getListId());
+ }
+ }
+
+ /**
+ * move cache to another list
+ *
+ * @param listId
+ * the ID of the list
+ */
+ public void switchListById(int listId) {
+ if (listId < 0) {
+ return;
+ }
+
+ Settings.saveLastList(listId);
+ cgData.moveToList(cache, listId);
+ updateListBox();
+ }
+
/**
* shows/hides buttons, sets text in watchlist box
*/
@@ -1729,7 +1607,7 @@ public class CacheDetailActivity extends AbstractActivity {
Button buttonRemove = (Button) view.findViewById(R.id.remove_from_watchlist);
TextView text = (TextView) view.findViewById(R.id.watchlist_text);
- if (cache.isOnWatchlist() || cache.isOwn()) {
+ if (cache.isOnWatchlist() || cache.isOwner()) {
buttonAdd.setVisibility(View.GONE);
buttonRemove.setVisibility(View.VISIBLE);
text.setText(R.string.cache_watchlist_on);
@@ -1740,7 +1618,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
// the owner of a cache has it always on his watchlist. Adding causes an error
- if (cache.isOwn()) {
+ if (cache.isOwner()) {
buttonAdd.setEnabled(false);
buttonAdd.setVisibility(View.GONE);
buttonRemove.setEnabled(false);
@@ -1756,7 +1634,7 @@ public class CacheDetailActivity extends AbstractActivity {
LinearLayout layout = (LinearLayout) view.findViewById(R.id.favpoint_box);
boolean supportsFavoritePoints = cache.supportsFavoritePoints();
layout.setVisibility(supportsFavoritePoints ? View.VISIBLE : View.GONE);
- if (!supportsFavoritePoints || cache.isOwn() || !Settings.isPremiumMember()) {
+ if (!supportsFavoritePoints || cache.isOwner() || !Settings.isPremiumMember()) {
return;
}
Button buttonAdd = (Button) view.findViewById(R.id.add_to_favpoint);
@@ -1783,6 +1661,31 @@ public class CacheDetailActivity extends AbstractActivity {
}
/**
+ * shows/hides/updates list box
+ */
+ private void updateListBox() {
+ View box = view.findViewById(R.id.list_box);
+
+ if (cache.isOffline()) {
+ // show box
+ box.setVisibility(View.VISIBLE);
+
+ // update text
+ TextView text = (TextView) view.findViewById(R.id.list_text);
+ StoredList list = cgData.getList(cache.getListId());
+ if (list != null) {
+ text.setText(res.getString(R.string.cache_list_text) + " " + list.title);
+ } else {
+ // this should not happen
+ text.setText(R.string.cache_list_unknown);
+ }
+ } else {
+ // hide box
+ box.setVisibility(View.GONE);
+ }
+ }
+
+ /**
* Handler, called when watchlist add or remove is done
*/
private class WatchlistHandler extends Handler {
@@ -1793,49 +1696,9 @@ public class CacheDetailActivity extends AbstractActivity {
if (msg.what == -1) {
showToast(res.getString(R.string.err_watchlist_failed));
} else {
- updateWatchlistBox();
- }
- }
- }
-
- private void updateOfflineBox() {
- // offline use
- final TextView offlineText = (TextView) view.findViewById(R.id.offline_text);
- final Button offlineRefresh = (Button) view.findViewById(R.id.offline_refresh);
- final Button offlineStore = (Button) view.findViewById(R.id.offline_store);
-
- if (cache.isOffline()) {
- long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
-
- String ago;
- if (diff < 15) {
- ago = res.getString(R.string.cache_offline_time_mins_few);
- } else if (diff < 50) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + diff + " " + res.getString(R.string.cache_offline_time_mins);
- } else if (diff < 90) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + res.getString(R.string.cache_offline_time_hour);
- } else if (diff < (48 * 60)) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / 60) + " " + res.getString(R.string.cache_offline_time_hours);
- } else {
- ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / (24 * 60)) + " " + res.getString(R.string.cache_offline_time_days);
+ CacheDetailActivity.this.notifyDataSetChanged(); // reload cache details
}
-
- offlineText.setText(res.getString(R.string.cache_offline_stored) + "\n" + ago);
- offlineRefresh.setOnClickListener(new RefreshCacheClickListener());
-
- offlineStore.setText(res.getString(R.string.cache_offline_drop));
- offlineStore.setClickable(true);
- offlineStore.setOnClickListener(new DropCacheClickListener());
- } else {
- offlineText.setText(res.getString(R.string.cache_offline_not_ready));
- offlineRefresh.setOnClickListener(new RefreshCacheClickListener());
-
- offlineStore.setText(res.getString(R.string.cache_offline_store));
- offlineStore.setClickable(true);
- offlineStore.setOnClickListener(new StoreCacheClickListener());
}
- offlineRefresh.setVisibility(cache.supportsRefresh() ? View.VISIBLE : View.GONE);
- offlineRefresh.setClickable(true);
}
private class PreviewMapTask extends AsyncTask<Void, Void, BitmapDrawable> {
@@ -1860,7 +1723,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private Bitmap decode(final cgCache cache) {
+ private Bitmap decode(final Geocache cache) {
return StaticMapsProvider.getPreviewMap(cache.getGeocode());
}
@@ -1870,38 +1733,26 @@ public class CacheDetailActivity extends AbstractActivity {
return;
}
- final Bitmap bitmap = image.getBitmap();
- if (bitmap == null || bitmap.getWidth() <= 10) {
- return;
- }
+ try {
+ final Bitmap bitmap = image.getBitmap();
+ if (bitmap == null || bitmap.getWidth() <= 10) {
+ return;
+ }
- ((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image);
- view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
+ ((ImageView) view.findViewById(R.id.map_preview)).setImageDrawable(image);
+ view.findViewById(R.id.map_preview_box).setVisibility(View.VISIBLE);
+ } catch (Exception e) {
+ Log.e("CacheDetailActivity.PreviewMapTask", e);
+ }
}
}
}
- private class DescriptionViewCreator implements PageViewCreator {
-
- private ScrollView view;
+ private class DescriptionViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ScrollView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ScrollView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -1948,7 +1799,7 @@ public class CacheDetailActivity extends AbstractActivity {
public void update(CharSequence editorText) {
cache.setPersonalNote(editorText.toString());
setPersonalNote(personalNoteView);
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
}
});
editor.show();
@@ -2086,7 +1937,9 @@ public class CacheDetailActivity extends AbstractActivity {
// sometimes technically incorrect.
if (unknownTagsHandler.isProblematicDetected() && descriptionView != null) {
final int startPos = description.length();
- ((Editable) description).append("\n\n").append(res.getString(R.string.cache_description_table_note));
+ final IConnector connector = ConnectorFactory.getConnector(cache);
+ final Spanned tableNote = Html.fromHtml(res.getString(R.string.cache_description_table_note, "<a href=\"" + cache.getUrl() + "\">" + connector.getName() + "</a>"));
+ ((Editable) description).append("\n\n").append(tableNote);
((Editable) description).setSpan(new StyleSpan(Typeface.ITALIC), startPos, description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
publishProgress();
}
@@ -2135,7 +1988,7 @@ public class CacheDetailActivity extends AbstractActivity {
backcolor = color.darker_gray;
}
else {
- Matcher matcher = DARK_COLOR_PATTERN.matcher(text);
+ MatcherWrapper matcher = new MatcherWrapper(DARK_COLOR_PATTERN, text);
if (matcher.find()) {
backcolor = color.darker_gray;
}
@@ -2144,31 +1997,15 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class LogsViewCreator implements PageViewCreator {
- private ListView view;
- private boolean allLogs;
+ private class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> {
+ private final boolean allLogs;
LogsViewCreator(boolean allLogs) {
- super();
this.allLogs = allLogs;
}
@Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ListView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ListView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -2187,7 +2024,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- if (sortedLogCounts.size() > 0) {
+ if (!sortedLogCounts.isEmpty()) {
// sort the log counts by type id ascending. that way the FOUND, DNF log types are the first and most visible ones
Collections.sort(sortedLogCounts, new Comparator<Entry<LogType, Integer>>() {
@@ -2208,7 +2045,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- final List<LogEntry> logs = allLogs ? cache.getLogs().asList() : cache.getFriendsLogs();
+ final List<LogEntry> logs = allLogs ? cache.getLogs() : cache.getFriendsLogs();
view.setAdapter(new ArrayAdapter<LogEntry>(CacheDetailActivity.this, R.layout.cacheview_logs_item, logs) {
final UserActionsClickListener userActionsClickListener = new UserActionsClickListener();
final DecryptTextClickListener decryptTextClickListener = new DecryptTextClickListener();
@@ -2241,7 +2078,7 @@ public class CacheDetailActivity extends AbstractActivity {
holder.count.setVisibility(View.VISIBLE);
if (log.found == -1) {
holder.count.setVisibility(View.GONE);
- } else {
+ } else {
holder.count.setText(res.getQuantityString(R.plurals.cache_counts, log.found, log.found));
}
@@ -2262,7 +2099,7 @@ public class CacheDetailActivity extends AbstractActivity {
holder.images.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<cgImage>(log.getLogImages()));
+ ImagesActivity.startActivityLogImages(CacheDetailActivity.this, cache.getGeocode(), new ArrayList<Image>(log.getLogImages()));
}
});
} else {
@@ -2270,23 +2107,12 @@ public class CacheDetailActivity extends AbstractActivity {
}
// colored marker
- holder.statusMarker.setVisibility(View.VISIBLE);
- if (log.type == LogType.FOUND_IT
- || log.type == LogType.WEBCAM_PHOTO_TAKEN
- || log.type == LogType.ATTENDED) {
- holder.statusMarker.setImageResource(R.drawable.mark_green);
- } else if (log.type == LogType.PUBLISH_LISTING
- || log.type == LogType.ENABLE_LISTING
- || log.type == LogType.OWNER_MAINTENANCE) {
- holder.statusMarker.setImageResource(R.drawable.mark_green_more);
- } else if (log.type == LogType.DIDNT_FIND_IT
- || log.type == LogType.NEEDS_MAINTENANCE
- || log.type == LogType.NEEDS_ARCHIVE) {
- holder.statusMarker.setImageResource(R.drawable.mark_red);
- } else if (log.type == LogType.TEMP_DISABLE_LISTING
- || log.type == LogType.ARCHIVE) {
- holder.statusMarker.setImageResource(R.drawable.mark_red_more);
- } else {
+ int marker = log.type.markerId;
+ if (marker != 0) {
+ holder.statusMarker.setVisibility(View.VISIBLE);
+ holder.statusMarker.setImageResource(marker);
+ }
+ else {
holder.statusMarker.setVisibility(View.GONE);
}
@@ -2326,26 +2152,10 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class WaypointsViewCreator implements PageViewCreator {
-
- private ScrollView view;
+ private class WaypointsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
@Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ScrollView) getDispatchedView();
- }
-
- return view;
- }
-
- @Override
- public View getDispatchedView() {
+ public ScrollView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -2356,10 +2166,10 @@ public class CacheDetailActivity extends AbstractActivity {
final LinearLayout waypoints = (LinearLayout) view.findViewById(R.id.waypoints);
// sort waypoints: PP, Sx, FI, OWN
- final List<cgWaypoint> sortedWaypoints = new ArrayList<cgWaypoint>(cache.getWaypoints());
+ final List<Waypoint> sortedWaypoints = new ArrayList<Waypoint>(cache.getWaypoints());
Collections.sort(sortedWaypoints);
- for (final cgWaypoint wpt : sortedWaypoints) {
+ for (final Waypoint wpt : sortedWaypoints) {
final LinearLayout waypointView = (LinearLayout) getLayoutInflater().inflate(R.layout.waypoint_item, null);
// coordinates
@@ -2441,26 +2251,10 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class InventoryViewCreator implements PageViewCreator {
-
- private ListView view;
-
- @Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = (ListView) getDispatchedView();
- }
-
- return view;
- }
+ private class InventoryViewCreator extends AbstractCachingPageViewCreator<ListView> {
@Override
- public View getDispatchedView() {
+ public ListView getDispatchedView() {
if (cache == null) {
// something is really wrong
return null;
@@ -2470,14 +2264,14 @@ public class CacheDetailActivity extends AbstractActivity {
// TODO: fix layout, then switch back to Android-resource and delete copied one
// this copy is modified to respect the text color
- view.setAdapter(new ArrayAdapter<cgTrackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory()));
+ view.setAdapter(new ArrayAdapter<Trackable>(CacheDetailActivity.this, R.layout.simple_list_item_1, cache.getInventory()));
view.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Object selection = arg0.getItemAtPosition(arg2);
- if (selection instanceof cgTrackable) {
- cgTrackable trackable = (cgTrackable) selection;
- cgeotrackable.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName());
+ if (selection instanceof Trackable) {
+ Trackable trackable = (Trackable) selection;
+ TrackableActivity.startActivity(CacheDetailActivity.this, trackable.getGuid(), trackable.getGeocode(), trackable.getName());
}
}
});
@@ -2486,23 +2280,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
}
- private class ImagesViewCreator implements PageViewCreator {
-
- private View view;
-
- @Override
- public void notifyDataSetChanged() {
- view = null;
- }
-
- @Override
- public View getView() {
- if (view == null) {
- view = getDispatchedView();
- }
-
- return view;
- }
+ private class ImagesViewCreator extends AbstractCachingPageViewCreator<View> {
@Override
public View getDispatchedView() {
@@ -2511,7 +2289,7 @@ public class CacheDetailActivity extends AbstractActivity {
}
view = getLayoutInflater().inflate(R.layout.caches_images, null);
- if (imagesList == null && viewPager.getCurrentItem() == pageOrder.indexOf(Page.IMAGES)) {
+ if (imagesList == null && isCurrentPage(Page.IMAGES)) {
loadCacheImages();
}
return view;
@@ -2520,15 +2298,240 @@ public class CacheDetailActivity extends AbstractActivity {
public static void startActivity(final Context context, final String geocode, final String cacheName) {
final Intent cachesIntent = new Intent(context, CacheDetailActivity.class);
- cachesIntent.putExtra("geocode", geocode);
- cachesIntent.putExtra("name", cacheName);
+ cachesIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
+ cachesIntent.putExtra(Intents.EXTRA_NAME, cacheName);
context.startActivity(cachesIntent);
}
public static void startActivityGuid(final Context context, final String guid, final String cacheName) {
final Intent cacheIntent = new Intent(context, CacheDetailActivity.class);
- cacheIntent.putExtra("guid", guid);
- cacheIntent.putExtra("name", cacheName);
+ cacheIntent.putExtra(Intents.EXTRA_GUID, guid);
+ cacheIntent.putExtra(Intents.EXTRA_NAME, cacheName);
context.startActivity(cacheIntent);
}
+
+ /**
+ * A dialog to allow the user to select reseting coordinates local/remote/both.
+ */
+ private AlertDialog createResetCacheCoordinatesDialog(final Geocache cache, final Waypoint wpt) {
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.waypoint_reset_cache_coords);
+
+ String[] items = new String[] {res.getString(R.string.waypoint_localy_reset_cache_coords), res.getString(R.string.waypoint_reset_local_and_remote_cache_coords)};
+ builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, final int which) {
+ dialog.dismiss();
+ final ProgressDialog progressDialog = ProgressDialog.show(CacheDetailActivity.this, getString(R.string.cache), getString(R.string.waypoint_reset), true);
+ final HandlerResetCoordinates handler = new HandlerResetCoordinates(CacheDetailActivity.this, progressDialog, which == 1);
+ new ResetCoordsThread(cache, handler, wpt, which == 0 || which == 1, which == 1, progressDialog).start();
+ }
+ });
+ return builder.create();
+ }
+
+ private static class HandlerResetCoordinates extends WeakReferenceHandler<CacheDetailActivity> {
+ private boolean remoteFinished = false;
+ private boolean localFinished = false;
+ private final ProgressDialog progressDialog;
+ private final boolean resetRemote;
+
+ protected HandlerResetCoordinates(CacheDetailActivity activity, ProgressDialog progressDialog, boolean resetRemote) {
+ super(activity);
+ this.progressDialog = progressDialog;
+ this.resetRemote = resetRemote;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == ResetCoordsThread.LOCAL) {
+ localFinished = true;
+ } else {
+ remoteFinished = true;
+ }
+
+ if (localFinished && (remoteFinished || !resetRemote)) {
+ progressDialog.dismiss();
+ final CacheDetailActivity activity = getActivity();
+ if (activity != null) {
+ activity.notifyDataSetChanged();
+ }
+ }
+ }
+
+ }
+
+ private class ResetCoordsThread extends Thread {
+
+ private final Geocache cache;
+ private final Handler handler;
+ private final boolean local;
+ private final boolean remote;
+ private final Waypoint wpt;
+ private ProgressDialog progress;
+ public static final int LOCAL = 0;
+ public static final int ON_WEBSITE = 1;
+
+ public ResetCoordsThread(Geocache cache, Handler handler, final Waypoint wpt, boolean local, boolean remote, final ProgressDialog progress) {
+ this.cache = cache;
+ this.handler = handler;
+ this.local = local;
+ this.remote = remote;
+ this.wpt = wpt;
+ this.progress = progress;
+ }
+
+ @Override
+ public void run() {
+
+ if (local) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ progress.setMessage(res.getString(R.string.waypoint_reset_cache_coords));
+ }
+ });
+ cache.setCoords(wpt.getCoords());
+ cache.setUserModifiedCoords(false);
+ cache.deleteWaypointForce(wpt);
+ cgData.saveChangedCache(cache);
+ handler.sendEmptyMessage(LOCAL);
+ }
+
+ IConnector con = ConnectorFactory.getConnector(cache);
+ if (remote && con.supportsOwnCoordinates()) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ progress.setMessage(res.getString(R.string.waypoint_coordinates_being_reset_on_website));
+ }
+ });
+
+ final boolean result = con.deleteModifiedCoordinates(cache);
+
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ if (result) {
+ showToast(getString(R.string.waypoint_coordinates_has_been_reset_on_website));
+ } else {
+ showToast(getString(R.string.waypoint_coordinates_upload_error));
+ }
+ handler.sendEmptyMessage(ON_WEBSITE);
+ notifyDataSetChanged();
+ }
+
+ });
+
+ }
+ }
+ }
+
+ @Override
+ protected String getTitle(Page page) {
+ // show number of waypoints directly in waypoint title
+ if (page == Page.WAYPOINTS) {
+ final int waypointCount = cache.getWaypoints().size();
+ return res.getQuantityString(R.plurals.waypoints, waypointCount, waypointCount);
+ }
+ return res.getString(page.titleStringId);
+ }
+
+ @Override
+ protected Pair<List<? extends Page>, Integer> getOrderedPages() {
+ final ArrayList<Page> pages = new ArrayList<Page>();
+ pages.add(Page.WAYPOINTS);
+ pages.add(Page.DETAILS);
+ final int detailsIndex = pages.size() - 1;
+ pages.add(Page.DESCRIPTION);
+ if (!cache.getLogs().isEmpty()) {
+ pages.add(Page.LOGS);
+ }
+ if (CollectionUtils.isNotEmpty(cache.getFriendsLogs())) {
+ pages.add(Page.LOGSFRIENDS);
+ }
+ if (CollectionUtils.isNotEmpty(cache.getInventory())) {
+ pages.add(Page.INVENTORY);
+ }
+ if (CollectionUtils.isNotEmpty(cache.getImages())) {
+ pages.add(Page.IMAGES);
+ }
+ return new ImmutablePair<List<? extends Page>, Integer>(pages, detailsIndex);
+ }
+
+ @Override
+ protected AbstractViewPagerActivity.PageViewCreator createViewCreator(Page page) {
+ switch (page) {
+ case DETAILS:
+ return new DetailsViewCreator();
+
+ case DESCRIPTION:
+ return new DescriptionViewCreator();
+
+ case LOGS:
+ return new LogsViewCreator(true);
+
+ case LOGSFRIENDS:
+ return new LogsViewCreator(false);
+
+ case WAYPOINTS:
+ return new WaypointsViewCreator();
+
+ case INVENTORY:
+ return new InventoryViewCreator();
+
+ case IMAGES:
+ return new ImagesViewCreator();
+
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ static void updateOfflineBox(final View view, final Geocache cache, final Resources res,
+ final OnClickListener refreshCacheClickListener,
+ final OnClickListener dropCacheClickListener,
+ final OnClickListener storeCacheClickListener) {
+ // offline use
+ final TextView offlineText = (TextView) view.findViewById(R.id.offline_text);
+ final Button offlineRefresh = (Button) view.findViewById(R.id.offline_refresh);
+ final Button offlineStore = (Button) view.findViewById(R.id.offline_store);
+
+ if (cache.isOffline()) {
+ long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
+
+ String ago;
+ if (diff < 15) {
+ ago = res.getString(R.string.cache_offline_time_mins_few);
+ } else if (diff < 50) {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + diff + " " + res.getString(R.string.cache_offline_time_mins);
+ } else if (diff < 90) {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + res.getString(R.string.cache_offline_time_hour);
+ } else if (diff < (48 * 60)) {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / 60) + " " + res.getString(R.string.cache_offline_time_hours);
+ } else {
+ ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / (24 * 60)) + " " + res.getString(R.string.cache_offline_time_days);
+ }
+
+ offlineText.setText(res.getString(R.string.cache_offline_stored) + "\n" + ago);
+ offlineRefresh.setOnClickListener(refreshCacheClickListener);
+
+ offlineStore.setText(res.getString(R.string.cache_offline_drop));
+ offlineStore.setClickable(true);
+ offlineStore.setOnClickListener(dropCacheClickListener);
+ } else {
+ offlineText.setText(res.getString(R.string.cache_offline_not_ready));
+ offlineRefresh.setOnClickListener(refreshCacheClickListener);
+
+ offlineStore.setText(res.getString(R.string.cache_offline_store));
+ offlineStore.setClickable(true);
+ offlineStore.setOnClickListener(storeCacheClickListener);
+ }
+ offlineRefresh.setVisibility(cache.supportsRefresh() ? View.VISIBLE : View.GONE);
+ offlineRefresh.setClickable(true);
+ }
+
}
diff --git a/main/src/cgeo/geocaching/CachePopup.java b/main/src/cgeo/geocaching/CachePopup.java
index e01e4a0..e6d0148 100644
--- a/main/src/cgeo/geocaching/CachePopup.java
+++ b/main/src/cgeo/geocaching/CachePopup.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.ui.CacheDetailsCreator;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.lang3.StringUtils;
@@ -15,7 +16,6 @@ import android.content.res.Configuration;
import android.os.Handler;
import android.os.Message;
import android.view.View;
-import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -79,7 +79,7 @@ public class CachePopup extends AbstractPopupActivity {
if (StringUtils.isNotBlank(cache.getName())) {
setTitle(cache.getName());
} else {
- setTitle(geocode.toUpperCase());
+ setTitle(geocode);
}
// actionbar icon
@@ -89,52 +89,11 @@ public class CachePopup extends AbstractPopupActivity {
addCacheDetails();
- findViewById(R.id.offline_box).setVisibility(View.VISIBLE);
-
// offline use
- final TextView offlineText = (TextView) findViewById(R.id.offline_text);
- final Button offlineRefresh = (Button) findViewById(R.id.offline_refresh);
- final Button offlineStore = (Button) findViewById(R.id.offline_store);
-
- if (cache.getListId() > 0) {
- final long diff = (System.currentTimeMillis() / (60 * 1000)) - (cache.getDetailedUpdate() / (60 * 1000)); // minutes
-
- String ago;
- if (diff < 15) {
- ago = res.getString(R.string.cache_offline_time_mins_few);
- } else if (diff < 50) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + diff + " " + res.getString(R.string.cache_offline_time_mins);
- } else if (diff < 90) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + res.getString(R.string.cache_offline_time_hour);
- } else if (diff < (48 * 60)) {
- ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / 60) + " " + res.getString(R.string.cache_offline_time_hours);
- } else {
- ago = res.getString(R.string.cache_offline_time_about) + " " + (diff / (24 * 60)) + " " + res.getString(R.string.cache_offline_time_days);
- }
-
- offlineText.setText(res.getString(R.string.cache_offline_stored) + "\n" + ago);
-
- offlineRefresh.setVisibility(View.VISIBLE);
- offlineRefresh.setEnabled(true);
- offlineRefresh.setOnClickListener(new RefreshCacheClickListener());
-
- offlineStore.setText(res.getString(R.string.cache_offline_drop));
- offlineStore.setEnabled(true);
- offlineStore.setOnClickListener(new DropCacheClickListener());
- } else {
- offlineText.setText(res.getString(R.string.cache_offline_not_ready));
+ CacheDetailActivity.updateOfflineBox(findViewById(android.R.id.content), cache, res, new RefreshCacheClickListener(), new DropCacheClickListener(), new StoreCacheClickListener());
- offlineRefresh.setVisibility(View.GONE);
- offlineRefresh.setEnabled(false);
- offlineRefresh.setOnTouchListener(null);
- offlineRefresh.setOnClickListener(null);
-
- offlineStore.setText(res.getString(R.string.cache_offline_store));
- offlineStore.setEnabled(true);
- offlineStore.setOnClickListener(new StoreCacheClickListener());
- }
} catch (Exception e) {
- Log.e("cgeopopup.init: " + e.toString());
+ Log.e("cgeopopup.init", e);
}
// cache is loaded. remove progress-popup if any there
@@ -156,22 +115,39 @@ public class CachePopup extends AbstractPopupActivity {
return;
}
+ if (Settings.getChooseList()) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(CachePopup.this).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ storeCache(selectedListId);
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ storeCache(StoredList.TEMPORARY_LIST_ID);
+ }
+ }
+
+ protected void storeCache(final int listId) {
final StoreCacheHandler storeCacheHandler = new StoreCacheHandler();
progress.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
- new StoreCacheThread(storeCacheHandler).start();
+ new StoreCacheThread(listId, storeCacheHandler).start();
}
}
private class StoreCacheThread extends Thread {
+ final private int listId;
final private CancellableHandler handler;
- public StoreCacheThread(final CancellableHandler handler) {
+ public StoreCacheThread(final int listId, final CancellableHandler handler) {
+ this.listId = listId;
this.handler = handler;
}
@Override
public void run() {
- cache.store(handler);
+ cache.store(listId, handler);
invalidateOptionsMenuCompatible();
}
}
@@ -237,7 +213,7 @@ public class CachePopup extends AbstractPopupActivity {
}
/**
- * Tries to navigate to the {@link cgCache} of this activity.
+ * Tries to navigate to the {@link Geocache} of this activity.
*/
@Override
protected void startDefaultNavigation2() {
@@ -251,7 +227,7 @@ public class CachePopup extends AbstractPopupActivity {
public static void startActivity(final Context context, final String geocode) {
final Intent popupIntent = new Intent(context, CachePopup.class);
- popupIntent.putExtra(EXTRA_GEOCODE, geocode);
+ popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
context.startActivity(popupIntent);
}
diff --git a/main/src/cgeo/geocaching/Destination.java b/main/src/cgeo/geocaching/Destination.java
index 441e959..10d51be 100644
--- a/main/src/cgeo/geocaching/Destination.java
+++ b/main/src/cgeo/geocaching/Destination.java
@@ -34,7 +34,13 @@ public final class Destination implements ICoordinates {
@Override
public boolean equals(final Object obj) {
- return obj != null && obj instanceof Destination && ((Destination) obj).coords.equals(coords);
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof Destination)) {
+ return false;
+ }
+ return ((Destination) obj).coords.equals(coords);
}
public long getId() {
diff --git a/main/src/cgeo/geocaching/DirectionProvider.java b/main/src/cgeo/geocaching/DirectionProvider.java
index 14fd283..c1f83ac 100644
--- a/main/src/cgeo/geocaching/DirectionProvider.java
+++ b/main/src/cgeo/geocaching/DirectionProvider.java
@@ -14,7 +14,7 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
private final SensorManager sensorManager;
- // Previous values signalled to observers to avoid resending the same value when the
+ // Previous values signaled to observers to avoid resending the same value when the
// device doesn't change orientation. The orientation is usually given with a 1 degree
// precision by Android, so it is not uncommon to obtain exactly the same value several
// times.
@@ -38,14 +38,14 @@ public class DirectionProvider extends MemorySubject<Float> implements SensorEve
@Override
public void onAccuracyChanged(final Sensor sensor, int accuracy) {
/*
- * There is a bug in Android, which appearently causes this method to be called every
- * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging
- * this event leads to the log being flooded with multiple entries _per second_,
- * which I experienced when running cgeo in a building (with GPS and network being
- * unreliable).
- *
- * See for example https://code.google.com/p/android/issues/detail?id=14792
- */
+ * There is a bug in Android, which apparently causes this method to be called every
+ * time the sensor _value_ changed, even if the _accuracy_ did not change. So logging
+ * this event leads to the log being flooded with multiple entries _per second_,
+ * which I experienced when running cgeo in a building (with GPS and network being
+ * unreliable).
+ *
+ * See for example https://code.google.com/p/android/issues/detail?id=14792
+ */
//Log.i(Settings.tag, "Compass' accuracy is low (" + accuracy + ")");
}
diff --git a/main/src/cgeo/geocaching/EditWaypointActivity.java b/main/src/cgeo/geocaching/EditWaypointActivity.java
index ef2a2cc..3c8789f 100644
--- a/main/src/cgeo/geocaching/EditWaypointActivity.java
+++ b/main/src/cgeo/geocaching/EditWaypointActivity.java
@@ -2,12 +2,16 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.IConnector;
+import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.DistanceParser;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -17,6 +21,7 @@ import org.apache.commons.lang3.StringUtils;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -28,6 +33,7 @@ import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.RadioButton;
import android.widget.Spinner;
import java.util.ArrayList;
@@ -39,7 +45,7 @@ public class EditWaypointActivity extends AbstractActivity {
private String geocode = null;
private int id = -1;
private ProgressDialog waitDialog = null;
- private cgWaypoint waypoint = null;
+ private Waypoint waypoint = null;
private Geopoint gpTemp = null;
private WaypointType type = WaypointType.OWN;
private String prefix = "OWN";
@@ -77,6 +83,8 @@ public class EditWaypointActivity extends AbstractActivity {
else {
((EditText) findViewById(R.id.note)).setText(StringUtils.trimToEmpty(waypoint.getNote()));
}
+ Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_ONLY);
+ setCoordsModificationVisibility(ConnectorFactory.getConnector(geocode), cache);
}
if (own) {
@@ -85,7 +93,7 @@ public class EditWaypointActivity extends AbstractActivity {
initializeDistanceUnitSelector();
} catch (Exception e) {
- Log.e("EditWaypointActivity.loadWaypointHandler: " + e.toString());
+ Log.e("EditWaypointActivity.loadWaypointHandler", e);
} finally {
if (waitDialog != null) {
waitDialog.dismiss();
@@ -100,15 +108,15 @@ public class EditWaypointActivity extends AbstractActivity {
super.onCreate(savedInstanceState);
setTheme();
- setContentView(R.layout.waypoint_new);
+ setContentView(R.layout.edit_waypoint_activity);
setTitle("waypoint");
// get parameters
Bundle extras = getIntent().getExtras();
if (extras != null) {
- geocode = extras.getString("geocode");
- wpCount = extras.getInt("count", 0);
- id = extras.getInt("waypoint");
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
+ wpCount = extras.getInt(Intents.EXTRA_COUNT, 0);
+ id = extras.getInt(Intents.EXTRA_WAYPOINT_ID);
}
if (StringUtils.isBlank(geocode) && id <= 0) {
@@ -133,7 +141,7 @@ public class EditWaypointActivity extends AbstractActivity {
addWaypoint.setOnClickListener(new coordsListener());
List<String> wayPointNames = new ArrayList<String>();
- for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN) {
+ for (WaypointType wpt : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
wayPointNames.add(wpt.getL10n());
}
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.name);
@@ -152,11 +160,27 @@ public class EditWaypointActivity extends AbstractActivity {
initializeWaypointTypeSelector();
}
+ if (geocode != null) {
+ Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ IConnector con = ConnectorFactory.getConnector(geocode);
+ setCoordsModificationVisibility(con, cache);
+ }
+
initializeDistanceUnitSelector();
disableSuggestions((EditText) findViewById(R.id.distance));
}
+ 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);
+ } else {
+ findViewById(R.id.modify_cache_coordinates_group).setVisibility(View.GONE);
+ findViewById(R.id.modify_cache_coordinates_local_and_remote).setVisibility(View.GONE);
+ }
+ }
+
@Override
public void onResume() {
super.onResume();
@@ -193,7 +217,7 @@ public class EditWaypointActivity extends AbstractActivity {
Spinner waypointTypeSelector = (Spinner) findViewById(R.id.type);
- wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN);
+ wpTypes = new ArrayList<WaypointType>(WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL);
ArrayAdapter<WaypointType> wpAdapter = new ArrayAdapter<WaypointType>(this, android.R.layout.simple_spinner_item, wpTypes.toArray(new WaypointType[wpTypes.size()]));
wpAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
waypointTypeSelector.setAdapter(wpAdapter);
@@ -229,7 +253,6 @@ public class EditWaypointActivity extends AbstractActivity {
final private GeoDirHandler geoDirHandler = new GeoDirHandler() {
@Override
public void updateGeoData(final IGeoData geo) {
- Log.d("EditWaypointActivity.updateLocation called");
if (geo.getCoords() == null) {
return;
}
@@ -239,8 +262,8 @@ public class EditWaypointActivity extends AbstractActivity {
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));
- } catch (Exception e) {
- Log.w("Failed to update location.");
+ } catch (final Exception e) {
+ Log.e("failed to update location", e);
}
}
};
@@ -250,11 +273,11 @@ public class EditWaypointActivity extends AbstractActivity {
@Override
public void run() {
try {
- waypoint = app.loadWaypoint(id);
+ waypoint = cgData.loadWaypoint(id);
loadWaypointHandler.sendMessage(Message.obtain());
} catch (Exception e) {
- Log.e("cgeowaypoint.loadWaypoint.run: " + e.toString());
+ Log.e("cgeowaypoint.loadWaypoint.run", e);
}
}
}
@@ -269,10 +292,10 @@ public class EditWaypointActivity extends AbstractActivity {
} else if (gpTemp != null) {
gp = gpTemp;
}
- cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
- cgeocoords coordsDialog = new cgeocoords(EditWaypointActivity.this, cache, gp, app.currentGeo());
+ Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(EditWaypointActivity.this, cache, gp, app.currentGeo());
coordsDialog.setCancelable(true);
- coordsDialog.setOnCoordinateUpdate(new cgeocoords.CoordinateUpdate() {
+ coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
public void update(final Geopoint gp) {
((Button) findViewById(R.id.buttonLatitude)).setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
@@ -288,7 +311,7 @@ public class EditWaypointActivity extends AbstractActivity {
}
}
- private class changeWaypointType implements OnItemSelectedListener {
+ private static class changeWaypointType implements OnItemSelectedListener {
private changeWaypointType(EditWaypointActivity wpView) {
this.wpView = wpView;
@@ -312,7 +335,7 @@ public class EditWaypointActivity extends AbstractActivity {
}
}
- private class changeDistanceUnit implements OnItemSelectedListener {
+ private static class changeDistanceUnit implements OnItemSelectedListener {
private changeDistanceUnit(EditWaypointActivity unitView) {
this.unitView = unitView;
@@ -331,6 +354,13 @@ public class EditWaypointActivity extends AbstractActivity {
}
}
+ public static final int SUCCESS = 0;
+ public static final int UPLOAD_START = 1;
+ public static final int UPLOAD_ERROR = 2;
+ public static final int UPLOAD_NOT_POSSIBLE = 3;
+ public static final int UPLOAD_SUCCESS = 4;
+ public static final int SAVE_ERROR = 5;
+
private class coordsListener implements View.OnClickListener {
@Override
@@ -386,53 +416,118 @@ public class EditWaypointActivity extends AbstractActivity {
coords = coords.project(bearing, distance);
}
- String name = ((EditText) findViewById(R.id.name)).getText().toString().trim();
// if no name is given, just give the waypoint its number as name
- if (name.length() == 0) {
- name = res.getString(R.string.waypoint) + " " + String.valueOf(wpCount + 1);
- }
+ final String givenName = ((EditText) findViewById(R.id.name)).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 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() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case UPLOAD_SUCCESS:
+ showToast(getString(R.string.waypoint_coordinates_has_been_modified_on_website, coordsToSave));
+ //$FALL-THROUGH$
+ case SUCCESS:
+ progress.dismiss();
+ finish();
+ break;
+ case UPLOAD_START:
+ progress.setMessage(getString(R.string.waypoint_coordinates_uploading_to_website, coordsToSave));
+ break;
+ case UPLOAD_ERROR:
+ progress.dismiss();
+ finish();
+ showToast(getString(R.string.waypoint_coordinates_upload_error));
+ break;
+ case UPLOAD_NOT_POSSIBLE:
+ progress.dismiss();
+ finish();
+ showToast(getString(R.string.waypoint_coordinates_couldnt_be_modified_on_website));
+ break;
+ case SAVE_ERROR:
+ progress.dismiss();
+ finish(); //TODO: should we close activity here ?
+ showToast(res.getString(R.string.err_waypoint_add_failed));
+ break;
+ }
+ }
+ };
+
+ class SaveWptTask extends AsyncTask<Void, Void, Void> {
- final cgWaypoint waypoint = new cgWaypoint(name, type, own);
- waypoint.setGeocode(geocode);
- waypoint.setPrefix(prefix);
- waypoint.setLookup(lookup);
- waypoint.setCoords(coords);
- waypoint.setNote(note);
- waypoint.setId(id);
-
- cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
- if (null != cache && cache.addOrChangeWaypoint(waypoint, true)) {
- app.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- StaticMapsProvider.removeWpStaticMaps(id, geocode);
- if (Settings.isStoreOfflineWpMaps()) {
- StaticMapsProvider.storeWaypointStaticMap(cache, EditWaypointActivity.this, waypoint, false);
+ @Override
+ protected Void doInBackground(Void... params) {
+ final Waypoint waypoint = new Waypoint(name, type, own);
+ waypoint.setGeocode(geocode);
+ waypoint.setPrefix(prefix);
+ waypoint.setLookup(lookup);
+ waypoint.setCoords(coordsToSave);
+ waypoint.setNote(note);
+ waypoint.setId(id);
+
+ Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ if (null != cache && cache.addOrChangeWaypoint(waypoint, true)) {
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ StaticMapsProvider.removeWpStaticMaps(id, geocode);
+ if (Settings.isStoreOfflineWpMaps()) {
+ 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);
+ origWaypoint.setCoords(cache.getCoords());
+ cache.addOrChangeWaypoint(origWaypoint, false);
+ cache.setUserModifiedCoords(true);
+ }
+ cache.setCoords(waypoint.getCoords());
+ cgData.saveChangedCache(cache);
+ }
+ if (modifyBoth.isChecked() && waypoint.getCoords() != null) {
+ finishHandler.sendEmptyMessage(UPLOAD_START);
+
+ if (cache.supportsOwnCoordinates()) {
+ boolean result = uploadModifiedCoords(cache, waypoint.getCoords());
+ finishHandler.sendEmptyMessage(result ? SUCCESS : UPLOAD_ERROR);
+ } else {
+ showToast(getString(R.string.waypoint_coordinates_couldnt_be_modified_on_website));
+ finishHandler.sendEmptyMessage(UPLOAD_NOT_POSSIBLE);
+ }
+ } else {
+ finishHandler.sendEmptyMessage(SUCCESS);
+ }
+ } else {
+ finishHandler.sendEmptyMessage(SAVE_ERROR);
+ }
+ return null;
}
- finish();
- } else {
- showToast(res.getString(R.string.err_waypoint_add_failed));
}
+ new SaveWptTask().execute();
}
}
+ private static boolean uploadModifiedCoords(final Geocache cache, final Geopoint waypointUploaded) {
+ final IConnector con = ConnectorFactory.getConnector(cache);
+ return con.supportsOwnCoordinates() && con.uploadModifiedCoordinates(cache, waypointUploaded);
+ }
+
@Override
- public void goManual(View view) {
- if (id >= 0) {
- ActivityMixin.goManual(this, "c:geo-waypoint-edit");
- } else {
- ActivityMixin.goManual(this, "c:geo-waypoint-new");
- }
+ public void goManual(final View view) {
+ ActivityMixin.goManual(this, id >= 0 ? "c:geo-waypoint-edit" : "c:geo-waypoint-new");
}
public static void startActivityEditWaypoint(final Context context, final int waypointId) {
- final Intent editIntent = new Intent(context, EditWaypointActivity.class);
- editIntent.putExtra("waypoint", waypointId);
- context.startActivity(editIntent);
+ context.startActivity(new Intent(context, EditWaypointActivity.class)
+ .putExtra(Intents.EXTRA_WAYPOINT_ID, waypointId));
}
- public static void startActivityAddWaypoint(final Context context, final cgCache cache) {
- final Intent addWptIntent = new Intent(context, EditWaypointActivity.class);
- addWptIntent.putExtra("geocode", cache.getGeocode()).putExtra("count", cache.getWaypoints().size());
- context.startActivity(addWptIntent);
+ public static void startActivityAddWaypoint(final Context context, final Geocache cache) {
+ context.startActivity(new Intent(context, EditWaypointActivity.class)
+ .putExtra(Intents.EXTRA_GEOCODE, cache.getGeocode())
+ .putExtra(Intents.EXTRA_COUNT, cache.getWaypoints().size()));
}
}
diff --git a/main/src/cgeo/geocaching/cgCache.java b/main/src/cgeo/geocaching/Geocache.java
index 7035d65..cfa66bb 100644
--- a/main/src/cgeo/geocaching/cgCache.java
+++ b/main/src/cgeo/geocaching/Geocache.java
@@ -11,6 +11,7 @@ import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.gc.GCConstants;
import cgeo.geocaching.connector.gc.Tile;
import cgeo.geocaching.enumerations.CacheAttribute;
+import cgeo.geocaching.enumerations.CacheRealm;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -27,6 +28,7 @@ import cgeo.geocaching.utils.LazyInitializedList;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
+import cgeo.geocaching.utils.MatcherWrapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -38,7 +40,6 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.text.Html;
-import android.text.Spannable;
import java.util.ArrayList;
import java.util.Calendar;
@@ -46,15 +47,15 @@ import java.util.Collections;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Internal c:geo representation of a "cache"
*/
-public class cgCache implements ICache, IWaypoint {
+public class Geocache implements ICache, IWaypoint {
private long updated = 0;
private long detailedUpdate = 0;
@@ -66,7 +67,6 @@ public class cgCache implements ICache, IWaypoint {
private String guid = "";
private CacheType cacheType = CacheType.UNKNOWN;
private String name = "";
- private Spannable nameSp = null;
private String ownerDisplayName = "";
private String ownerUserId = "";
private Date hidden = null;
@@ -89,33 +89,32 @@ public class cgCache implements ICache, IWaypoint {
private boolean premiumMembersOnly = false;
private boolean found = false;
private boolean favorite = false;
- private boolean own = false;
private int favoritePoints = 0;
private float rating = 0; // valid ratings are larger than zero
private int votes = 0;
private float myVote = 0; // valid ratings are larger than zero
private int inventoryItems = 0;
private boolean onWatchlist = false;
- private LazyInitializedList<String> attributes = new LazyInitializedList<String>() {
+ private List<String> attributes = new LazyInitializedList<String>() {
@Override
- protected List<String> loadFromDatabase() {
- return cgeoapplication.getInstance().loadAttributes(geocode);
+ public List<String> call() {
+ return cgData.loadAttributes(geocode);
}
};
- private LazyInitializedList<cgWaypoint> waypoints = new LazyInitializedList<cgWaypoint>() {
+ private List<Waypoint> waypoints = new LazyInitializedList<Waypoint>() {
@Override
- protected List<cgWaypoint> loadFromDatabase() {
- return cgeoapplication.getInstance().loadWaypoints(geocode);
+ public List<Waypoint> call() {
+ return cgData.loadWaypoints(geocode);
}
};
- private List<cgImage> spoilers = null;
- private LazyInitializedList<LogEntry> logs = new LazyInitializedList<LogEntry>() {
+ private List<Image> spoilers = null;
+ private List<LogEntry> logs = new LazyInitializedList<LogEntry>() {
@Override
- protected List<LogEntry> loadFromDatabase() {
- return cgeoapplication.getInstance().loadLogs(geocode);
+ public List<LogEntry> call() {
+ return cgData.loadLogs(geocode);
}
};
- private List<cgTrackable> inventory = null;
+ private List<Trackable> inventory = null;
private Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>();
private boolean logOffline = false;
private boolean userModifiedCoords = false;
@@ -134,7 +133,7 @@ public class cgCache implements ICache, IWaypoint {
/**
* Create a new cache. To be used everywhere except for the GPX parser
*/
- public cgCache() {
+ public Geocache() {
// empty
}
@@ -144,10 +143,10 @@ public class cgCache implements ICache, IWaypoint {
*
* @param gpxParser
*/
- public cgCache(GPXParser gpxParser) {
+ public Geocache(GPXParser gpxParser) {
setReliableLatLon(true);
setAttributes(Collections.<String> emptyList());
- setWaypoints(Collections.<cgWaypoint> emptyList(), false);
+ setWaypoints(Collections.<Waypoint> emptyList(), false);
setLogs(Collections.<LogEntry> emptyList());
}
@@ -171,7 +170,7 @@ public class cgCache implements ICache, IWaypoint {
* the other version, or null if non-existent
* @return true if this cache is "equal" to the other version
*/
- public boolean gatherMissingFrom(final cgCache other) {
+ public boolean gatherMissingFrom(final Geocache other) {
if (other == null) {
return false;
}
@@ -188,7 +187,6 @@ public class cgCache implements ICache, IWaypoint {
reliableLatLon = other.reliableLatLon;
archived = other.archived;
found = other.found;
- own = other.own;
disabled = other.disabled;
favorite = other.favorite;
onWatchlist = other.onWatchlist;
@@ -227,9 +225,6 @@ public class cgCache implements ICache, IWaypoint {
if (StringUtils.isBlank(name)) {
name = other.name;
}
- if (StringUtils.isBlank(nameSp)) {
- nameSp = other.nameSp;
- }
if (StringUtils.isBlank(ownerDisplayName)) {
ownerDisplayName = other.ownerDisplayName;
}
@@ -278,6 +273,8 @@ public class cgCache implements ICache, IWaypoint {
if (StringUtils.isBlank(description)) {
description = other.description;
}
+ // FIXME: this makes no sense to favor this over the other. 0 should not be a special case here as it is
+ // in the range of acceptable values. This is probably the case at other places (rating, votes, etc.) too.
if (favoritePoints == 0) {
favoritePoints = other.favoritePoints;
}
@@ -291,15 +288,18 @@ public class cgCache implements ICache, IWaypoint {
myVote = other.myVote;
}
if (attributes.isEmpty()) {
- attributes.set(other.attributes);
+ attributes.clear();
+ if (other.attributes != null) {
+ attributes.addAll(other.attributes);
+ }
}
if (waypoints.isEmpty()) {
- waypoints.set(other.waypoints);
+ this.setWaypoints(other.waypoints, false);
}
else {
- ArrayList<cgWaypoint> newPoints = new ArrayList<cgWaypoint>(waypoints.asList());
- cgWaypoint.mergeWayPoints(newPoints, other.getWaypoints(), false);
- waypoints.set(newPoints);
+ ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>(waypoints);
+ Waypoint.mergeWayPoints(newPoints, other.waypoints, false);
+ this.setWaypoints(newPoints, false);
}
if (spoilers == null) {
spoilers = other.spoilers;
@@ -313,14 +313,26 @@ public class cgCache implements ICache, IWaypoint {
inventoryItems = other.inventoryItems;
}
if (logs.isEmpty()) { // keep last known logs if none
- logs.set(other.logs);
+ logs.clear();
+ if (other.logs != null) {
+ logs.addAll(other.logs);
+ }
}
- if (logCounts.size() == 0) {
+ if (logCounts.isEmpty()) {
logCounts = other.logCounts;
}
- if (!userModifiedCoords) {
- userModifiedCoords = other.userModifiedCoords;
+
+ // if cache has ORIGINAL type waypoint ... it is considered that it has modified coordinates, otherwise not
+ userModifiedCoords = false;
+ if (waypoints != null) {
+ for (Waypoint wpt : waypoints) {
+ if (wpt.getWaypointType() == WaypointType.ORIGINAL) {
+ userModifiedCoords = true;
+ break;
+ }
+ }
}
+
if (!reliableLatLon) {
reliableLatLon = other.reliableLatLon;
}
@@ -328,29 +340,23 @@ public class cgCache implements ICache, IWaypoint {
zoomlevel = other.zoomlevel;
}
- boolean isEqual = isEqualTo(other);
-
- if (!isEqual) {
- notifyChange();
- }
-
- return isEqual;
+ return isEqualTo(other);
}
/**
* Compare two caches quickly. For map and list fields only the references are compared !
*
- * @param other the other cache to compare this one to
+ * @param other
+ * the other cache to compare this one to
* @return true if both caches have the same content
*/
- private boolean isEqualTo(final cgCache other) {
+ private boolean isEqualTo(final Geocache other) {
return detailed == other.detailed &&
StringUtils.equalsIgnoreCase(geocode, other.geocode) &&
StringUtils.equalsIgnoreCase(name, other.name) &&
cacheType == other.cacheType &&
size == other.size &&
found == other.found &&
- own == other.own &&
premiumMembersOnly == other.premiumMembersOnly &&
difficulty == other.difficulty &&
terrain == other.terrain &&
@@ -376,7 +382,6 @@ public class cgCache implements ICache, IWaypoint {
(direction != null ? direction.equals(other.direction) : null == other.direction) &&
(distance != null ? distance.equals(other.distance) : null == other.distance) &&
(elevation != null ? elevation.equals(other.elevation) : null == other.elevation) &&
- nameSp == other.nameSp &&
rating == other.rating &&
votes == other.votes &&
myVote == other.myVote &&
@@ -426,7 +431,7 @@ public class cgCache implements ICache, IWaypoint {
return false;
}
final Boolean found = Pattern.compile(guid, Pattern.CASE_INSENSITIVE).matcher(page).find();
- Log.i("cgCache.isGuidContainedInPage: guid '" + guid + "' " + (found ? "" : "not ") + "found");
+ Log.i("Geocache.isGuidContainedInPage: guid '" + guid + "' " + (found ? "" : "not ") + "found");
return found;
}
@@ -441,8 +446,7 @@ public class cgCache implements ICache, IWaypoint {
}
Intent logVisitIntent = new Intent((Activity) fromActivity, VisitCacheActivity.class);
logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_ID, cacheId);
- logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_GEOCODE, geocode.toUpperCase());
- logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_FOUND, found);
+ logVisitIntent.putExtra(VisitCacheActivity.EXTRAS_GEOCODE, geocode);
((Activity) fromActivity).startActivity(logVisitIntent);
}
@@ -457,13 +461,12 @@ public class cgCache implements ICache, IWaypoint {
if (logType == LogType.UNKNOWN) {
return;
}
- cgeoapplication app = (cgeoapplication) fromActivity.getApplication();
- final boolean status = app.saveLogOffline(geocode, date.getTime(), logType, log);
+ final boolean status = cgData.saveLogOffline(geocode, date.getTime(), logType, log);
Resources res = fromActivity.getResources();
if (status) {
ActivityMixin.showToast(fromActivity, res.getString(R.string.info_log_saved));
- app.saveVisitDate(geocode);
+ cgData.saveVisitDate(geocode);
logOffline = true;
notifyChange();
@@ -473,14 +476,13 @@ public class cgCache implements ICache, IWaypoint {
}
public List<LogType> getPossibleLogTypes() {
- boolean isOwner = getOwnerUserId() != null && getOwnerUserId().equalsIgnoreCase(Settings.getUsername());
- List<LogType> logTypes = new ArrayList<LogType>();
+ final List<LogType> logTypes = new LinkedList<LogType>();
if (isEventCache()) {
logTypes.add(LogType.WILL_ATTEND);
logTypes.add(LogType.NOTE);
logTypes.add(LogType.ATTENDED);
logTypes.add(LogType.NEEDS_ARCHIVE);
- if (isOwner) {
+ if (isOwner()) {
logTypes.add(LogType.ANNOUNCEMENT);
}
} else if (CacheType.WEBCAM == cacheType) {
@@ -496,7 +498,7 @@ public class cgCache implements ICache, IWaypoint {
logTypes.add(LogType.NEEDS_ARCHIVE);
logTypes.add(LogType.NEEDS_MAINTENANCE);
}
- if (isOwner) {
+ if (isOwner()) {
logTypes.add(LogType.OWNER_MAINTENANCE);
logTypes.add(LogType.TEMP_DISABLE_LISTING);
logTypes.add(LogType.ENABLE_LISTING);
@@ -538,6 +540,14 @@ public class cgCache implements ICache, IWaypoint {
return getConnector().supportsLogging();
}
+ public boolean supportsOwnCoordinates() {
+ return getConnector().supportsOwnCoordinates();
+ }
+
+ public CacheRealm getCacheRealm() {
+ return getConnector().getCacheRealm();
+ }
+
@Override
public float getDifficulty() {
return difficulty;
@@ -586,8 +596,8 @@ public class cgCache implements ICache, IWaypoint {
}
@Override
- public boolean isOwn() {
- return own;
+ public boolean isOwner() {
+ return getConnector().isOwner(this);
}
@Override
@@ -603,7 +613,7 @@ public class cgCache implements ICache, IWaypoint {
@Override
public String getDescription() {
if (description == null) {
- description = StringUtils.defaultString(cgeoapplication.getInstance().getCacheDescription(geocode));
+ description = StringUtils.defaultString(cgData.getCacheDescription(geocode));
}
return description;
}
@@ -661,7 +671,7 @@ public class cgCache implements ICache, IWaypoint {
}
StringBuilder subject = new StringBuilder("Geocache ");
- subject.append(geocode.toUpperCase());
+ subject.append(geocode);
if (StringUtils.isNotBlank(name)) {
subject.append(" - ").append(name);
}
@@ -700,7 +710,6 @@ public class cgCache implements ICache, IWaypoint {
this.favorite = favourite;
}
-
@Override
public boolean isWatchlist() {
return onWatchlist;
@@ -712,24 +721,24 @@ public class cgCache implements ICache, IWaypoint {
}
@Override
- public LazyInitializedList<String> getAttributes() {
+ public List<String> getAttributes() {
return attributes;
}
@Override
- public List<cgTrackable> getInventory() {
+ public List<Trackable> getInventory() {
return inventory;
}
- public void addSpoiler(final cgImage spoiler) {
+ public void addSpoiler(final Image spoiler) {
if (spoilers == null) {
- spoilers = new ArrayList<cgImage>();
+ spoilers = new ArrayList<Image>();
}
spoilers.add(spoiler);
}
@Override
- public List<cgImage> getSpoilers() {
+ public List<Image> getSpoilers() {
if (spoilers == null) {
return Collections.emptyList();
}
@@ -749,7 +758,7 @@ public class cgCache implements ICache, IWaypoint {
@Override
public String getNameForSorting() {
if (null == nameForSorting) {
- final Matcher matcher = NUMBER_PATTERN.matcher(name);
+ final MatcherWrapper matcher = new MatcherWrapper(NUMBER_PATTERN, name);
if (matcher.find()) {
nameForSorting = name.replace(matcher.group(), StringUtils.leftPad(matcher.group(), 6, '0'));
}
@@ -809,14 +818,6 @@ public class cgCache implements ICache, IWaypoint {
this.detailed = detailed;
}
- public Spannable getNameSp() {
- return nameSp;
- }
-
- public void setNameSp(Spannable nameSp) {
- this.nameSp = nameSp;
- }
-
public void setHidden(final Date hidden) {
if (hidden == null) {
this.hidden = null;
@@ -935,8 +936,8 @@ public class cgCache implements ICache, IWaypoint {
*
* @return always non <code>null</code>
*/
- public List<cgWaypoint> getWaypoints() {
- return waypoints.asList();
+ public List<Waypoint> getWaypoints() {
+ return waypoints;
}
/**
@@ -947,25 +948,27 @@ public class cgCache implements ICache, IWaypoint {
* called while loading or building a cache
* @return <code>true</code> if waypoints successfully added to waypoint database
*/
- public boolean setWaypoints(List<cgWaypoint> waypoints, boolean saveToDatabase) {
- this.waypoints.set(waypoints);
+ public boolean setWaypoints(List<Waypoint> waypoints, boolean saveToDatabase) {
+ this.waypoints.clear();
+ if (waypoints != null) {
+ this.waypoints.addAll(waypoints);
+ }
finalDefined = false;
if (waypoints != null) {
- for (cgWaypoint waypoint : waypoints) {
+ for (Waypoint waypoint : waypoints) {
waypoint.setGeocode(geocode);
if (waypoint.isFinalWithCoords()) {
finalDefined = true;
}
}
}
-
- return saveToDatabase && cgeoapplication.getInstance().saveWaypoints(this);
+ return saveToDatabase && cgData.saveWaypoints(this);
}
/**
* @return never <code>null</code>
*/
- public LazyInitializedList<LogEntry> getLogs() {
+ public List<LogEntry> getLogs() {
return logs;
}
@@ -987,7 +990,10 @@ public class cgCache implements ICache, IWaypoint {
* the log entries
*/
public void setLogs(List<LogEntry> logs) {
- this.logs.set(logs);
+ this.logs.clear();
+ if (logs != null) {
+ this.logs.addAll(logs);
+ }
}
public boolean isLogOffline() {
@@ -1015,7 +1021,7 @@ public class cgCache implements ICache, IWaypoint {
}
public void setGeocode(String geocode) {
- this.geocode = geocode;
+ this.geocode = StringUtils.upperCase(geocode);
}
public void setCacheId(String cacheId) {
@@ -1079,19 +1085,18 @@ public class cgCache implements ICache, IWaypoint {
this.found = found;
}
- public void setOwn(boolean own) {
- this.own = own;
- }
-
public void setAttributes(List<String> attributes) {
- this.attributes.set(attributes);
+ this.attributes.clear();
+ if (attributes != null) {
+ this.attributes.addAll(attributes);
+ }
}
- public void setSpoilers(List<cgImage> spoilers) {
+ public void setSpoilers(List<Image> spoilers) {
this.spoilers = spoilers;
}
- public void setInventory(List<cgTrackable> inventory) {
+ public void setInventory(List<Trackable> inventory) {
this.inventory = inventory;
}
@@ -1149,10 +1154,10 @@ public class cgCache implements ICache, IWaypoint {
* called while loading or building a cache
* @return <code>true</code> if waypoint successfully added to waypoint database
*/
- public boolean addOrChangeWaypoint(final cgWaypoint waypoint, boolean saveToDatabase) {
+ public boolean addOrChangeWaypoint(final Waypoint waypoint, boolean saveToDatabase) {
waypoint.setGeocode(geocode);
- if (waypoint.getId() <= 0) { // this is a new waypoint
+ if (waypoint.getId() < 0) { // this is a new waypoint
waypoints.add(waypoint);
if (waypoint.isFinalWithCoords()) {
finalDefined = true;
@@ -1166,8 +1171,7 @@ public class cgCache implements ICache, IWaypoint {
// when waypoint was edited, finalDefined may have changed
resetFinalDefined();
}
-
- return saveToDatabase && cgeoapplication.getInstance().saveWaypoint(waypoint.getId(), geocode, waypoint);
+ return saveToDatabase && cgData.saveWaypoint(waypoint.getId(), geocode, waypoint);
}
public boolean hasWaypoints() {
@@ -1188,7 +1192,7 @@ public class cgCache implements ICache, IWaypoint {
*/
private void resetFinalDefined() {
finalDefined = false;
- for (cgWaypoint wp : waypoints) {
+ for (Waypoint wp : waypoints) {
if (wp.isFinalWithCoords()) {
finalDefined = true;
break;
@@ -1201,43 +1205,47 @@ public class cgCache implements ICache, IWaypoint {
}
public void setUserModifiedCoords(boolean coordsChanged) {
- this.userModifiedCoords = coordsChanged;
+ userModifiedCoords = coordsChanged;
}
/**
* Duplicate a waypoint.
*
- * @param index the waypoint to duplicate
+ * @param original
+ * the waypoint to duplicate
* @return <code>true</code> if the waypoint was duplicated, <code>false</code> otherwise (invalid index)
*/
- public boolean duplicateWaypoint(final int index) {
- final cgWaypoint original = getWaypoint(index);
+ public boolean duplicateWaypoint(final Waypoint original) {
if (original == null) {
return false;
}
- final cgWaypoint copy = new cgWaypoint(original);
+ final int index = getWaypointIndex(original);
+ final Waypoint copy = new Waypoint(original);
copy.setUserDefined();
copy.setName(cgeoapplication.getInstance().getString(R.string.waypoint_copy_of) + " " + copy.getName());
waypoints.add(index + 1, copy);
- return cgeoapplication.getInstance().saveWaypoint(-1, geocode, copy);
+ return cgData.saveWaypoint(-1, geocode, copy);
}
/**
* delete a user defined waypoint
*
- * @param index
- * of the waypoint in cache's waypoint list
+ * @param waypoint
+ * to be removed from cache
* @return <code>true</code>, if the waypoint was deleted
*/
- public boolean deleteWaypoint(final int index) {
- final cgWaypoint waypoint = getWaypoint(index);
+ public boolean deleteWaypoint(final Waypoint waypoint) {
if (waypoint == null) {
return false;
}
+ if (waypoint.getId() < 0) {
+ return false;
+ }
if (waypoint.isUserDefined()) {
+ final int index = getWaypointIndex(waypoint);
waypoints.remove(index);
- cgeoapplication.getInstance().deleteWaypoint(waypoint.getId());
- cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ cgData.deleteWaypoint(waypoint.getId());
+ cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
// Check status if Final is defined
if (waypoint.isFinalWithCoords()) {
resetFinalDefined();
@@ -1248,19 +1256,17 @@ public class cgCache implements ICache, IWaypoint {
}
/**
- * delete a user defined waypoint
+ * deletes any waypoint
*
* @param waypoint
- * to be removed from cache
- * @return <code>true</code>, if the waypoint was deleted
*/
- public boolean deleteWaypoint(final cgWaypoint waypoint) {
- if (waypoint.getId() <= 0) {
- return false;
- }
+ public void deleteWaypointForce(Waypoint waypoint) {
final int index = getWaypointIndex(waypoint);
- return index >= 0 && deleteWaypoint(index);
+ waypoints.remove(index);
+ cgData.deleteWaypoint(waypoint.getId());
+ cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ resetFinalDefined();
}
/**
@@ -1270,7 +1276,7 @@ public class cgCache implements ICache, IWaypoint {
* to find index for
* @return index in <code>waypoints</code> if found, -1 otherwise
*/
- private int getWaypointIndex(final cgWaypoint waypoint) {
+ private int getWaypointIndex(final Waypoint waypoint) {
final int id = waypoint.getId();
for (int index = 0; index < waypoints.size(); index++) {
if (waypoints.get(index).getId() == id) {
@@ -1283,21 +1289,23 @@ public class cgCache implements ICache, IWaypoint {
/**
* Retrieve a given waypoint.
*
- * @param index the index of the waypoint
+ * @param index
+ * the index of the waypoint
* @return waypoint or <code>null</code> if index is out of range
*/
- public cgWaypoint getWaypoint(final int index) {
+ public Waypoint getWaypoint(final int index) {
return index >= 0 && index < waypoints.size() ? waypoints.get(index) : null;
}
/**
* Lookup a waypoint by its id.
*
- * @param id the id of the waypoint to look for
+ * @param id
+ * the id of the waypoint to look for
* @return waypoint or <code>null</code>
*/
- public cgWaypoint getWaypointById(final int id) {
- for (final cgWaypoint waypoint : waypoints) {
+ public Waypoint getWaypointById(final int id) {
+ for (final Waypoint waypoint : waypoints) {
if (waypoint.getId() == id) {
return waypoint;
}
@@ -1313,14 +1321,14 @@ public class cgCache implements ICache, IWaypoint {
final Pattern coordPattern = Pattern.compile("\\b[nNsS]{1}\\s*\\d"); // begin of coordinates
int count = 1;
String note = getPersonalNote();
- Matcher matcher = coordPattern.matcher(note);
+ MatcherWrapper matcher = new MatcherWrapper(coordPattern, note);
while (matcher.find()) {
try {
final Geopoint point = new Geopoint(note.substring(matcher.start()));
// 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 cgWaypoint waypoint = new cgWaypoint(name, WaypointType.WAYPOINT, false);
+ final Waypoint waypoint = new Waypoint(name, WaypointType.WAYPOINT, false);
waypoint.setCoords(point);
addOrChangeWaypoint(waypoint, false);
count++;
@@ -1330,10 +1338,10 @@ public class cgCache implements ICache, IWaypoint {
}
note = note.substring(matcher.start() + 1);
- matcher = coordPattern.matcher(note);
+ matcher = new MatcherWrapper(coordPattern, note);
}
} catch (Exception e) {
- Log.e("cgCache.parseWaypointsFromNote: " + e.toString());
+ Log.e("Geocache.parseWaypointsFromNote", e);
}
}
@@ -1358,16 +1366,22 @@ public class cgCache implements ICache, IWaypoint {
if (this == obj) {
return true;
}
- if (!(obj instanceof cgCache)) {
+ if (!(obj instanceof Geocache)) {
return false;
}
// just compare the geocode even if that is not what "equals" normally does
- return StringUtils.isNotBlank(geocode) && geocode.equals(((cgCache) obj).geocode);
+ return StringUtils.isNotBlank(geocode) && geocode.equals(((Geocache) obj).geocode);
}
public void store(CancellableHandler handler) {
- final int listId = Math.max(getListId(), StoredList.STANDARD_LIST_ID);
- storeCache(this, null, listId, false, handler);
+ store(StoredList.TEMPORARY_LIST_ID, handler);
+ }
+
+ public void store(final int listId, CancellableHandler handler) {
+ int newListId = listId < StoredList.STANDARD_LIST_ID
+ ? Math.max(getListId(), StoredList.STANDARD_LIST_ID)
+ : listId;
+ storeCache(this, null, newListId, false, handler);
}
public void setZoomlevel(int zoomlevel) {
@@ -1391,8 +1405,8 @@ public class cgCache implements ICache, IWaypoint {
public void drop(Handler handler) {
try {
- cgeoapplication.getInstance().markDropped(Collections.singletonList(this));
- cgeoapplication.getInstance().removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ cgData.markDropped(Collections.singletonList(this));
+ cgData.removeCache(getGeocode(), EnumSet.of(RemoveFlag.REMOVE_CACHE));
handler.sendMessage(Message.obtain());
} catch (Exception e) {
@@ -1402,54 +1416,54 @@ public class cgCache implements ICache, IWaypoint {
public void checkFields() {
if (StringUtils.isBlank(getGeocode())) {
- Log.e("geo code not parsed correctly");
+ Log.w("geo code not parsed correctly for " + geocode);
}
if (StringUtils.isBlank(getName())) {
- Log.e("name not parsed correctly");
+ Log.w("name not parsed correctly for " + geocode);
}
if (StringUtils.isBlank(getGuid())) {
- Log.e("guid not parsed correctly");
+ Log.w("guid not parsed correctly for " + geocode);
}
if (getTerrain() == 0.0) {
- Log.e("terrain not parsed correctly");
+ Log.w("terrain not parsed correctly for " + geocode);
}
if (getDifficulty() == 0.0) {
- Log.e("difficulty not parsed correctly");
+ Log.w("difficulty not parsed correctly for " + geocode);
}
if (StringUtils.isBlank(getOwnerDisplayName())) {
- Log.e("owner display name not parsed correctly");
+ Log.w("owner display name not parsed correctly for " + geocode);
}
if (StringUtils.isBlank(getOwnerUserId())) {
- Log.e("owner user id real not parsed correctly");
+ Log.w("owner user id real not parsed correctly for " + geocode);
}
if (getHiddenDate() == null) {
- Log.e("hidden not parsed correctly");
+ Log.w("hidden not parsed correctly for " + geocode);
}
if (getFavoritePoints() < 0) {
- Log.e("favoriteCount not parsed correctly");
+ Log.w("favoriteCount not parsed correctly for " + geocode);
}
if (getSize() == null) {
- Log.e("size not parsed correctly");
+ Log.w("size not parsed correctly for " + geocode);
}
if (getType() == null || getType() == CacheType.UNKNOWN) {
- Log.e("type not parsed correctly");
+ Log.w("type not parsed correctly for " + geocode);
}
if (getCoords() == null) {
- Log.e("coordinates not parsed correctly");
+ Log.w("coordinates not parsed correctly for " + geocode);
}
if (StringUtils.isBlank(getLocation())) {
- Log.e("location not parsed correctly");
+ Log.w("location not parsed correctly for " + geocode);
}
}
public void refresh(int newListId, CancellableHandler handler) {
- cgeoapplication.getInstance().removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
storeCache(null, geocode, newListId, true, handler);
}
- public static void storeCache(cgCache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) {
+ public static void storeCache(Geocache origCache, String geocode, int listId, boolean forceRedownload, CancellableHandler handler) {
try {
- cgCache cache;
+ Geocache cache;
// get cache details, they may not yet be complete
if (origCache != null) {
// only reload the cache if it was already stored or doesn't have full details (by checking the description)
@@ -1491,7 +1505,7 @@ public class cgCache implements ICache, IWaypoint {
// store spoilers
if (CollectionUtils.isNotEmpty(cache.getSpoilers())) {
- for (cgImage oneSpoiler : cache.getSpoilers()) {
+ for (Image oneSpoiler : cache.getSpoilers()) {
imgGetter.getDrawable(oneSpoiler.getUrl());
}
}
@@ -1504,7 +1518,7 @@ public class cgCache implements ICache, IWaypoint {
if (Settings.isStoreLogImages()) {
for (LogEntry log : cache.getLogs()) {
if (log.hasLogImages()) {
- for (cgImage oneLogImg : log.getLogImages()) {
+ for (Image oneLogImg : log.getLogImages()) {
imgGetter.getDrawable(oneLogImg.getUrl());
}
}
@@ -1516,7 +1530,7 @@ public class cgCache implements ICache, IWaypoint {
}
cache.setListId(listId);
- cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
if (CancellableHandler.isCancelled(handler)) {
return;
@@ -1534,14 +1548,13 @@ public class cgCache implements ICache, IWaypoint {
public static SearchResult searchByGeocode(final String geocode, final String guid, final int listId, final boolean forceReload, final CancellableHandler handler) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) {
- Log.e("cgCache.searchByGeocode: No geocode nor guid given");
+ Log.e("Geocache.searchByGeocode: No geocode nor guid given");
return null;
}
- final cgeoapplication app = cgeoapplication.getInstance();
- if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (app.isOffline(geocode, guid) || app.isThere(geocode, guid, true, true))) {
+ if (!forceReload && listId == StoredList.TEMPORARY_LIST_ID && (cgData.isOffline(geocode, guid) || cgData.isThere(geocode, guid, true, true))) {
final SearchResult search = new SearchResult();
- final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : app.getGeocode(guid);
+ final String realGeocode = StringUtils.isNotBlank(geocode) ? geocode : cgData.getGeocodeForGuid(guid);
search.addGeocode(realGeocode);
return search;
}
@@ -1573,7 +1586,7 @@ public class cgCache implements ICache, IWaypoint {
}
// 12:34
final Pattern time = Pattern.compile("\\b(\\d{1,2})\\:(\\d\\d)\\b");
- final Matcher matcher = time.matcher(getDescription());
+ final MatcherWrapper matcher = new MatcherWrapper(time, getDescription());
while (matcher.find()) {
try {
final int hours = Integer.valueOf(matcher.group(1));
@@ -1589,7 +1602,7 @@ public class cgCache implements ICache, IWaypoint {
final String hourLocalized = cgeoapplication.getInstance().getString(R.string.cache_time_full_hours);
if (StringUtils.isNotBlank(hourLocalized)) {
final Pattern fullHours = Pattern.compile("\\b(\\d{1,2})\\s+" + Pattern.quote(hourLocalized), Pattern.CASE_INSENSITIVE);
- final Matcher matcherHours = fullHours.matcher(getDescription());
+ final MatcherWrapper matcherHours = new MatcherWrapper(fullHours, getDescription());
if (matcherHours.find()) {
try {
final int hours = Integer.valueOf(matcherHours.group(1));
@@ -1613,8 +1626,7 @@ public class cgCache implements ICache, IWaypoint {
* @return
*/
public boolean hasAttribute(CacheAttribute attribute, boolean yes) {
- // lazy loading of attributes
- cgCache fullCache = cgeoapplication.getInstance().loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
+ Geocache fullCache = cgData.loadCache(getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
if (fullCache == null) {
fullCache = this;
}
@@ -1625,12 +1637,32 @@ public class cgCache implements ICache, IWaypoint {
return StaticMapsProvider.hasStaticMap(this);
}
- public List<cgImage> getImages() {
- List<cgImage> result = new ArrayList<cgImage>();
+ public List<Image> getImages() {
+ List<Image> result = new ArrayList<Image>();
result.addAll(getSpoilers());
for (LogEntry log : getLogs()) {
result.addAll(log.getLogImages());
}
return result;
}
+
+ public void setDetailedUpdatedNow() {
+ final long now = System.currentTimeMillis();
+ setUpdated(now);
+ setDetailedUpdate(now);
+ setDetailed(true);
+ }
+
+ /**
+ * Gets whether the user has logged the specific log type for this cache. Only checks the currently stored logs of
+ * the cache, so the result might be wrong.
+ */
+ public boolean hasOwnLog(LogType logType) {
+ for (LogEntry logEntry : getLogs()) {
+ if (logEntry.type == logType && logEntry.isOwn()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/main/src/cgeo/geocaching/ICache.java b/main/src/cgeo/geocaching/ICache.java
index 8f8baf9..c852d05 100644
--- a/main/src/cgeo/geocaching/ICache.java
+++ b/main/src/cgeo/geocaching/ICache.java
@@ -28,7 +28,7 @@ public interface ICache extends IBasicCache {
/**
* @return true if the user is the owner of the cache, false else
*/
- public boolean isOwn();
+ public boolean isOwner();
/**
* @return true is the cache is archived, false else
@@ -107,17 +107,17 @@ public interface ICache extends IBasicCache {
*
* @return the list of attributes for this cache
*/
- public LazyInitializedList<String> getAttributes();
+ public List<String> getAttributes();
/**
* @return the list of trackables in this cache
*/
- public List<cgTrackable> getInventory();
+ public List<Trackable> getInventory();
/**
* @return the list of spoiler images
*/
- public List<cgImage> getSpoilers();
+ public List<Image> getSpoilers();
/**
* @return a statistic how often the caches has been found, disabled, archived etc.
diff --git a/main/src/cgeo/geocaching/IWaypoint.java b/main/src/cgeo/geocaching/IWaypoint.java
index 78e3b43..2b992e1 100644
--- a/main/src/cgeo/geocaching/IWaypoint.java
+++ b/main/src/cgeo/geocaching/IWaypoint.java
@@ -1,12 +1,14 @@
-/**
- *
- */
package cgeo.geocaching;
import cgeo.geocaching.enumerations.WaypointType;
public interface IWaypoint extends ILogable, ICoordinates {
+ /**
+ * Return an unique waypoint id.
+ *
+ * @return a non-negative id if set, -1 if unset
+ */
public abstract int getId();
public abstract WaypointType getWaypointType();
diff --git a/main/src/cgeo/geocaching/cgImage.java b/main/src/cgeo/geocaching/Image.java
index b313ef5..22c76aa 100644
--- a/main/src/cgeo/geocaching/cgImage.java
+++ b/main/src/cgeo/geocaching/Image.java
@@ -8,22 +8,22 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-public class cgImage implements Parcelable {
+public class Image implements Parcelable {
private final String url;
private final String title;
private final String description;
- public cgImage(final String url, final String title, final String description) {
+ public Image(final String url, final String title, final String description) {
this.url = url;
this.title = title;
this.description = description;
}
- public cgImage(final String url, final String title) {
+ public Image(final String url, final String title) {
this(url, title, null);
}
- public cgImage(final Parcel in) {
+ public Image(final Parcel in) {
url = in.readString();
title = in.readString();
description = in.readString();
@@ -41,15 +41,15 @@ public class cgImage implements Parcelable {
dest.writeString(description);
}
- public static final Parcelable.Creator<cgImage> CREATOR = new Parcelable.Creator<cgImage>() {
+ public static final Parcelable.Creator<Image> CREATOR = new Parcelable.Creator<Image>() {
@Override
- public cgImage createFromParcel(Parcel in) {
- return new cgImage(in);
+ public Image createFromParcel(Parcel in) {
+ return new Image(in);
}
@Override
- public cgImage[] newArray(int size) {
- return new cgImage[size];
+ public Image[] newArray(int size) {
+ return new Image[size];
}
};
diff --git a/main/src/cgeo/geocaching/ImagesActivity.java b/main/src/cgeo/geocaching/ImagesActivity.java
index 0accf12..24f699e 100644
--- a/main/src/cgeo/geocaching/ImagesActivity.java
+++ b/main/src/cgeo/geocaching/ImagesActivity.java
@@ -24,11 +24,10 @@ public class ImagesActivity extends AbstractActivity {
private static final String EXTRAS_GEOCODE = "geocode";
private boolean offline;
- private ArrayList<cgImage> imageNames;
+ private ArrayList<Image> imageNames;
private ImagesList imagesList;
private ImageType imgType = ImageType.SpoilerImages;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -62,7 +61,7 @@ public class ImagesActivity extends AbstractActivity {
return;
}
- offline = app.isOffline(geocode, null) && (imgType == ImageType.SpoilerImages || Settings.isStoreLogImages());
+ offline = cgData.isOffline(geocode, null) && (imgType == ImageType.SpoilerImages || Settings.isStoreLogImages());
}
@Override
@@ -78,24 +77,24 @@ public class ImagesActivity extends AbstractActivity {
super.onStop();
}
- public static void startActivityLogImages(final Context fromActivity, final String geocode, List<cgImage> logImages) {
+ public static void startActivityLogImages(final Context fromActivity, final String geocode, List<Image> logImages) {
startActivity(fromActivity, geocode, logImages, ImageType.LogImages);
}
- private static void startActivity(final Context fromActivity, final String geocode, List<cgImage> logImages, ImageType imageType) {
+ private static void startActivity(final Context fromActivity, final String geocode, List<Image> logImages, ImageType imageType) {
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.toUpperCase())
+ .putExtra(EXTRAS_GEOCODE, geocode)
.putExtra(EXTRAS_TYPE, imageType);
// avoid forcing the array list as parameter type
- final ArrayList<cgImage> arrayList = new ArrayList<cgImage>(logImages);
+ final ArrayList<Image> arrayList = new ArrayList<Image>(logImages);
logImgIntent.putParcelableArrayListExtra(EXTRAS_IMAGES, arrayList);
fromActivity.startActivity(logImgIntent);
}
- public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<cgImage> spoilers) {
+ public static void startActivitySpoilerImages(final Context fromActivity, String geocode, List<Image> spoilers) {
startActivity(fromActivity, geocode, spoilers, ImageType.SpoilerImages);
}
diff --git a/main/src/cgeo/geocaching/Intents.java b/main/src/cgeo/geocaching/Intents.java
new file mode 100644
index 0000000..07e1c13
--- /dev/null
+++ b/main/src/cgeo/geocaching/Intents.java
@@ -0,0 +1,28 @@
+package cgeo.geocaching;
+
+public class Intents {
+
+ private Intents() {
+ // Do not instantiate
+ }
+
+ 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_COUNT = PREFIX + "count";
+ public static final String EXTRA_GEOCODE = PREFIX + "geocode";
+ public static final String EXTRA_GUID = PREFIX + "guid";
+ 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";
+ public static final String EXTRA_LIST_ID = PREFIX + "list_id";
+ public static final String EXTRA_LIST_TYPE = PREFIX + "list_type";
+ public static final String EXTRA_MAP_FILE = PREFIX + "map_file";
+ public static final String EXTRA_NAME = PREFIX + "name";
+ 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_USERNAME = PREFIX + "username";
+ public static final String EXTRA_WAYPOINT_ID = PREFIX + "waypoint_id";
+}
diff --git a/main/src/cgeo/geocaching/LiveMapInfo.java b/main/src/cgeo/geocaching/LiveMapInfo.java
deleted file mode 100644
index 2fee940..0000000
--- a/main/src/cgeo/geocaching/LiveMapInfo.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package cgeo.geocaching;
-
-import cgeo.geocaching.activity.AbstractActivity;
-
-import android.os.Bundle;
-import android.view.View;
-import android.widget.Button;
-import android.widget.CheckBox;
-
-public class LiveMapInfo extends AbstractActivity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.livemapinfo);
-
- final int showCount = Settings.getLiveMapHintShowCount();
-
- if (showCount > 2) {
- final CheckBox cb = (CheckBox) findViewById(R.id.live_map_hint_hide);
- cb.setVisibility(View.VISIBLE);
- }
-
- final Button closeButton = (Button) findViewById(R.id.live_map_hint_ok);
- closeButton.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- final CheckBox cb = (CheckBox) findViewById(R.id.live_map_hint_hide);
- if (cb.isChecked()) {
- Settings.setHideLiveHint(true);
- }
- finish();
- }
- });
-
- Settings.setLiveMapHintShowCount(showCount + 1);
- }
-
- @Override
- protected void onStop() {
-
- final CheckBox cb = (CheckBox) findViewById(R.id.live_map_hint_hide);
- if (cb.isChecked()) {
- Settings.setHideLiveHint(true);
- }
-
- super.onStop();
- }
-
-}
diff --git a/main/src/cgeo/geocaching/LogEntry.java b/main/src/cgeo/geocaching/LogEntry.java
index b625bb5..df1038f 100644
--- a/main/src/cgeo/geocaching/LogEntry.java
+++ b/main/src/cgeo/geocaching/LogEntry.java
@@ -2,6 +2,7 @@ package cgeo.geocaching;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.utils.DateUtils;
+import cgeo.geocaching.utils.MatcherWrapper;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -10,7 +11,6 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class LogEntry {
@@ -25,7 +25,7 @@ public final class LogEntry {
public int found = -1;
/** Friend's log entry */
public boolean friend = false;
- private List<cgImage> logImages = null;
+ private List<Image> logImages = null;
public String cacheName = ""; // used for trackables
public String cacheGuid = ""; // used for trackables
@@ -64,9 +64,9 @@ public final class LogEntry {
log.compareTo(otherLog.log) == 0;
}
- public void addLogImage(final cgImage image) {
+ public void addLogImage(final Image image) {
if (logImages == null) {
- logImages = new ArrayList<cgImage>();
+ logImages = new ArrayList<Image>();
}
logImages.add(image);
}
@@ -74,7 +74,7 @@ public final class LogEntry {
/**
* @return the log images or an empty list, never <code>null</code>
*/
- public List<cgImage> getLogImages() {
+ public List<Image> getLogImages() {
if (logImages == null) {
return Collections.emptyList();
}
@@ -87,7 +87,7 @@ public final class LogEntry {
public CharSequence getImageTitles() {
final List<String> titles = new ArrayList<String>(5);
- for (cgImage image : getLogImages()) {
+ for (Image image : getLogImages()) {
if (StringUtils.isNotBlank(image.getTitle())) {
titles.add(image.getTitle());
}
@@ -107,9 +107,13 @@ public final class LogEntry {
*/
public String getDisplayText() {
if (Settings.getPlainLogs()) {
- Matcher matcher = PATTERN_REMOVE_COLORS.matcher(log);
+ MatcherWrapper matcher = new MatcherWrapper(PATTERN_REMOVE_COLORS, log);
return matcher.replaceAll("");
}
return log;
}
+
+ public boolean isOwn() {
+ return author.equalsIgnoreCase(Settings.getUsername());
+ }
}
diff --git a/main/src/cgeo/geocaching/LogTrackableActivity.java b/main/src/cgeo/geocaching/LogTrackableActivity.java
index 4ddec72..b8983ba 100644
--- a/main/src/cgeo/geocaching/LogTrackableActivity.java
+++ b/main/src/cgeo/geocaching/LogTrackableActivity.java
@@ -7,8 +7,8 @@ import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.twitter.Twitter;
-import cgeo.geocaching.ui.DateDialog;
import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.dialog.DateDialog;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
@@ -47,7 +47,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
private int attempts = 0;
private CheckBox tweetCheck = null;
private LinearLayout tweetBox = null;
- private cgTrackable trackable;
+ private Trackable trackable;
private Handler showProgressHandler = new Handler() {
@Override
@@ -119,20 +119,20 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
// get parameters
final Bundle extras = getIntent().getExtras();
if (extras != null) {
- geocode = extras.getString("geocode");
- guid = extras.getString("guid");
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
+ guid = extras.getString(Intents.EXTRA_GUID);
- if (StringUtils.isNotBlank(extras.getString("trackingcode"))) {
- ((EditText) findViewById(R.id.tracking)).setText(extras.getString("trackingcode"));
+ if (StringUtils.isNotBlank(extras.getString(Intents.EXTRA_TRACKING_CODE))) {
+ ((EditText) findViewById(R.id.tracking)).setText(extras.getString(Intents.EXTRA_TRACKING_CODE));
}
}
- trackable = app.getTrackableByGeocode(geocode);
+ trackable = cgData.loadTrackable(geocode);
if (StringUtils.isNotBlank(trackable.getName())) {
setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getName());
} else {
- setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getGeocode().toUpperCase());
+ setTitle(res.getString(R.string.trackable_touch) + ": " + trackable.getGeocode());
}
if (guid == null) {
@@ -207,7 +207,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
tweetCheck.setChecked(true);
if (CollectionUtils.isEmpty(possibleLogTypes)) {
- possibleLogTypes = cgTrackable.getPossibleLogTypes();
+ possibleLogTypes = Trackable.getPossibleLogTypes();
}
final Button buttonPost = (Button) findViewById(R.id.post);
@@ -311,7 +311,7 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
possibleLogTypes.addAll(typesPre);
}
} catch (Exception e) {
- Log.e("LogTrackableActivity.LoadDataThread.run: " + e.toString());
+ Log.e("LogTrackableActivity.LoadDataThread.run", e);
}
loadDataHandler.sendEmptyMessage(0);
@@ -349,17 +349,17 @@ public class LogTrackableActivity extends AbstractLoggingActivity implements Dat
return status;
} catch (Exception e) {
- Log.e("LogTrackableActivity.postLogFn: " + e.toString());
+ Log.e("LogTrackableActivity.postLogFn", e);
}
return StatusCode.LOG_POST_ERROR;
}
- public static void startActivity(final Context context, final cgTrackable trackable) {
+ public static void startActivity(final Context context, final Trackable trackable) {
final Intent logTouchIntent = new Intent(context, LogTrackableActivity.class);
- logTouchIntent.putExtra("geocode", trackable.getGeocode().toUpperCase());
- logTouchIntent.putExtra("guid", trackable.getGuid());
- logTouchIntent.putExtra("trackingcode", trackable.getTrackingcode());
+ logTouchIntent.putExtra(Intents.EXTRA_GEOCODE, trackable.getGeocode());
+ logTouchIntent.putExtra(Intents.EXTRA_GUID, trackable.getGuid());
+ logTouchIntent.putExtra(Intents.EXTRA_TRACKING_CODE, trackable.getTrackingcode());
context.startActivity(logTouchIntent);
}
diff --git a/main/src/cgeo/geocaching/SearchActivity.java b/main/src/cgeo/geocaching/SearchActivity.java
index 6194013..ddb9483 100644
--- a/main/src/cgeo/geocaching/SearchActivity.java
+++ b/main/src/cgeo/geocaching/SearchActivity.java
@@ -7,6 +7,7 @@ import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.connector.gc.GCConstants;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.EditUtils;
import cgeo.geocaching.utils.GeoDirHandler;
@@ -28,9 +29,9 @@ import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
-public class SearchActivity extends AbstractActivity {
+import java.util.Locale;
- private static final String EXTRAS_KEYWORDSEARCH = "keywordsearch";
+public class SearchActivity extends AbstractActivity {
private static final int MENU_SEARCH_OWN_CACHES = 1;
private EditText latEdit = null;
@@ -48,7 +49,7 @@ public class SearchActivity extends AbstractActivity {
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
final String query = intent.getStringExtra(SearchManager.QUERY);
- final boolean keywordSearch = intent.getBooleanExtra(EXTRAS_KEYWORDSEARCH, true);
+ final boolean keywordSearch = intent.getBooleanExtra(Intents.EXTRA_KEYWORD_SEARCH, true);
if (instantSearch(query, keywordSearch)) {
setResult(RESULT_OK);
@@ -109,7 +110,7 @@ public class SearchActivity extends AbstractActivity {
final IConnector connector = ConnectorFactory.getConnector(geocode);
if (connector instanceof ISearchByGeocode) {
final Intent cachesIntent = new Intent(this, CacheDetailActivity.class);
- cachesIntent.putExtra("geocode", geocode.toUpperCase());
+ cachesIntent.putExtra(Intents.EXTRA_GEOCODE, geocode.toUpperCase(Locale.US));
startActivity(cachesIntent);
return true;
}
@@ -117,8 +118,8 @@ public class SearchActivity extends AbstractActivity {
// Check if the query is a TB code
final String trackable = BaseUtils.getMatch(query, GCConstants.PATTERN_TB_CODE, true, 0, "", false);
if (StringUtils.isNotBlank(trackable)) {
- final Intent trackablesIntent = new Intent(this, cgeotrackable.class);
- trackablesIntent.putExtra("geocode", trackable.toUpperCase());
+ final Intent trackablesIntent = new Intent(this, TrackableActivity.class);
+ trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, trackable.toUpperCase(Locale.US));
startActivity(trackablesIntent);
return true;
}
@@ -159,7 +160,7 @@ public class SearchActivity extends AbstractActivity {
findByGeocodeFn();
}
});
- addHistoryEntries(geocodeEdit, app.geocodesInCache());
+ addHistoryEntries(geocodeEdit, cgData.getRecentGeocodesForSearch());
final Button displayByGeocode = (Button) findViewById(R.id.display_geocode);
displayByGeocode.setOnClickListener(new findByGeocodeListener());
@@ -211,7 +212,7 @@ public class SearchActivity extends AbstractActivity {
findTrackableFn();
}
});
- addHistoryEntries(trackable, app.getTrackableCodes());
+ addHistoryEntries(trackable, cgData.getTrackableCodes());
disableSuggestions(trackable);
@@ -255,9 +256,9 @@ public class SearchActivity extends AbstractActivity {
@Override
public void onClick(View arg0) {
- cgeocoords coordsDialog = new cgeocoords(SearchActivity.this, null, null, app.currentGeo());
+ CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(SearchActivity.this, null, null, app.currentGeo());
coordsDialog.setCancelable(true);
- coordsDialog.setOnCoordinateUpdate(new cgeocoords.CoordinateUpdate() {
+ coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
public void update(Geopoint gp) {
((Button) findViewById(R.id.buttonLatitude)).setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
@@ -332,8 +333,8 @@ public class SearchActivity extends AbstractActivity {
return;
}
- final Intent addressesIntent = new Intent(this, AdressListActivity.class);
- addressesIntent.putExtra("keyword", addText);
+ final Intent addressesIntent = new Intent(this, AddressListActivity.class);
+ addressesIntent.putExtra(Intents.EXTRA_KEYWORD, addText);
startActivity(addressesIntent);
}
@@ -406,8 +407,8 @@ public class SearchActivity extends AbstractActivity {
return;
}
- final Intent trackablesIntent = new Intent(this, cgeotrackable.class);
- trackablesIntent.putExtra("geocode", trackableText.toUpperCase());
+ final Intent trackablesIntent = new Intent(this, TrackableActivity.class);
+ trackablesIntent.putExtra(Intents.EXTRA_GEOCODE, trackableText.toUpperCase(Locale.US));
startActivity(trackablesIntent);
}
@@ -430,7 +431,7 @@ public class SearchActivity extends AbstractActivity {
final Intent searchIntent = new Intent(fromActivity, SearchActivity.class);
searchIntent.setAction(Intent.ACTION_SEARCH).
putExtra(SearchManager.QUERY, scan).
- putExtra(SearchActivity.EXTRAS_KEYWORDSEARCH, false);
+ putExtra(Intents.EXTRA_KEYWORD_SEARCH, false);
fromActivity.startActivityForResult(searchIntent, cgeo.SEARCH_REQUEST_CODE);
}
}
diff --git a/main/src/cgeo/geocaching/SearchResult.java b/main/src/cgeo/geocaching/SearchResult.java
index e21717d..b0540f2 100644
--- a/main/src/cgeo/geocaching/SearchResult.java
+++ b/main/src/cgeo/geocaching/SearchResult.java
@@ -8,6 +8,7 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.gcvote.GCVote;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import android.os.Parcel;
@@ -40,38 +41,49 @@ public class SearchResult implements Parcelable {
}
};
+ /**
+ * Build a new empty search result.
+ */
public SearchResult() {
- this((Set<String>) null);
+ this(new HashSet<String>());
}
- public SearchResult(SearchResult searchResult) {
- if (searchResult != null) {
- this.geocodes = new HashSet<String>(searchResult.geocodes);
- this.error = searchResult.error;
- this.url = searchResult.url;
- this.viewstates = searchResult.viewstates;
- this.setTotal(searchResult.getTotal());
- } else {
- this.geocodes = new HashSet<String>();
- }
+ /**
+ * Copy a search result, for example to apply different filters on it.
+ *
+ * @param searchResult the original search result, which cannot be null
+ */
+ public SearchResult(final SearchResult searchResult) {
+ geocodes = new HashSet<String>(searchResult.geocodes);
+ error = searchResult.error;
+ url = searchResult.url;
+ viewstates = searchResult.viewstates;
+ setTotal(searchResult.getTotal());
}
- public SearchResult(final Set<String> geocodes, final int total) {
- if (geocodes == null) {
- this.geocodes = new HashSet<String>();
- } else {
- this.geocodes = new HashSet<String>(geocodes.size());
- this.geocodes.addAll(geocodes);
- }
+ /**
+ * Build a search result from an existing collection of geocodes.
+ *
+ * @param geocodes a non-null collection of geocodes
+ * @param total the total number of geocodes (FIXME: what is the meaning of this number wrt to geocodes.size()?)
+ */
+ public SearchResult(final Collection<String> geocodes, final int total) {
+ this.geocodes = new HashSet<String>(geocodes.size());
+ this.geocodes.addAll(geocodes);
this.setTotal(total);
}
+ /**
+ * Build a search result from an existing collection of geocodes.
+ *
+ * @param geocodes a non-null set of geocodes
+ */
public SearchResult(final Set<String> geocodes) {
- this(geocodes, geocodes == null ? 0 : geocodes.size());
+ this(geocodes, geocodes.size());
}
public SearchResult(final Parcel in) {
- ArrayList<String> list = new ArrayList<String>();
+ final ArrayList<String> list = new ArrayList<String>();
in.readStringList(list);
geocodes = new HashSet<String>(list);
error = (StatusCode) in.readSerializable();
@@ -84,14 +96,24 @@ public class SearchResult implements Parcelable {
setTotal(in.readInt());
}
- public SearchResult(cgCache cache) {
- this();
- addCache(cache);
+ /**
+ * Build a search result designating a single cache.
+ *
+ * @param cache the cache to include
+ */
+
+ public SearchResult(final Geocache cache) {
+ this(Collections.singletonList(cache));
}
- public SearchResult(Collection<cgCache> caches) {
+ /**
+ * Build a search result from a collection of caches.
+ *
+ * @param caches the non-null collection of caches to include
+ */
+ public SearchResult(final Collection<Geocache> caches) {
this();
- for (cgCache cache : caches) {
+ for (final Geocache cache : caches) {
addCache(cache);
}
}
@@ -148,7 +170,7 @@ public class SearchResult implements Parcelable {
return;
}
- this.viewstates = viewstates;
+ System.arraycopy(viewstates, 0, this.viewstates, 0, viewstates.length);
}
public int getTotal() {
@@ -169,14 +191,13 @@ public class SearchResult implements Parcelable {
SearchResult result = new SearchResult(this);
result.geocodes.clear();
- final ArrayList<cgCache> cachesForVote = new ArrayList<cgCache>();
-
- final Set<cgCache> caches = cgeoapplication.getInstance().loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
- for (cgCache cache : caches) {
+ final ArrayList<Geocache> cachesForVote = new ArrayList<Geocache>();
+ final Set<Geocache> caches = cgData.loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
+ for (Geocache cache : caches) {
// Is there any reason to exclude the cache from the list?
final boolean excludeCache = (excludeDisabled && cache.isDisabled()) ||
- (excludeMine && (cache.isOwn() || cache.isFound())) ||
- (cacheType != CacheType.ALL && cacheType != cache.getType());
+ (excludeMine && (cache.isOwner() || cache.isFound())) ||
+ (!cacheType.contains(cache));
if (!excludeCache) {
result.addCache(cache);
cachesForVote.add(cache);
@@ -186,15 +207,12 @@ public class SearchResult implements Parcelable {
return result;
}
- public cgCache getFirstCacheFromResult(final EnumSet<LoadFlag> loadFlags) {
- if (geocodes != null && geocodes.size() >= 1) {
- return cgeoapplication.getInstance().loadCache((String) geocodes.toArray()[0], loadFlags);
- }
- return null;
+ public Geocache getFirstCacheFromResult(final EnumSet<LoadFlag> loadFlags) {
+ return CollectionUtils.isNotEmpty(geocodes) ? cgData.loadCache(geocodes.iterator().next(), loadFlags) : null;
}
- public Set<cgCache> getCachesFromSearchResult(final EnumSet<LoadFlag> loadFlags) {
- return cgeoapplication.getInstance().loadCaches(geocodes, loadFlags);
+ public Set<Geocache> getCachesFromSearchResult(final EnumSet<LoadFlag> loadFlags) {
+ return cgData.loadCaches(geocodes, loadFlags);
}
/** Add the geocode to the search. No cache is loaded into the CacheCache */
@@ -211,13 +229,22 @@ public class SearchResult implements Parcelable {
}
/** Add the cache geocode to the search and store the cache in the CacheCache */
- public boolean addCache(final cgCache cache) {
+ public boolean addCache(final Geocache cache) {
addGeocode(cache.getGeocode());
- return cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
+ return cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_CACHE));
}
public boolean isEmpty() {
return geocodes.isEmpty();
}
+ public boolean hasUnsavedCaches() {
+ for (final String geocode : getGeocodes()) {
+ if (!cgData.isOffline(geocode, null)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/Settings.java b/main/src/cgeo/geocaching/Settings.java
index 850c4f4..0c157e1 100644
--- a/main/src/cgeo/geocaching/Settings.java
+++ b/main/src/cgeo/geocaching/Settings.java
@@ -75,7 +75,6 @@ public final class Settings {
private static final String KEY_AUTO_VISIT_TRACKABLES = "trackautovisit";
private static final String KEY_AUTO_INSERT_SIGNATURE = "sigautoinsert";
private static final String KEY_ALTITUDE_CORRECTION = "altcorrection";
- private static final String KEY_USE_GOOGLE_NAVIGATION = "usegnav";
private static final String KEY_STORE_LOG_IMAGES = "logimages";
private static final String KEY_EXCLUDE_DISABLED = "excludedisabled";
private static final String KEY_EXCLUDE_OWN = "excludemine";
@@ -87,6 +86,7 @@ public final class Settings {
private static final String KEY_MEMBER_STATUS = "memberstatus";
private static final String KEY_COORD_INPUT_FORMAT = "coordinputformat";
private static final String KEY_LOG_OFFLINE = "log_offline";
+ private static final String KEY_CHOOSE_LIST = "choose_list";
private static final String KEY_LOAD_DIRECTION_IMG = "loaddirectionimg";
private static final String KEY_GC_CUSTOM_DATE = "gccustomdate";
private static final String KEY_SHOW_WAYPOINTS_THRESHOLD = "gcshowwaypointsthreshold";
@@ -110,6 +110,8 @@ public final class Settings {
private static final String KEY_PLAIN_LOGS = "plainLogs";
private static final String KEY_NATIVE_UA = "nativeUa";
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 final static int unitsMetric = 1;
@@ -127,7 +129,7 @@ public final class Settings {
Min,
Sec;
- static coordInputFormatEnum fromInt(int id) {
+ public static coordInputFormatEnum fromInt(int id) {
final coordInputFormatEnum[] values = coordInputFormatEnum.values();
if (id < 0 || id >= values.length) {
return Min;
@@ -192,7 +194,6 @@ public final class Settings {
e.putBoolean(KEY_AUTO_VISIT_TRACKABLES, old.getBoolean(KEY_AUTO_VISIT_TRACKABLES, false));
e.putBoolean(KEY_AUTO_INSERT_SIGNATURE, old.getBoolean(KEY_AUTO_INSERT_SIGNATURE, false));
e.putInt(KEY_ALTITUDE_CORRECTION, old.getInt(KEY_ALTITUDE_CORRECTION, 0));
- e.putBoolean(KEY_USE_GOOGLE_NAVIGATION, 0 != old.getInt(KEY_USE_GOOGLE_NAVIGATION, 1));
e.putBoolean(KEY_STORE_LOG_IMAGES, old.getBoolean(KEY_STORE_LOG_IMAGES, false));
e.putBoolean(KEY_EXCLUDE_DISABLED, 0 != old.getInt(KEY_EXCLUDE_DISABLED, 0));
e.putBoolean(KEY_EXCLUDE_OWN, 0 != old.getInt(KEY_EXCLUDE_OWN, 0));
@@ -204,6 +205,7 @@ public final class Settings {
e.putString(KEY_MEMBER_STATUS, old.getString(KEY_MEMBER_STATUS, ""));
e.putInt(KEY_COORD_INPUT_FORMAT, old.getInt(KEY_COORD_INPUT_FORMAT, 0));
e.putBoolean(KEY_LOG_OFFLINE, old.getBoolean(KEY_LOG_OFFLINE, false));
+ e.putBoolean(KEY_CHOOSE_LIST, old.getBoolean(KEY_CHOOSE_LIST, false));
e.putBoolean(KEY_LOAD_DIRECTION_IMG, old.getBoolean(KEY_LOAD_DIRECTION_IMG, true));
e.putString(KEY_GC_CUSTOM_DATE, old.getString(KEY_GC_CUSTOM_DATE, null));
e.putInt(KEY_SHOW_WAYPOINTS_THRESHOLD, old.getInt(KEY_SHOW_WAYPOINTS_THRESHOLD, 0));
@@ -307,6 +309,42 @@ public final class Settings {
});
}
+ public static boolean isOCConnectorActive() {
+ return sharedPrefs.getBoolean(KEY_CONNECTOR_OC_ACTIVE, false);
+ }
+
+ public static boolean setOCConnectorActive(final boolean isActive) {
+ return editSharedSettings(new PrefRunnable() {
+
+ @Override
+ public void edit(Editor edit) {
+ edit.putBoolean(KEY_CONNECTOR_OC_ACTIVE, isActive);
+ }
+ });
+ }
+
+ public static String getOCConnectorUserName() {
+ String ocConnectorUser = sharedPrefs.getString(KEY_CONNECTOR_OC_USER, null);
+ if (StringUtils.isBlank(ocConnectorUser)) {
+ return StringUtils.EMPTY;
+ }
+ return ocConnectorUser;
+ }
+
+ public static boolean setOCConnectorUserName(final String userName) {
+ return editSharedSettings(new PrefRunnable() {
+
+ @Override
+ public void edit(Editor edit) {
+ if (StringUtils.isBlank(userName)) {
+ edit.remove(KEY_CONNECTOR_OC_USER);
+ } else {
+ edit.putString(KEY_CONNECTOR_OC_USER, userName);
+ }
+ }
+ });
+ }
+
public static boolean isGCvoteLogin() {
final String preUsername = sharedPrefs.getString(KEY_USERNAME, null);
final String prePassword = sharedPrefs.getString(KEY_GCVOTE_PASSWORD, null);
@@ -516,6 +554,20 @@ public final class Settings {
return sharedPrefs.getBoolean(KEY_LOG_OFFLINE, false);
}
+ static void setChooseList(final boolean choose) {
+ editSharedSettings(new PrefRunnable() {
+
+ @Override
+ public void edit(Editor edit) {
+ edit.putBoolean(KEY_CHOOSE_LIST, choose);
+ }
+ });
+ }
+
+ public static boolean getChooseList() {
+ return sharedPrefs.getBoolean(KEY_CHOOSE_LIST, false);
+ }
+
static void setLoadDirImg(final boolean value) {
editSharedSettings(new PrefRunnable() {
@@ -672,20 +724,6 @@ public final class Settings {
});
}
- public static boolean isUseGoogleNavigation() {
- return sharedPrefs.getBoolean(KEY_USE_GOOGLE_NAVIGATION, true);
- }
-
- public static void setUseGoogleNavigation(final boolean useGoogleNavigation) {
- editSharedSettings(new PrefRunnable() {
-
- @Override
- public void edit(Editor edit) {
- edit.putBoolean(KEY_USE_GOOGLE_NAVIGATION, useGoogleNavigation);
- }
- });
- }
-
public static boolean isAutoLoadDescription() {
return sharedPrefs.getBoolean(KEY_LOAD_DESCRIPTION, false);
}
@@ -1331,7 +1369,7 @@ public final class Settings {
FileUtils.listDir(result, directory, new ExtensionsBasedFileSelector(new String[] { "xml" }), null);
- return result.toArray(new File[] {});
+ return result.toArray(new File[result.size()]);
}
private static class ExtensionsBasedFileSelector extends FileSelector {
diff --git a/main/src/cgeo/geocaching/SettingsActivity.java b/main/src/cgeo/geocaching/SettingsActivity.java
index 823b52f..3463204 100644
--- a/main/src/cgeo/geocaching/SettingsActivity.java
+++ b/main/src/cgeo/geocaching/SettingsActivity.java
@@ -5,7 +5,6 @@ import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory.NavigationAppsEnum;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.gc.Login;
-import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.files.SimpleDirChooser;
import cgeo.geocaching.maps.MapProviderFactory;
@@ -24,6 +23,7 @@ import ch.boye.httpclientandroidlib.HttpResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openintents.intents.FileManagerIntents;
import android.app.ProgressDialog;
import android.content.Context;
@@ -84,7 +84,7 @@ public class SettingsActivity extends AbstractActivity {
} catch (Exception e) {
showToast(res.getString(R.string.err_login_failed));
- Log.e("SettingsActivity.logInHandler: " + e.toString());
+ Log.e("SettingsActivity.logInHandler", e);
}
if (loginDialog != null && loginDialog.isShowing()) {
@@ -112,7 +112,7 @@ public class SettingsActivity extends AbstractActivity {
} catch (Exception e) {
showToast(res.getString(R.string.init_sendToCgeo_register_fail));
- Log.e("SettingsActivity.webHandler: " + e.toString());
+ Log.e("SettingsActivity.webHandler", e);
}
if (webDialog != null && webDialog.isShowing()) {
@@ -242,6 +242,21 @@ public class SettingsActivity extends AbstractActivity {
}
});
+ // opencaching.de settings
+ final CheckBox ocCheck = (CheckBox) findViewById(R.id.oc_option);
+ ocCheck.setChecked(Settings.isOCConnectorActive());
+ ocCheck.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Settings.setOCConnectorActive(ocCheck.isChecked());
+ }
+ });
+ EditText ocUserEdit = (EditText) findViewById(R.id.oc_username);
+ if (ocUserEdit.getText().length() == 0) {
+ ocUserEdit.setText(Settings.getOCConnectorUserName());
+ }
+
// gcvote settings
final ImmutablePair<String, String> gcvoteLogin = Settings.getGCvoteLogin();
if (null != gcvoteLogin && null != gcvoteLogin.right) {
@@ -495,24 +510,25 @@ public class SettingsActivity extends AbstractActivity {
}
});
- final CheckBox gnavButton = (CheckBox) findViewById(R.id.gnav);
- gnavButton.setChecked(Settings.isUseGoogleNavigation());
- gnavButton.setOnClickListener(new View.OnClickListener() {
+ final CheckBox logOffline = (CheckBox) findViewById(R.id.log_offline);
+ logOffline.setChecked(Settings.getLogOffline());
+ logOffline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- Settings.setUseGoogleNavigation(gnavButton.isChecked());
+ Settings.setLogOffline(!Settings.getLogOffline());
+ logOffline.setChecked(Settings.getLogOffline());
}
});
- final CheckBox logOffline = (CheckBox) findViewById(R.id.log_offline);
- logOffline.setChecked(Settings.getLogOffline());
- logOffline.setOnClickListener(new View.OnClickListener() {
+ final CheckBox chooseList = (CheckBox) findViewById(R.id.choose_list);
+ chooseList.setChecked(Settings.getChooseList());
+ chooseList.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- Settings.setLogOffline(!Settings.getLogOffline());
- logOffline.setChecked(Settings.getLogOffline());
+ Settings.setChooseList(!Settings.getChooseList());
+ chooseList.setChecked(Settings.getChooseList());
}
});
@@ -577,9 +593,7 @@ public class SettingsActivity extends AbstractActivity {
@Override
public void onClick(View v) {
- Intent dirChooser = new Intent(SettingsActivity.this, SimpleDirChooser.class);
- dirChooser.putExtra(SimpleDirChooser.START_DIR, Settings.getCustomRenderThemeBaseFolder());
- startActivityForResult(dirChooser, SELECT_THEMEFOLDER_REQUEST);
+ selectDirectory(Settings.getCustomRenderThemeBaseFolder(), SELECT_THEMEFOLDER_REQUEST);
}
});
@@ -591,9 +605,7 @@ public class SettingsActivity extends AbstractActivity {
@Override
public void onClick(View v) {
- Intent dirChooser = new Intent(SettingsActivity.this, SimpleDirChooser.class);
- dirChooser.putExtra(SimpleDirChooser.START_DIR, Settings.getGpxExportDir());
- startActivityForResult(dirChooser, SELECT_GPX_EXPORT_REQUEST);
+ selectDirectory(Settings.getGpxExportDir(), SELECT_GPX_EXPORT_REQUEST);
}
});
@@ -605,9 +617,7 @@ public class SettingsActivity extends AbstractActivity {
@Override
public void onClick(View v) {
- Intent dirChooser = new Intent(SettingsActivity.this, SimpleDirChooser.class);
- dirChooser.putExtra(SimpleDirChooser.START_DIR, Settings.getGpxImportDir());
- startActivityForResult(dirChooser, SELECT_GPX_IMPORT_REQUEST);
+ selectDirectory(Settings.getGpxImportDir(), SELECT_GPX_IMPORT_REQUEST);
}
});
@@ -775,7 +785,7 @@ public class SettingsActivity extends AbstractActivity {
*/
public void backup(View view) {
// avoid overwriting an existing backup with an empty database (can happen directly after reinstalling the app)
- if (app.getAllStoredCachesCount(true, CacheType.ALL) == 0) {
+ if (cgData.getAllCachesCount() == 0) {
helpDialog(res.getString(R.string.init_backup), res.getString(R.string.init_backup_unnecessary));
return;
}
@@ -784,7 +794,7 @@ public class SettingsActivity extends AbstractActivity {
new Thread() {
@Override
public void run() {
- final String backupFileName = app.backupDatabase();
+ final String backupFileName = cgData.backupDatabase();
runOnUiThread(new Runnable() {
@Override
public void run() {
@@ -800,7 +810,7 @@ public class SettingsActivity extends AbstractActivity {
private void refreshBackupLabel() {
TextView lastBackup = (TextView) findViewById(R.id.backup_last);
- File lastBackupFile = cgeoapplication.isRestoreFile();
+ File lastBackupFile = cgData.getRestoreFile();
if (lastBackupFile != null) {
lastBackup.setText(res.getString(R.string.init_backup_last) + " " + Formatter.formatTime(lastBackupFile.lastModified()) + ", " + Formatter.formatDate(lastBackupFile.lastModified()));
} else {
@@ -829,6 +839,7 @@ public class SettingsActivity extends AbstractActivity {
String signatureNew = ((EditText) findViewById(R.id.signature)).getText().toString();
String mapDirectoryNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.map_directory)).getText().toString());
String themesDirectoryNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.themefolder)).getText().toString());
+ String ocUserName = StringUtils.trimToEmpty(((EditText) findViewById(R.id.oc_username)).getText().toString());
String altitudeNew = StringUtils.trimToNull(((EditText) findViewById(R.id.altitude)).getText().toString());
int altitudeNewInt = parseNumber(altitudeNew, 0);
@@ -842,6 +853,7 @@ public class SettingsActivity extends AbstractActivity {
final boolean status4 = Settings.setAltCorrection(altitudeNewInt);
final boolean status5 = Settings.setMapFileDirectory(mapDirectoryNew);
final boolean status6 = Settings.setCustomRenderThemeBaseFolder(themesDirectoryNew);
+ final boolean status7 = Settings.setOCConnectorUserName(ocUserName);
Settings.setShowWaypointsThreshold(waypointThreshold);
String importNew = StringUtils.trimToEmpty(((EditText) findViewById(R.id.gpx_importdir)).getText().toString());
@@ -849,7 +861,7 @@ public class SettingsActivity extends AbstractActivity {
Settings.setGpxImportDir(importNew);
Settings.setGpxExportDir(exportNew);
- return status1 && status2 && status3 && status4 && status5 && status6;
+ return status1 && status2 && status3 && status4 && status5 && status6 && status7;
}
/**
@@ -951,7 +963,7 @@ public class SettingsActivity extends AbstractActivity {
try {
pin = Integer.parseInt(strings[1].trim());
} catch (Exception e) {
- Log.e("webDialog: " + e.toString());
+ Log.e("webDialog", e);
}
String code = strings[0];
Settings.setWebNameCode(nam, code);
@@ -966,58 +978,81 @@ public class SettingsActivity extends AbstractActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
+ if (resultCode != RESULT_OK) {
+ return;
+ }
- if (requestCode == SELECT_MAPFILE_REQUEST) {
- if (resultCode == RESULT_OK) {
- if (data.hasExtra("mapfile")) {
- final String mapFile = data.getStringExtra("mapfile");
+ switch (requestCode) {
+ case SELECT_MAPFILE_REQUEST:
+ if (data.hasExtra(Intents.EXTRA_MAP_FILE)) {
+ final String mapFile = data.getStringExtra(Intents.EXTRA_MAP_FILE);
Settings.setMapFile(mapFile);
if (!Settings.isValidMapFile(Settings.getMapFile())) {
showToast(res.getString(R.string.warn_invalid_mapfile));
}
}
- }
- updateMapSourceMenu();
- initMapDirectoryEdittext(true);
- }
- if (requestCode == SELECT_GPX_EXPORT_REQUEST) {
- checkDirectory(resultCode, data, R.id.gpx_exportdir, new RunnableWithArgument<String>() {
+ updateMapSourceMenu();
+ initMapDirectoryEdittext(true);
+ break;
+ case SELECT_GPX_EXPORT_REQUEST:
+ checkDirectory(resultCode, data, R.id.gpx_exportdir, new RunnableWithArgument<String>() {
- @Override
- public void run(String directory) {
- Settings.setGpxExportDir(directory);
- }
- });
- }
- if (requestCode == SELECT_GPX_IMPORT_REQUEST) {
- checkDirectory(resultCode, data, R.id.gpx_importdir, new RunnableWithArgument<String>() {
+ @Override
+ public void run(String directory) {
+ Settings.setGpxExportDir(directory);
+ }
+ });
+ break;
+ case SELECT_GPX_IMPORT_REQUEST:
+ checkDirectory(resultCode, data, R.id.gpx_importdir, new RunnableWithArgument<String>() {
- @Override
- public void run(String directory) {
- Settings.setGpxImportDir(directory);
- }
- });
- }
- if (requestCode == SELECT_THEMEFOLDER_REQUEST) {
- checkDirectory(resultCode, data, R.id.themefolder, new RunnableWithArgument<String>() {
+ @Override
+ public void run(String directory) {
+ Settings.setGpxImportDir(directory);
+ }
+ });
+ break;
+ case SELECT_THEMEFOLDER_REQUEST:
+ checkDirectory(resultCode, data, R.id.themefolder, new RunnableWithArgument<String>() {
- @Override
- public void run(String directory) {
- Settings.setCustomRenderThemeBaseFolder(directory);
- }
- });
+ @Override
+ public void run(String directory) {
+ Settings.setCustomRenderThemeBaseFolder(directory);
+ }
+ });
+ break;
+ default:
+ throw new IllegalArgumentException();
}
}
private void checkDirectory(int resultCode, Intent data, int textField, RunnableWithArgument<String> runnableSetDir) {
- if (resultCode == RESULT_OK) {
- if (data.hasExtra(SimpleDirChooser.EXTRA_CHOSEN_DIR)) {
- final String directory = data.getStringExtra(SimpleDirChooser.EXTRA_CHOSEN_DIR);
- runnableSetDir.run(directory);
- EditText directoryText = (EditText) findViewById(textField);
- directoryText.setText(directory);
- directoryText.requestFocus();
+ if (resultCode != RESULT_OK) {
+ return;
+ }
+ final String directory = new File(data.getData().getPath()).getAbsolutePath();
+ if (StringUtils.isNotBlank(directory)) {
+ runnableSetDir.run(directory);
+ EditText directoryText = (EditText) findViewById(textField);
+ directoryText.setText(directory);
+ directoryText.requestFocus();
+ }
+ }
+
+ private void selectDirectory(String startDirectory, int directoryKind) {
+ try {
+ final Intent dirChooser = new Intent(FileManagerIntents.ACTION_PICK_DIRECTORY);
+ if (StringUtils.isNotBlank(startDirectory)) {
+ dirChooser.setData(Uri.fromFile(new File(startDirectory)));
}
+ dirChooser.putExtra(FileManagerIntents.EXTRA_TITLE, res.getString(R.string.simple_dir_chooser_title));
+ dirChooser.putExtra(FileManagerIntents.EXTRA_BUTTON_TEXT, res.getString(android.R.string.ok));
+ startActivityForResult(dirChooser, directoryKind);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // OI file manager not available
+ final Intent dirChooser = new Intent(this, SimpleDirChooser.class);
+ dirChooser.putExtra(Intents.EXTRA_START_DIR, startDirectory);
+ startActivityForResult(dirChooser, directoryKind);
}
}
diff --git a/main/src/cgeo/geocaching/StaticMapsActivity.java b/main/src/cgeo/geocaching/StaticMapsActivity.java
index 05a18f2..d7cef65 100644
--- a/main/src/cgeo/geocaching/StaticMapsActivity.java
+++ b/main/src/cgeo/geocaching/StaticMapsActivity.java
@@ -10,7 +10,6 @@ import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -36,7 +35,6 @@ public class StaticMapsActivity extends AbstractActivity {
private LayoutInflater inflater = null;
private ProgressDialog waitDialog = null;
private LinearLayout smapsView = null;
- private BitmapFactory factory = null;
private final Handler loadMapsHandler = new Handler() {
@Override
@@ -61,7 +59,7 @@ public class StaticMapsActivity extends AbstractActivity {
showStaticMaps();
}
} catch (Exception e) {
- Log.e("StaticMapsActivity.loadMapsHandler: " + e.toString());
+ Log.e("StaticMapsActivity.loadMapsHandler", e);
}
}
};
@@ -131,10 +129,6 @@ public class StaticMapsActivity extends AbstractActivity {
@Override
public void run() {
try {
- if (factory == null) {
- factory = new BitmapFactory();
- }
-
// try downloading 2 times
for (int trials = 0; trials < 2; trials++) {
for (int level = 1; level <= 5; level++) {
@@ -151,7 +145,7 @@ public class StaticMapsActivity extends AbstractActivity {
}
}
} catch (Exception e) {
- Log.e("StaticMapsActivity.LoadMapsThread.run: " + e.toString());
+ Log.e("StaticMapsActivity.LoadMapsThread.run", e);
}
}
if (!maps.isEmpty()) {
@@ -161,7 +155,7 @@ public class StaticMapsActivity extends AbstractActivity {
loadMapsHandler.sendMessage(Message.obtain());
} catch (Exception e) {
- Log.e("StaticMapsActivity.LoadMapsThread.run: " + e.toString());
+ Log.e("StaticMapsActivity.LoadMapsThread.run", e);
}
}
}
@@ -183,23 +177,23 @@ public class StaticMapsActivity extends AbstractActivity {
}
private boolean downloadStaticMaps() {
- final cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
if (waypoint_id == null) {
showToast(res.getString(R.string.info_storing_static_maps));
- StaticMapsProvider.storeCacheStaticMap(cache, this, true);
+ StaticMapsProvider.storeCacheStaticMap(cache, true);
return cache.hasStaticMap();
}
- final cgWaypoint waypoint = cache.getWaypointById(waypoint_id);
+ final Waypoint waypoint = cache.getWaypointById(waypoint_id);
if (waypoint != null) {
showToast(res.getString(R.string.info_storing_static_maps));
- StaticMapsProvider.storeWaypointStaticMap(cache, this, waypoint, true);
+ StaticMapsProvider.storeWaypointStaticMap(cache, waypoint, true);
return StaticMapsProvider.hasStaticMapForWaypoint(geocode, waypoint_id);
}
showToast(res.getString(R.string.err_detail_not_load_map_static));
return false;
}
- public static void startActivity(final Context activity, final String geocode, final boolean download, final cgWaypoint waypoint) {
+ public static void startActivity(final Context activity, final String geocode, final boolean download, final Waypoint waypoint) {
final Intent intent = new Intent(activity, StaticMapsActivity.class);
// if resuming our app within this activity, finish it and return to the cache activity
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
diff --git a/main/src/cgeo/geocaching/StaticMapsProvider.java b/main/src/cgeo/geocaching/StaticMapsProvider.java
index 87a04fa..6feacc2 100644
--- a/main/src/cgeo/geocaching/StaticMapsProvider.java
+++ b/main/src/cgeo/geocaching/StaticMapsProvider.java
@@ -1,5 +1,6 @@
package cgeo.geocaching;
+import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.concurrent.BlockingThreadPool;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.geopoint.GeopointFormatter.Format;
@@ -12,10 +13,10 @@ import ch.boye.httpclientandroidlib.HttpResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
-import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Point;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
@@ -61,30 +62,25 @@ public class StaticMapsProvider {
}
final HttpResponse httpResponse = Network.getRequest(GOOGLE_STATICMAP_URL, params);
- if (httpResponse != null) {
- if (httpResponse.getStatusLine().getStatusCode() == 200) {
- final File file = getMapFile(geocode, prefix, true);
- if (LocalStorage.saveEntityToFile(httpResponse, file)) {
- // Delete image if it has no contents
- final long fileSize = file.length();
- if (fileSize < MIN_MAP_IMAGE_BYTES) {
- file.delete();
- }
- }
- } else {
- Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode());
- }
- } else {
+ if (httpResponse == null) {
Log.e("StaticMapsProvider.downloadMap: httpResponse is null");
+ return;
+ }
+ if (httpResponse.getStatusLine().getStatusCode() != 200) {
+ Log.d("StaticMapsProvider.downloadMap: httpResponseCode = " + httpResponse.getStatusLine().getStatusCode());
+ return;
+ }
+ final File file = getMapFile(geocode, prefix, true);
+ if (LocalStorage.saveEntityToFile(httpResponse, file)) {
+ // Delete image if it has no contents
+ final long fileSize = file.length();
+ if (fileSize < MIN_MAP_IMAGE_BYTES) {
+ file.delete();
+ }
}
}
- public static void downloadMaps(cgCache cache) {
- final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- downloadMaps(cache, display);
- }
-
- private static void downloadMaps(cgCache cache, Display display) {
+ public static void downloadMaps(Geocache cache) {
if (cache == null) {
Log.e("downloadMaps - missing input parameter cache");
return;
@@ -92,7 +88,7 @@ public class StaticMapsProvider {
if ((!Settings.isStoreOfflineMaps() && !Settings.isStoreOfflineWpMaps()) || StringUtils.isBlank(cache.getGeocode())) {
return;
}
- int edge = guessMaxDisplaySide(display);
+ int edge = guessMaxDisplaySide();
if (Settings.isStoreOfflineMaps() && cache.getCoords() != null) {
storeCachePreviewMap(cache);
@@ -103,18 +99,18 @@ public class StaticMapsProvider {
if (Settings.isStoreOfflineWpMaps() && CollectionUtils.isNotEmpty(cache.getWaypoints())) {
// remove all waypoint static map files due to origin cache waypoint id changed on saveCache
LocalStorage.deleteFilesWithPrefix(cache.getGeocode(), MAP_FILENAME_PREFIX + WAYPOINT_PREFIX);
- for (cgWaypoint waypoint : cache.getWaypoints()) {
+ for (Waypoint waypoint : cache.getWaypoints()) {
storeWaypointStaticMap(cache.getGeocode(), edge, waypoint, false);
}
}
}
- public static void storeWaypointStaticMap(cgCache cache, Activity activity, cgWaypoint waypoint, boolean waitForResult) {
- int edge = StaticMapsProvider.guessMaxDisplaySide(activity);
+ public static void storeWaypointStaticMap(Geocache cache, Waypoint waypoint, boolean waitForResult) {
+ int edge = StaticMapsProvider.guessMaxDisplaySide();
storeWaypointStaticMap(cache.getGeocode(), edge, waypoint, waitForResult);
}
- private static void storeWaypointStaticMap(final String geocode, int edge, cgWaypoint waypoint, final boolean waitForResult) {
+ private static void storeWaypointStaticMap(final String geocode, int edge, Waypoint waypoint, final boolean waitForResult) {
if (geocode == null) {
Log.e("storeWaypointStaticMap - missing input parameter geocode");
return;
@@ -132,15 +128,15 @@ public class StaticMapsProvider {
downloadMaps(geocode, wpMarkerUrl, WAYPOINT_PREFIX + waypoint.getId() + '_', wpLatlonMap, edge, null, waitForResult);
}
- public static void storeCacheStaticMap(cgCache cache, Activity activity, final boolean waitForResult) {
- int edge = guessMaxDisplaySide(activity);
+ public static void storeCacheStaticMap(Geocache cache, final boolean waitForResult) {
+ int edge = guessMaxDisplaySide();
storeCacheStaticMap(cache, edge, waitForResult);
}
- private static void storeCacheStaticMap(final cgCache cache, final int edge, final boolean waitForResult) {
+ private static void storeCacheStaticMap(final Geocache cache, final int edge, final boolean waitForResult) {
final String latlonMap = cache.getCoords().format(Format.LAT_LON_DECDEGREE_COMMA);
final Parameters waypoints = new Parameters();
- for (final cgWaypoint waypoint : cache.getWaypoints()) {
+ for (final Waypoint waypoint : cache.getWaypoints()) {
if (waypoint.getCoords() == null) {
continue;
}
@@ -152,34 +148,31 @@ public class StaticMapsProvider {
downloadMaps(cache.getGeocode(), cacheMarkerUrl, "", latlonMap, edge, waypoints, waitForResult);
}
- public static void storeCachePreviewMap(final cgCache cache) {
+ 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 String markerUrl = MARKERS_URL + "my_location_mdpi.png";
final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
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);
}
- private static int guessMaxDisplaySide(Display display) {
- final int maxWidth = display.getWidth() - 25;
- final int maxHeight = display.getHeight() - 25;
+ 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;
}
- private static int guessMaxDisplaySide(Activity activity) {
- return guessMaxDisplaySide(((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay());
- }
-
private static void downloadMaps(final String geocode, final String markerUrl, final String prefix, final String latlonMap, final int edge,
final Parameters waypoints, boolean waitForResult) {
if (waitForResult) {
@@ -195,12 +188,12 @@ public class StaticMapsProvider {
try {
pool.add(currentTask, 20, TimeUnit.SECONDS);
} catch (InterruptedException e) {
- Log.e("StaticMapsProvider.downloadMaps error adding task: " + e.toString());
+ Log.e("StaticMapsProvider.downloadMaps error adding task", e);
}
}
}
- private static String getCacheMarkerUrl(final cgCache cache) {
+ private static String getCacheMarkerUrl(final Geocache cache) {
StringBuilder url = new StringBuilder(MARKERS_URL);
url.append("marker_cache_").append(cache.getType().id);
if (cache.isFound()) {
@@ -212,7 +205,7 @@ public class StaticMapsProvider {
return url.toString();
}
- private static String getWpMarkerUrl(final cgWaypoint waypoint) {
+ private static String getWpMarkerUrl(final Waypoint waypoint) {
String type = waypoint.getWaypointType() != null ? waypoint.getWaypointType().id : null;
return MARKERS_URL + "marker_waypoint_" + type + ".png";
}
@@ -225,7 +218,7 @@ public class StaticMapsProvider {
try {
StaticMapsProvider.getMapFile(geocode, WAYPOINT_PREFIX + wp_id + '_' + level, false).delete();
} catch (Exception e) {
- Log.e("StaticMapsProvider.removeWpStaticMaps: " + e.toString());
+ Log.e("StaticMapsProvider.removeWpStaticMaps", e);
}
}
}
@@ -236,7 +229,7 @@ public class StaticMapsProvider {
* @param cache
* @return <code>true</code> if at least one mapfile exists; <code>false</code> otherwise
*/
- public static boolean hasStaticMap(final cgCache cache) {
+ public static boolean hasStaticMap(final Geocache cache) {
if (cache == null) {
return false;
}
diff --git a/main/src/cgeo/geocaching/StatusFragment.java b/main/src/cgeo/geocaching/StatusFragment.java
new file mode 100644
index 0000000..5a9a5b4
--- /dev/null
+++ b/main/src/cgeo/geocaching/StatusFragment.java
@@ -0,0 +1,110 @@
+package cgeo.geocaching;
+
+import cgeo.geocaching.network.StatusUpdater.Status;
+import cgeo.geocaching.utils.IObserver;
+import cgeo.geocaching.utils.Log;
+
+import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class StatusFragment extends Fragment {
+
+ private ViewGroup status;
+ private ImageView statusIcon;
+ private TextView statusMessage;
+
+ final private StatusHandler statusHandler = new StatusHandler();
+
+ @Override
+ public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
+ super.onCreateView(inflater, container, savedInstanceState);
+ status = (ViewGroup) inflater.inflate(R.layout.status, container, false);
+ statusIcon = (ImageView) status.findViewById(R.id.status_icon);
+ statusMessage = (TextView) status.findViewById(R.id.status_message);
+ return status;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ cgeoapplication.getInstance().getStatusUpdater().addObserver(statusHandler);
+ }
+
+ @Override
+ public void onPause() {
+ cgeoapplication.getInstance().getStatusUpdater().deleteObserver(statusHandler);
+ super.onPause();
+ }
+
+ private class StatusHandler extends Handler implements IObserver<Status> {
+
+ @Override
+ public void update(final Status data) {
+ obtainMessage(0, data).sendToTarget();
+ }
+
+ @Override
+ public void handleMessage(final Message msg) {
+ final Status data = (Status) msg.obj;
+ updateDisplay(data != null && data.message != null ? data : null);
+ }
+
+ private void updateDisplay(final Status data) {
+
+ if (data == null) {
+ status.setVisibility(View.INVISIBLE);
+ return;
+ }
+
+ final Resources res = getResources();
+ final String packageName = getActivity().getPackageName();
+
+ if (data.icon != null) {
+ final int iconId = res.getIdentifier(data.icon, "drawable", packageName);
+ if (iconId != 0) {
+ statusIcon.setImageResource(iconId);
+ statusIcon.setVisibility(View.VISIBLE);
+ } else {
+ Log.w("StatusHandler: could not find icon corresponding to @drawable/" + data.icon);
+ statusIcon.setVisibility(View.GONE);
+ }
+ } else {
+ statusIcon.setVisibility(View.GONE);
+ }
+
+ String message = data.message;
+ if (data.messageId != null) {
+ final int messageId = res.getIdentifier(data.messageId, "string", packageName);
+ if (messageId != 0) {
+ message = res.getString(messageId);
+ }
+ }
+
+ statusMessage.setText(message);
+ status.setVisibility(View.VISIBLE);
+
+ if (data.url != null) {
+ status.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(data.url)));
+ }
+ });
+ } else {
+ status.setClickable(false);
+ }
+ }
+
+ }
+}
diff --git a/main/src/cgeo/geocaching/StoredList.java b/main/src/cgeo/geocaching/StoredList.java
index cdff1cb..5a6f132 100644
--- a/main/src/cgeo/geocaching/StoredList.java
+++ b/main/src/cgeo/geocaching/StoredList.java
@@ -1,6 +1,6 @@
package cgeo.geocaching;
-import cgeo.geocaching.activity.IAbstractActivity;
+import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.lang3.StringUtils;
@@ -34,28 +34,54 @@ public class StoredList {
return title + " [" + count + "]";
}
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof StoredList)) {
+ return false;
+ }
+ return id == ((StoredList) obj).id;
+ }
+
public static class UserInterface {
- private final IAbstractActivity activity;
+ private final Activity activity;
private final cgeoapplication app;
private final Resources res;
- public UserInterface(final IAbstractActivity activity) {
+ public UserInterface(final Activity activity) {
this.activity = activity;
app = cgeoapplication.getInstance();
res = app.getResources();
}
public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards) {
- promptForListSelection(titleId, runAfterwards, false);
+ promptForListSelection(titleId, runAfterwards, false, -1);
}
- public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyMoveTargets) {
- final List<StoredList> lists = app.getLists();
+ public void promptForListSelection(final int titleId, final RunnableWithArgument<Integer> runAfterwards, final boolean onlyMoveTargets, final int exceptListId) {
+ final List<StoredList> lists = cgData.getLists();
if (lists == null) {
return;
}
+ if (exceptListId > StoredList.TEMPORARY_LIST_ID) {
+ StoredList exceptList = cgData.getList(exceptListId);
+ if (exceptList != null) {
+ lists.remove(exceptList);
+ }
+ }
+
final List<CharSequence> listsTitle = new ArrayList<CharSequence>();
for (StoredList list : lists) {
listsTitle.add(list.getTitleAndCount());
@@ -67,7 +93,7 @@ public class StoredList {
final CharSequence[] items = new CharSequence[listsTitle.size()];
- AlertDialog.Builder builder = new AlertDialog.Builder((Activity) activity);
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(res.getString(titleId));
builder.setItems(listsTitle.toArray(items), new DialogInterface.OnClickListener() {
@Override
@@ -94,23 +120,23 @@ public class StoredList {
@Override
public void run(final String listName) {
- final int newId = app.createList(listName);
+ final int newId = cgData.createList(listName);
if (newId >= cgData.customListIdOffset) {
- activity.showToast(res.getString(R.string.list_dialog_create_ok));
+ ActivityMixin.showToast(activity, res.getString(R.string.list_dialog_create_ok));
if (runAfterwards != null) {
runAfterwards.run(newId);
}
} else {
- activity.showToast(res.getString(R.string.list_dialog_create_err));
+ ActivityMixin.showToast(activity, res.getString(R.string.list_dialog_create_err));
}
}
});
}
private void handleListNameInput(final String defaultValue, int dialogTitle, int buttonTitle, final RunnableWithArgument<String> runnable) {
- final AlertDialog.Builder alert = new AlertDialog.Builder((Activity) activity);
- final View view = ((Activity) activity).getLayoutInflater().inflate(R.layout.list_create_dialog, null);
+ final AlertDialog.Builder alert = new AlertDialog.Builder(activity);
+ final View view = activity.getLayoutInflater().inflate(R.layout.list_create_dialog, null);
final EditText input = (EditText) view.findViewById(R.id.text);
input.setText(defaultValue);
@@ -137,12 +163,12 @@ public class StoredList {
}
public void promptForListRename(final int listId, final Runnable runAfterRename) {
- final StoredList list = app.getList(listId);
+ final StoredList list = cgData.getList(listId);
handleListNameInput(list.title, R.string.list_dialog_rename_title, R.string.list_dialog_rename, new RunnableWithArgument<String>() {
@Override
public void run(final String listName) {
- app.renameList(listId, listName);
+ cgData.renameList(listId, listName);
if (runAfterRename != null) {
runAfterRename.run();
}
diff --git a/main/src/cgeo/geocaching/cgTrackable.java b/main/src/cgeo/geocaching/Trackable.java
index 7ed3424..f777351 100644
--- a/main/src/cgeo/geocaching/cgTrackable.java
+++ b/main/src/cgeo/geocaching/Trackable.java
@@ -11,7 +11,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-public class cgTrackable implements ILogable {
+public class Trackable implements ILogable {
static final public int SPOTTED_UNSET = 0;
static final public int SPOTTED_CACHE = 1;
static final public int SPOTTED_USER = 2;
@@ -38,17 +38,17 @@ public class cgTrackable implements ILogable {
private String trackingcode = null;
public String getUrl() {
- if (StringUtils.startsWithIgnoreCase(geocode, "GK")) {
- String hex = geocode.substring(3);
+ if (StringUtils.startsWithIgnoreCase(getGeocode(), "GK")) {
+ String hex = getGeocode().substring(3);
try {
int id = Integer.parseInt(hex, 16);
return "http://geokrety.org/konkret.php?id=" + id;
} catch (NumberFormatException e) {
- Log.e("cgTrackable.getUrl", e);
+ Log.e("Trackable.getUrl", e);
return null;
}
}
- return "http://www.geocaching.com//track/details.aspx?tracker=" + geocode.toUpperCase();
+ return "http://www.geocaching.com//track/details.aspx?tracker=" + geocode;
}
public String getGuid() {
@@ -65,7 +65,7 @@ public class cgTrackable implements ILogable {
}
public void setGeocode(String geocode) {
- this.geocode = geocode;
+ this.geocode = StringUtils.upperCase(geocode);
}
public String getIconUrl() {
@@ -208,7 +208,7 @@ public class cgTrackable implements ILogable {
}
public boolean isLoggable() {
- return !StringUtils.startsWithIgnoreCase(geocode, "GK");
+ return !StringUtils.startsWithIgnoreCase(getGeocode(), "GK");
}
public String getTrackingcode() {
diff --git a/main/src/cgeo/geocaching/TrackableActivity.java b/main/src/cgeo/geocaching/TrackableActivity.java
new file mode 100644
index 0000000..fea4521
--- /dev/null
+++ b/main/src/cgeo/geocaching/TrackableActivity.java
@@ -0,0 +1,681 @@
+package cgeo.geocaching;
+
+import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.activity.AbstractViewPagerActivity;
+import cgeo.geocaching.connector.gc.GCParser;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.geopoint.Units;
+import cgeo.geocaching.network.HtmlImage;
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.ui.AbstractCachingPageViewCreator;
+import cgeo.geocaching.ui.CacheDetailsCreator;
+import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.utils.BaseUtils;
+import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.UnknownTagsHandler;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.text.Html;
+import android.text.method.LinkMovementMethod;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+public class TrackableActivity extends AbstractViewPagerActivity<TrackableActivity.Page> {
+
+ public enum Page {
+ DETAILS(R.string.detail),
+ LOGS(R.string.cache_logs);
+
+ private final int resId;
+
+ Page(final int resId) {
+ this.resId = resId;
+ }
+ }
+ private static final int MENU_LOG_TOUCH = 1;
+ private static final int MENU_BROWSER_TRACKABLE = 2;
+ private Trackable trackable = null;
+ private String geocode = null;
+ private String name = null;
+ private String guid = null;
+ private String id = null;
+ private String contextMenuUser = null;
+ private LayoutInflater inflater = null;
+ private ProgressDialog waitDialog = null;
+ private Handler loadTrackableHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (trackable == null) {
+ if (waitDialog != null) {
+ waitDialog.dismiss();
+ }
+
+ if (StringUtils.isNotBlank(geocode)) {
+ showToast(res.getString(R.string.err_tb_find) + " " + geocode + ".");
+ } else {
+ showToast(res.getString(R.string.err_tb_find_that));
+ }
+
+ finish();
+ return;
+ }
+
+ try {
+ inflater = getLayoutInflater();
+ geocode = trackable.getGeocode();
+
+ if (StringUtils.isNotBlank(trackable.getName())) {
+ setTitle(Html.fromHtml(trackable.getName()).toString());
+ } else {
+ setTitle(trackable.getName());
+ }
+
+ invalidateOptionsMenuCompatible();
+ reinitializeViewPager();
+
+ } catch (Exception e) {
+ Log.e("TrackableActivity.loadTrackableHandler: ", e);
+ }
+
+ if (waitDialog != null) {
+ waitDialog.dismiss();
+ }
+ }
+ };
+
+ public TrackableActivity() {
+ super("c:geo-trackable-details");
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setTheme();
+ setContentView(R.layout.trackable_activity);
+ setTitle(res.getString(R.string.trackable));
+
+ // get parameters
+ Bundle extras = getIntent().getExtras();
+ Uri uri = getIntent().getData();
+
+ // try to get data from extras
+ if (extras != null) {
+ geocode = extras.getString(Intents.EXTRA_GEOCODE);
+ name = extras.getString(Intents.EXTRA_NAME);
+ guid = extras.getString(Intents.EXTRA_GUID);
+ id = extras.getString(Intents.EXTRA_ID);
+ }
+
+ // try to get data from URI
+ if (geocode == null && guid == null && id == null && uri != null) {
+ String uriHost = uri.getHost().toLowerCase(Locale.US);
+ if (uriHost.contains("geocaching.com")) {
+ geocode = uri.getQueryParameter("tracker");
+ guid = uri.getQueryParameter("guid");
+ id = uri.getQueryParameter("id");
+
+ if (StringUtils.isNotBlank(geocode)) {
+ geocode = geocode.toUpperCase(Locale.US);
+ guid = null;
+ id = null;
+ } else if (StringUtils.isNotBlank(guid)) {
+ geocode = null;
+ guid = guid.toLowerCase(Locale.US);
+ id = null;
+ } else if (StringUtils.isNotBlank(id)) {
+ geocode = null;
+ guid = null;
+ id = id.toLowerCase(Locale.US);
+ } else {
+ showToast(res.getString(R.string.err_tb_details_open));
+ finish();
+ return;
+ }
+ } else if (uriHost.contains("coord.info")) {
+ String uriPath = uri.getPath().toLowerCase(Locale.US);
+ if (uriPath != null && uriPath.startsWith("/tb")) {
+ geocode = uriPath.substring(1).toUpperCase(Locale.US);
+ guid = null;
+ id = null;
+ } else {
+ showToast(res.getString(R.string.err_tb_details_open));
+ finish();
+ return;
+ }
+ }
+ }
+
+ // no given data
+ if (geocode == null && guid == null && id == null) {
+ showToast(res.getString(R.string.err_tb_display));
+ finish();
+ return;
+ }
+
+ String message;
+ if (StringUtils.isNotBlank(name)) {
+ message = Html.fromHtml(name).toString();
+ } else if (StringUtils.isNotBlank(geocode)) {
+ message = geocode;
+ } else {
+ message = res.getString(R.string.trackable);
+ }
+ waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true);
+
+ createViewPager(0, null);
+ LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id);
+ thread.start();
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
+ super.onCreateContextMenu(menu, view, info);
+ final int viewId = view.getId();
+
+ if (viewId == R.id.author) { // Log item author
+ contextMenuUser = ((TextView) view).getText().toString();
+ } else { // Trackable owner, and user holding trackable now
+ RelativeLayout itemLayout = (RelativeLayout) view.getParent();
+ TextView itemName = (TextView) itemLayout.findViewById(R.id.name);
+
+ String selectedName = itemName.getText().toString();
+ if (selectedName.equals(res.getString(R.string.trackable_owner))) {
+ contextMenuUser = trackable.getOwner();
+ } else if (selectedName.equals(res.getString(R.string.trackable_spotted))) {
+ contextMenuUser = trackable.getSpottedName();
+ }
+ }
+
+ menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser);
+ menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden));
+ menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found));
+ menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser));
+ menu.add(viewId, 4, 0, res.getString(R.string.user_menu_send_message));
+ }
+
+ @Override
+ public boolean onContextItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case 1:
+ cgeocaches.startActivityOwner(this, contextMenuUser);
+ return true;
+ case 2:
+ cgeocaches.startActivityUserName(this, contextMenuUser);
+ return true;
+ case 3:
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + Network.encode(contextMenuUser))));
+ return true;
+ case 4:
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/email/?u=" + Network.encode(contextMenuUser))));
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(0, MENU_LOG_TOUCH, 0, res.getString(R.string.trackable_log_touch)).setIcon(R.drawable.ic_menu_agenda); // log touch
+ menu.add(0, MENU_BROWSER_TRACKABLE, 0, res.getString(R.string.trackable_browser_open)).setIcon(R.drawable.ic_menu_info_details); // browser
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_LOG_TOUCH:
+ LogTrackableActivity.startActivity(this, trackable);
+ return true;
+ case MENU_BROWSER_TRACKABLE:
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl())));
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ if (trackable != null) {
+ menu.findItem(MENU_LOG_TOUCH).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable());
+ menu.findItem(MENU_BROWSER_TRACKABLE).setEnabled(StringUtils.isNotBlank(trackable.getUrl()));
+ }
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ private class LoadTrackableThread extends Thread {
+ final private Handler handler;
+ final private String geocode;
+ final private String guid;
+ final private String id;
+
+ public LoadTrackableThread(Handler handlerIn, String geocodeIn, String guidIn, String idIn) {
+ handler = handlerIn;
+ geocode = geocodeIn;
+ guid = guidIn;
+ id = idIn;
+ }
+
+ @Override
+ public void run() {
+ trackable = cgData.loadTrackable(geocode);
+
+ if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) {
+ trackable = GCParser.searchTrackable(geocode, guid, id);
+ }
+ handler.sendMessage(Message.obtain());
+ }
+ }
+
+ private class UserActionsListener implements View.OnClickListener {
+
+ @Override
+ public void onClick(View view) {
+ if (view == null) {
+ return;
+ }
+
+ try {
+ registerForContextMenu(view);
+ openContextMenu(view);
+ } catch (Exception e) {
+ Log.e("TrackableActivity.UserActionsListener.onClick ", e);
+ }
+ }
+ }
+
+ private class TrackableIconThread extends Thread {
+ final private String url;
+ final private Handler handler;
+
+ public TrackableIconThread(String urlIn, Handler handlerIn) {
+ url = urlIn;
+ handler = handlerIn;
+ }
+
+ @Override
+ public void run() {
+ if (url == null || handler == null) {
+ return;
+ }
+
+ try {
+ HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false);
+
+ BitmapDrawable image = imgGetter.getDrawable(url);
+ Message message = handler.obtainMessage(0, image);
+ handler.sendMessage(message);
+ } catch (Exception e) {
+ Log.e("TrackableActivity.TrackableIconThread.run: ", e);
+ }
+ }
+ }
+
+ private static class TrackableIconHandler extends Handler {
+ final private TextView view;
+
+ public TrackableIconHandler(TextView viewIn) {
+ view = viewIn;
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ final BitmapDrawable image = (BitmapDrawable) message.obj;
+ if (image != null && view != null) {
+ image.setBounds(0, 0, view.getHeight(), view.getHeight());
+ view.setCompoundDrawables(image, null, null, null);
+ }
+ }
+ }
+
+ public static void startActivity(final AbstractActivity fromContext,
+ final String guid, final String geocode, final String name) {
+ final Intent trackableIntent = new Intent(fromContext, TrackableActivity.class);
+ trackableIntent.putExtra(Intents.EXTRA_GUID, guid);
+ trackableIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
+ trackableIntent.putExtra(Intents.EXTRA_NAME, name);
+ fromContext.startActivity(trackableIntent);
+ }
+
+ @Override
+ protected PageViewCreator createViewCreator(Page page) {
+ switch (page) {
+ case DETAILS:
+ return new DetailsViewCreator();
+ case LOGS:
+ return new LogsViewCreator();
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ protected String getTitle(Page page) {
+ return res.getString(page.resId);
+ }
+
+ @Override
+ protected Pair<List<? extends Page>, Integer> getOrderedPages() {
+ List<Page> pages = new ArrayList<TrackableActivity.Page>();
+ pages.add(Page.DETAILS);
+ if (!trackable.getLogs().isEmpty()) {
+ pages.add(Page.LOGS);
+ }
+ return new ImmutablePair<List<? extends Page>, Integer>(pages, 0);
+ }
+
+ public class LogsViewCreator extends AbstractCachingPageViewCreator<ListView> {
+
+ private class LogViewHolder {
+
+ private final TextView added;
+ private final TextView type;
+ private final TextView author;
+ private final TextView location;
+ private final TextView log;
+ private final ImageView marker;
+ private final LinearLayout logImages;
+
+ public LogViewHolder(View rowView) {
+ added = ((TextView) rowView.findViewById(R.id.added));
+ type = ((TextView) rowView.findViewById(R.id.type));
+ author = ((TextView) rowView.findViewById(R.id.author));
+ location = ((TextView) rowView.findViewById(R.id.location));
+ log = (TextView) rowView.findViewById(R.id.log);
+ marker = (ImageView) rowView.findViewById(R.id.log_mark);
+ logImages = (LinearLayout) rowView.findViewById(R.id.log_layout);
+ }
+ }
+
+ @Override
+ public ListView getDispatchedView() {
+ view = (ListView) getLayoutInflater().inflate(R.layout.trackable_logs_view, null);
+
+ if (trackable != null && trackable.getLogs() != null) {
+ view.setAdapter(new ArrayAdapter<LogEntry>(TrackableActivity.this, R.layout.trackable_logs_item, trackable.getLogs()) {
+ @Override
+ public View getView(int position, View convertView, android.view.ViewGroup parent) {
+ View rowView = convertView;
+ if (null == rowView) {
+ rowView = getLayoutInflater().inflate(R.layout.trackable_logs_item, null);
+ }
+ LogViewHolder holder = (LogViewHolder) rowView.getTag();
+ if (null == holder) {
+ holder = new LogViewHolder(rowView);
+ rowView.setTag(holder);
+ }
+
+ final LogEntry log = getItem(position);
+ fillViewHolder(holder, log);
+ return rowView;
+ }
+ });
+ }
+ return view;
+ }
+
+ protected void fillViewHolder(LogViewHolder holder, LogEntry log) {
+ if (log.date > 0) {
+ holder.added.setText(Formatter.formatShortDate(log.date));
+ }
+
+ holder.type.setText(log.type.getL10n());
+ holder.author.setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE);
+
+ if (StringUtils.isBlank(log.cacheName)) {
+ holder.location.setVisibility(View.GONE);
+ } else {
+ holder.location.setText(Html.fromHtml(log.cacheName));
+ final String cacheGuid = log.cacheGuid;
+ final String cacheName = log.cacheName;
+ holder.location.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ CacheDetailActivity.startActivityGuid(TrackableActivity.this, cacheGuid, Html.fromHtml(cacheName).toString());
+ }
+ });
+ }
+
+ TextView logView = holder.log;
+ logView.setMovementMethod(LinkMovementMethod.getInstance());
+
+ String logText = log.log;
+ if (BaseUtils.containsHtml(logText)) {
+ logText = log.getDisplayText();
+ logView.setText(Html.fromHtml(logText, new HtmlImage(null, false, StoredList.TEMPORARY_LIST_ID, false), null), TextView.BufferType.SPANNABLE);
+ }
+ else {
+ logView.setText(logText);
+ }
+
+ ImageView statusMarker = holder.marker;
+ // colored marker
+ int marker = log.type.markerId;
+ if (marker != 0) {
+ statusMarker.setVisibility(View.VISIBLE);
+ statusMarker.setImageResource(marker);
+ }
+ else {
+ statusMarker.setVisibility(View.GONE);
+ }
+
+ // add LogImages
+ LinearLayout logLayout = holder.logImages;
+
+ if (log.hasLogImages()) {
+
+ final ArrayList<Image> logImages = new ArrayList<Image>(log.getLogImages());
+
+ final View.OnClickListener listener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ ImagesActivity.startActivityLogImages(TrackableActivity.this, trackable.getGeocode(), logImages);
+ }
+ };
+
+ LinearLayout log_imgView = (LinearLayout) getLayoutInflater().inflate(R.layout.trackable_logs_img, null);
+ TextView log_img_title = (TextView) log_imgView.findViewById(R.id.title);
+ log_img_title.setText(log.getImageTitles());
+ log_img_title.setOnClickListener(listener);
+ logLayout.addView(log_imgView);
+ }
+
+ holder.author.setOnClickListener(new UserActionsListener());
+ }
+
+ }
+
+ public class DetailsViewCreator extends AbstractCachingPageViewCreator<ScrollView> {
+
+ @Override
+ public ScrollView getDispatchedView() {
+ view = (ScrollView) getLayoutInflater().inflate(R.layout.trackable_details_view, null);
+ final CacheDetailsCreator details = new CacheDetailsCreator(TrackableActivity.this, (LinearLayout) view.findViewById(R.id.details_list));
+
+ // action bar icon
+ if (StringUtils.isNotBlank(trackable.getIconUrl())) {
+ final TrackableIconHandler iconHandler = new TrackableIconHandler(((TextView) findViewById(R.id.actionbar_title)));
+ final TrackableIconThread iconThread = new TrackableIconThread(trackable.getIconUrl(), iconHandler);
+ iconThread.start();
+ }
+
+ // trackable name
+ details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown));
+
+ // trackable type
+ String tbType;
+ if (StringUtils.isNotBlank(trackable.getType())) {
+ tbType = Html.fromHtml(trackable.getType()).toString();
+ } else {
+ tbType = res.getString(R.string.trackable_unknown);
+ }
+ details.add(R.string.trackable_type, tbType);
+
+ // trackable geocode
+ details.add(R.string.trackable_code, trackable.getGeocode());
+
+ // trackable owner
+ TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown));
+ if (StringUtils.isNotBlank(trackable.getOwner())) {
+ owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE);
+ owner.setOnClickListener(new UserActionsListener());
+ }
+
+ // trackable spotted
+ if (StringUtils.isNotBlank(trackable.getSpottedName()) ||
+ trackable.getSpottedType() == Trackable.SPOTTED_UNKNOWN ||
+ trackable.getSpottedType() == Trackable.SPOTTED_OWNER) {
+ boolean showTimeSpan = true;
+ StringBuilder text;
+
+ if (trackable.getSpottedType() == Trackable.SPOTTED_CACHE) {
+ text = new StringBuilder(res.getString(R.string.trackable_spotted_in_cache) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString());
+ } else if (trackable.getSpottedType() == Trackable.SPOTTED_USER) {
+ text = new StringBuilder(res.getString(R.string.trackable_spotted_at_user) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString());
+ } else if (trackable.getSpottedType() == Trackable.SPOTTED_UNKNOWN) {
+ text = new StringBuilder(res.getString(R.string.trackable_spotted_unknown_location));
+ } else if (trackable.getSpottedType() == Trackable.SPOTTED_OWNER) {
+ text = new StringBuilder(res.getString(R.string.trackable_spotted_owner));
+ } else {
+ text = new StringBuilder("N/A");
+ showTimeSpan = false;
+ }
+
+ // days since last spotting
+ if (showTimeSpan && trackable.getLogs() != null) {
+ for (LogEntry log : trackable.getLogs()) {
+ if (log.type == LogType.RETRIEVED_IT || log.type == LogType.GRABBED_IT || log.type == LogType.DISCOVERED_IT || log.type == LogType.PLACED_IT) {
+ final int days = log.daysSinceLog();
+ text.append(" (").append(res.getQuantityString(R.plurals.days_ago, days, days)).append(')');
+ break;
+ }
+ }
+ }
+
+ final TextView spotted = details.add(R.string.trackable_spotted, text.toString());
+ spotted.setClickable(true);
+ if (Trackable.SPOTTED_CACHE == trackable.getSpottedType()) {
+ spotted.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ CacheDetailActivity.startActivityGuid(TrackableActivity.this, trackable.getSpottedGuid(), trackable.getSpottedName());
+ }
+ });
+ } else if (Trackable.SPOTTED_USER == trackable.getSpottedType()) {
+ spotted.setOnClickListener(new UserActionsListener());
+ }
+ }
+
+ // trackable origin
+ if (StringUtils.isNotBlank(trackable.getOrigin())) {
+ TextView origin = details.add(R.string.trackable_origin, "");
+ origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE);
+ }
+
+ // trackable released
+ if (trackable.getReleased() != null) {
+ details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()));
+ }
+
+ // trackable distance
+ if (trackable.getDistance() >= 0) {
+ details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()));
+ }
+
+ // trackable goal
+ if (StringUtils.isNotBlank(trackable.getGoal())) {
+ view.findViewById(R.id.goal_box).setVisibility(View.VISIBLE);
+ TextView descView = (TextView) view.findViewById(R.id.goal);
+ descView.setVisibility(View.VISIBLE);
+ descView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE);
+ descView.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
+ // trackable details
+ if (StringUtils.isNotBlank(trackable.getDetails())) {
+ view.findViewById(R.id.details_box).setVisibility(View.VISIBLE);
+ TextView descView = (TextView) view.findViewById(R.id.details);
+ descView.setVisibility(View.VISIBLE);
+ descView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE);
+ descView.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
+ // trackable image
+ if (StringUtils.isNotBlank(trackable.getImage())) {
+ view.findViewById(R.id.image_box).setVisibility(View.VISIBLE);
+ LinearLayout imgView = (LinearLayout) view.findViewById(R.id.image);
+
+ final ImageView trackableImage = (ImageView) inflater.inflate(R.layout.trackable_image, null);
+
+ trackableImage.setImageResource(R.drawable.image_not_loaded);
+ trackableImage.setClickable(true);
+ trackableImage.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View arg0) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getImage())));
+ }
+ });
+
+ // try to load image
+ final Handler handler = new Handler() {
+
+ @Override
+ public void handleMessage(Message message) {
+ BitmapDrawable image = (BitmapDrawable) message.obj;
+ if (image != null) {
+ trackableImage.setImageDrawable((BitmapDrawable) message.obj);
+ }
+ }
+ };
+
+ new Thread() {
+
+ @Override
+ public void run() {
+ try {
+ HtmlImage imgGetter = new HtmlImage(geocode, true, 0, false);
+
+ BitmapDrawable image = imgGetter.getDrawable(trackable.getImage());
+ Message message = handler.obtainMessage(0, image);
+ handler.sendMessage(message);
+ } catch (Exception e) {
+ Log.e("cgeospoilers.onCreate.onClick.run: ", e);
+ }
+ }
+ }.start();
+
+ imgView.addView(trackableImage);
+ }
+ return view;
+ }
+
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/VisitCacheActivity.java b/main/src/cgeo/geocaching/VisitCacheActivity.java
index 443ef3a..d77be5f 100644
--- a/main/src/cgeo/geocaching/VisitCacheActivity.java
+++ b/main/src/cgeo/geocaching/VisitCacheActivity.java
@@ -7,11 +7,11 @@ import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.enumerations.LogTypeTrackable;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.gcvote.GCVote;
-import cgeo.geocaching.network.Network;
+import cgeo.geocaching.loaders.UrlLoader;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.twitter.Twitter;
-import cgeo.geocaching.ui.DateDialog;
import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.dialog.DateDialog;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.LogTemplateProvider;
import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
@@ -19,14 +19,19 @@ import cgeo.geocaching.utils.LogTemplateProvider.LogContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
+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.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.view.ContextMenu;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.Loader;
+import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -42,134 +47,150 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
+import java.util.Locale;
-public class VisitCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent {
- static final String EXTRAS_FOUND = "found";
- static final String EXTRAS_TEXT = "text";
+public class VisitCacheActivity extends AbstractLoggingActivity implements DateDialog.DateDialogParent, LoaderManager.LoaderCallbacks<String> {
static final String EXTRAS_GEOCODE = "geocode";
static final String EXTRAS_ID = "id";
private static final int SUBMENU_VOTE = 3;
+ private static final String SAVED_STATE_RATING = "cgeo.geocaching.saved_state_rating";
+ private static final String SAVED_STATE_TYPE = "cgeo.geocaching.saved_state_type";
+ private static final String SAVED_STATE_DATE = "cgeo.geocaching.saved_state_date";
private LayoutInflater inflater = null;
- private cgCache cache = null;
+ private Geocache cache = null;
private ProgressDialog waitDialog = null;
private String cacheid = null;
private String geocode = null;
private String text = null;
- private boolean alreadyFound = false;
private List<LogType> possibleLogTypes = new ArrayList<LogType>();
private String[] viewstates = null;
- private boolean gettingViewstate = true;
private List<TrackableLog> trackables = null;
- private Calendar date = Calendar.getInstance();
- private LogType typeSelected = LogType.UNKNOWN;
- private int attempts = 0;
private Button postButton = null;
- private Button clearButton = null;
private CheckBox tweetCheck = null;
private LinearLayout tweetBox = null;
- private double rating = 0.0;
private boolean tbChanged = false;
+ private SparseArray<TrackableLog> actionButtons;
- // handlers
- private final Handler loadDataHandler = new Handler() {
+ // Data to be saved while reconfiguring
+ private double rating;
+ private LogType typeSelected;
+ private Calendar date;
- @Override
- public void handleMessage(Message msg) {
- if (!possibleLogTypes.contains(typeSelected)) {
- typeSelected = possibleLogTypes.get(0);
- setType(typeSelected);
+ @Override
+ public Loader<String> onCreateLoader(final int id, final Bundle args) {
+ if (!Settings.isLogin()) { // allow offline logging
+ showToast(res.getString(R.string.err_login));
+ return null;
+ }
+ return new UrlLoader(getBaseContext(), "http://www.geocaching.com/seek/log.aspx", new Parameters("ID", cacheid));
+ }
- showToast(res.getString(R.string.info_log_type_changed));
- }
+ @Override
+ public void onLoaderReset(final Loader<String> loader) {
+ // Nothing to do
+ }
- if (Login.isEmpty(viewstates)) {
- if (attempts < 2) {
- new LoadDataThread().start();
- } else {
- showToast(res.getString(R.string.err_log_load_data));
- showProgress(false);
- }
- return;
+ @Override
+ public void onLoadFinished(final Loader<String> loader, final String page) {
+ if (page == null) {
+ showToast(res.getString(R.string.err_log_load_data));
+ showProgress(false);
+ return;
+ }
+
+ viewstates = Login.getViewstates(page);
+ trackables = GCParser.parseTrackableLog(page);
+ possibleLogTypes = GCParser.parseTypes(page);
+ possibleLogTypes.remove(LogType.UPDATE_COORDINATES);
+
+ if (!possibleLogTypes.contains(typeSelected)) {
+ typeSelected = possibleLogTypes.get(0);
+ setType(typeSelected);
+
+ showToast(res.getString(R.string.info_log_type_changed));
+ }
+
+ enablePostButton(true);
+
+ initializeTrackablesAction();
+ updateTrackablesList();
+
+ showProgress(false);
+ }
+
+ private void initializeTrackablesAction() {
+ if (Settings.isTrackableAutoVisit()) {
+ for (TrackableLog trackable : trackables) {
+ trackable.action = LogTypeTrackable.VISITED;
+ tbChanged = true;
}
+ }
+ }
- gettingViewstate = false; // we're done, user can post log
+ private void updateTrackablesList() {
+ if (CollectionUtils.isEmpty(trackables)) {
+ return;
+ }
+ if (inflater == null) {
+ inflater = getLayoutInflater();
+ }
+ actionButtons = new SparseArray<TrackableLog>();
- enablePostButton(true);
+ final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory);
+ inventoryView.removeAllViews();
- // add trackables
- if (CollectionUtils.isNotEmpty(trackables)) {
- if (inflater == null) {
- inflater = getLayoutInflater();
- }
+ for (TrackableLog tb : trackables) {
+ LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.visit_trackable, null);
- final LinearLayout inventoryView = (LinearLayout) findViewById(R.id.inventory);
- inventoryView.removeAllViews();
+ ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode);
+ ((TextView) inventoryItem.findViewById(R.id.name)).setText(tb.name);
+ final TextView actionButton = (TextView) inventoryItem.findViewById(R.id.action);
+ actionButton.setId(tb.id);
+ actionButtons.put(actionButton.getId(), tb);
+ actionButton.setText(res.getString(tb.action.resourceId) + " ▼");
+ actionButton.setOnClickListener(new View.OnClickListener() {
- for (TrackableLog tb : trackables) {
- LinearLayout inventoryItem = (LinearLayout) inflater.inflate(R.layout.visit_trackable, null);
-
- ((TextView) inventoryItem.findViewById(R.id.trackcode)).setText(tb.trackCode);
- ((TextView) inventoryItem.findViewById(R.id.name)).setText(tb.name);
- ((TextView) inventoryItem.findViewById(R.id.action))
- .setText(res.getString(Settings.isTrackableAutoVisit()
- ? LogTypeTrackable.VISITED.resourceId
- : LogTypeTrackable.DO_NOTHING.resourceId)
- + " ▼");
-
- inventoryItem.setId(tb.id);
- final String tbCode = tb.trackCode;
- inventoryItem.setClickable(true);
- registerForContextMenu(inventoryItem);
- inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View view) {
- final Intent trackablesIntent = new Intent(VisitCacheActivity.this, cgeotrackable.class);
- trackablesIntent.putExtra(EXTRAS_GEOCODE, tbCode);
- startActivity(trackablesIntent);
- }
- });
- inventoryItem.findViewById(R.id.action).setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View view) {
- openContextMenu(view);
- }
- });
-
- inventoryView.addView(inventoryItem);
-
- if (Settings.isTrackableAutoVisit()) {
- tb.action = LogTypeTrackable.VISITED;
- tbChanged = true;
- }
+ @Override
+ public void onClick(View view) {
+ selectTrackableAction(view);
}
+ });
- if (inventoryView.getChildCount() > 0) {
- findViewById(R.id.inventory_box).setVisibility(View.VISIBLE);
+ final String tbCode = tb.trackCode;
+ inventoryItem.setClickable(true);
+ inventoryItem.findViewById(R.id.info).setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View view) {
+ final Intent trackablesIntent = new Intent(VisitCacheActivity.this, TrackableActivity.class);
+ trackablesIntent.putExtra(EXTRAS_GEOCODE, tbCode);
+ startActivity(trackablesIntent);
}
- if (inventoryView.getChildCount() > 1) {
- final LinearLayout inventoryChangeAllView = (LinearLayout) findViewById(R.id.inventory_changeall);
+ });
+
+ inventoryView.addView(inventoryItem);
+ }
- final Button changeButton = (Button) inventoryChangeAllView.findViewById(R.id.changebutton);
- registerForContextMenu(changeButton);
- changeButton.setOnClickListener(new View.OnClickListener() {
+ if (inventoryView.getChildCount() > 0) {
+ findViewById(R.id.inventory_box).setVisibility(View.VISIBLE);
+ }
+ if (inventoryView.getChildCount() > 1) {
+ final LinearLayout inventoryChangeAllView = (LinearLayout) findViewById(R.id.inventory_changeall);
- @Override
- public void onClick(View view) {
- openContextMenu(view);
- }
- });
+ final Button changeButton = (Button) inventoryChangeAllView.findViewById(R.id.changebutton);
+ changeButton.setOnClickListener(new View.OnClickListener() {
- inventoryChangeAllView.setVisibility(View.VISIBLE);
+ @Override
+ public void onClick(View view) {
+ selectAllTrackablesAction();
}
- }
+ });
- showProgress(false);
+ inventoryChangeAllView.setVisibility(View.VISIBLE);
}
- };
+ }
private void enablePostButton(boolean enabled) {
postButton.setEnabled(enabled);
@@ -184,20 +205,20 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
private void updatePostButtonText() {
- if (postButton.isEnabled()) {
- if (typeSelected == LogType.FOUND_IT && Settings.isGCvoteLogin()) {
- if (rating == 0) {
- postButton.setText(res.getString(R.string.log_post_no_rate));
- } else {
- postButton.setText(res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*");
- }
- } else {
- postButton.setText(res.getString(R.string.log_post));
- }
+ postButton.setText(getPostButtonText());
+ }
+
+ private String getPostButtonText() {
+ if (!postButton.isEnabled()) {
+ return res.getString(R.string.log_post_not_possible);
}
- else {
- postButton.setText(res.getString(R.string.log_post_not_possible));
+ if (typeSelected != LogType.FOUND_IT || !Settings.isGCvoteLogin()) {
+ return res.getString(R.string.log_post);
}
+ if (rating == 0) {
+ return res.getString(R.string.log_post_no_rate);
+ }
+ return res.getString(R.string.log_post_rate) + " " + ratingTextValue(rating) + "*";
}
private final Handler postLogHandler = new Handler() {
@@ -233,44 +254,140 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
@Override
- public void onCreate(Bundle savedInstanceState) {
+ public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme();
setContentView(R.layout.visit);
setTitle(res.getString(R.string.log_new_log));
- // get parameters
+ // Get parameters from intent and basic cache information from database
final Bundle extras = getIntent().getExtras();
if (extras != null) {
cacheid = extras.getString(EXTRAS_ID);
geocode = extras.getString(EXTRAS_GEOCODE);
- text = extras.getString(EXTRAS_TEXT);
- alreadyFound = extras.getBoolean(EXTRAS_FOUND);
}
if ((StringUtils.isBlank(cacheid)) && StringUtils.isNotBlank(geocode)) {
- cacheid = app.getCacheid(geocode);
+ cacheid = cgData.getCacheidForGeocode(geocode);
}
if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(cacheid)) {
- geocode = app.getGeocode(cacheid);
+ geocode = cgData.getGeocodeForGuid(cacheid);
}
- cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ possibleLogTypes = cache.getPossibleLogTypes();
if (StringUtils.isNotBlank(cache.getName())) {
setTitle(res.getString(R.string.log_new_log) + ": " + cache.getName());
} else {
- setTitle(res.getString(R.string.log_new_log) + ": " + cache.getGeocode().toUpperCase());
+ setTitle(res.getString(R.string.log_new_log) + ": " + cache.getGeocode());
+ }
+
+ // Get ids for later use
+ postButton = (Button) findViewById(R.id.post);
+ tweetBox = (LinearLayout) findViewById(R.id.tweet_box);
+ tweetCheck = (CheckBox) findViewById(R.id.tweet);
+
+ // initialize with default values
+ setDefaultValues();
+
+ // Restore previous state
+ if (savedInstanceState != null) {
+ rating = savedInstanceState.getDouble(SAVED_STATE_RATING);
+ typeSelected = LogType.getById(savedInstanceState.getInt(SAVED_STATE_TYPE));
+ date.setTimeInMillis(savedInstanceState.getLong(SAVED_STATE_DATE));
+ } else {
+ // If log had been previously saved, load it now, otherwise initialize signature as needed
+ final LogEntry log = cgData.loadLogOffline(geocode);
+ if (log != null) {
+ typeSelected = log.type;
+ date.setTime(new Date(log.date));
+ text = log.log;
+ } else if (StringUtils.isNotBlank(Settings.getSignature())
+ && Settings.isAutoInsertSignature()
+ && StringUtils.isBlank(currentLogText())) {
+ insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache)), false);
+ }
+ }
+ updatePostButtonText();
+ enablePostButton(false);
+
+ final Button typeButton = (Button) findViewById(R.id.type);
+ typeButton.setText(typeSelected.getL10n());
+ typeButton.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View view) {
+ selectLogType();
+ }
+ });
+
+ final Button dateButton = (Button) findViewById(R.id.date);
+ setDate(date);
+ dateButton.setOnClickListener(new DateListener());
+
+ final EditText logView = (EditText) findViewById(R.id.log);
+ if (StringUtils.isBlank(currentLogText()) && StringUtils.isNotBlank(text)) {
+ logView.setText(text);
}
- init();
+ tweetCheck.setChecked(true);
+
+ final Button saveButton = (Button) findViewById(R.id.save);
+ saveButton.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ saveLog(true);
+ }
+ });
+
+ final Button clearButton = (Button) findViewById(R.id.clear);
+ clearButton.setOnClickListener(new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ clearLog();
+ }
+ });
+
+ getSupportLoaderManager().initLoader(0, null, this);
}
- @Override
- public void onResume() {
- super.onResume();
+ private void setDefaultValues() {
+ date = Calendar.getInstance();
+ rating = 0.0;
+ if (cache.isEventCache()) {
+ if (cache.hasOwnLog(LogType.WILL_ATTEND)) {
+ typeSelected = LogType.ATTENDED;
+ }
+ else {
+ typeSelected = LogType.WILL_ATTEND;
+ }
+ }
+ else {
+ if (cache.isFound()) {
+ typeSelected = LogType.NOTE;
+ } else {
+ typeSelected = LogType.FOUND_IT;
+ }
+ }
+ text = null;
+ }
+
+ private void clearLog() {
+ cgData.clearLogOffline(geocode);
+
+ setDefaultValues();
+
+ setType(typeSelected);
+ setDate(date);
+
+ final EditText logView = (EditText) findViewById(R.id.log);
+ logView.setText(StringUtils.EMPTY);
+ showToast(res.getString(R.string.info_log_cleared));
}
@Override
@@ -280,13 +397,6 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- init();
- }
-
- @Override
public boolean onCreateOptionsMenu(final Menu menu) {
super.onCreateOptionsMenu(menu);
@@ -335,184 +445,15 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
private static String ratingTextValue(final double rating) {
- return String.format("%.1f", rating);
+ return String.format(Locale.getDefault(), "%.1f", rating);
}
@Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
- super.onCreateContextMenu(menu, view, info);
- final int viewId = view.getId();
-
- if (viewId == R.id.type) {
- for (final LogType typeOne : possibleLogTypes) {
- menu.add(viewId, typeOne.id, 0, typeOne.getL10n());
- Log.w("Adding " + typeOne + " " + typeOne.getL10n());
- }
- } else if (viewId == R.id.changebutton) {
- final int textId = findViewById(viewId).getId();
-
- menu.setHeaderTitle(res.getString(R.string.log_tb_changeall));
- for (LogTypeTrackable logType : LogTypeTrackable.values()) {
- menu.add(textId, logType.id, 0, res.getString(logType.resourceId));
- }
- } else {
- final int realViewId = findViewById(viewId).getId();
-
- for (final TrackableLog tb : trackables) {
- if (tb.id == realViewId) {
- menu.setHeaderTitle(tb.name);
- }
- }
- for (LogTypeTrackable logType : LogTypeTrackable.values()) {
- menu.add(realViewId, logType.id, 0, res.getString(logType.resourceId));
- }
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- final int group = item.getGroupId();
- final int id = item.getItemId();
-
- if (group == R.id.type) {
- setType(LogType.getById(id));
- return true;
- }
-
- if (group == R.id.changebutton) {
- try {
- final LogTypeTrackable logType = LogTypeTrackable.findById(id);
- if (logType != null) {
- final LinearLayout inventView = (LinearLayout) findViewById(R.id.inventory);
- for (int count = 0; count < inventView.getChildCount(); count++) {
- final LinearLayout tbView = (LinearLayout) inventView.getChildAt(count);
- if (tbView == null) {
- return false;
- }
-
- final TextView tbText = (TextView) tbView.findViewById(R.id.action);
- if (tbText == null) {
- return false;
- }
- tbText.setText(res.getString(logType.resourceId) + " ▼");
- }
- for (TrackableLog tb : trackables) {
- tb.action = logType;
- }
- tbChanged = true;
- return true;
- }
- } catch (Exception e) {
- Log.e("cgeovisit.onContextItemSelected: " + e.toString());
- }
- } else {
- try {
- final LogTypeTrackable logType = LogTypeTrackable.findById(id);
- if (logType != null) {
- final LinearLayout tbView = (LinearLayout) findViewById(group);
- if (tbView == null) {
- return false;
- }
-
- final TextView tbText = (TextView) tbView.findViewById(R.id.action);
- if (tbText == null) {
- return false;
- }
-
- for (TrackableLog tb : trackables) {
- if (tb.id == group) {
- tbChanged = true;
-
- tb.action = logType;
- tbText.setText(res.getString(logType.resourceId) + " ▼");
-
- Log.i("Trackable " + tb.trackCode + " (" + tb.name + ") has new action: #" + id);
- }
- }
-
- return true;
- }
- } catch (Exception e) {
- Log.e("cgeovisit.onContextItemSelected: " + e.toString());
- }
- }
-
- return false;
- }
-
- public void init() {
- postButton = (Button) findViewById(R.id.post);
- tweetBox = (LinearLayout) findViewById(R.id.tweet_box);
- tweetCheck = (CheckBox) findViewById(R.id.tweet);
- clearButton = (Button) findViewById(R.id.clear);
- final Button saveButton = (Button) findViewById(R.id.save);
-
- possibleLogTypes = cache.getPossibleLogTypes();
-
- final LogEntry log = app.loadLogOffline(geocode);
- if (log != null) {
- typeSelected = log.type;
- date.setTime(new Date(log.date));
- text = log.log;
- updatePostButtonText();
- } else if (StringUtils.isNotBlank(Settings.getSignature())
- && Settings.isAutoInsertSignature()
- && StringUtils.isBlank(((EditText) findViewById(R.id.log)).getText())) {
- insertIntoLog(LogTemplateProvider.applyTemplates(Settings.getSignature(), new LogContext(cache)), false);
- }
-
- if (!possibleLogTypes.contains(typeSelected)) {
- if (alreadyFound) {
- typeSelected = LogType.NOTE;
- } else {
- typeSelected = possibleLogTypes.get(0);
- }
- setType(typeSelected);
- }
-
- final Button typeButton = (Button) findViewById(R.id.type);
- registerForContextMenu(typeButton);
- typeButton.setText(typeSelected.getL10n());
- typeButton.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View view) {
- openContextMenu(view);
- }
- });
-
- final Button dateButton = (Button) findViewById(R.id.date);
- setDate(date);
- dateButton.setOnClickListener(new DateListener());
-
- final EditText logView = (EditText) findViewById(R.id.log);
- if (StringUtils.isBlank(logView.getText()) && StringUtils.isNotBlank(text)) {
- logView.setText(text);
- }
-
- tweetCheck.setChecked(true);
-
- final ActivityState lastState = (ActivityState) getLastNonConfigurationInstance();
- if (lastState != null) {
- lastState.restore(this);
- }
-
- if (Login.isEmpty(viewstates)) {
- enablePostButton(false);
- new LoadDataThread().start();
- } else {
- enablePostButton(true);
- }
-
- saveButton.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- saveLog(true);
- }
- });
-
- clearButton.setOnClickListener(new ClearListener());
+ protected void onSaveInstanceState(final Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putDouble(SAVED_STATE_RATING, rating);
+ outState.putInt(SAVED_STATE_TYPE, typeSelected.id);
+ outState.putLong(SAVED_STATE_DATE, date.getTimeInMillis());
}
@Override
@@ -554,102 +495,13 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
}
private class PostListener implements View.OnClickListener {
-
- @Override
- public void onClick(View arg0) {
- if (!gettingViewstate) {
- waitDialog = ProgressDialog.show(VisitCacheActivity.this, null, res.getString(R.string.log_saving), true);
- waitDialog.setCancelable(true);
-
- final String log = ((EditText) findViewById(R.id.log)).getText().toString();
- final Thread thread = new PostLogThread(postLogHandler, log);
- thread.start();
- } else {
- showToast(res.getString(R.string.err_log_load_data_still));
- }
- }
- }
-
- private class ClearListener implements View.OnClickListener {
-
@Override
public void onClick(View arg0) {
- //TODO: unify this method and the code in init()
- app.clearLogOffline(geocode);
-
- if (alreadyFound) {
- typeSelected = LogType.NOTE;
- } else {
- typeSelected = possibleLogTypes.get(0);
- }
- date.setTime(new Date());
- text = null;
-
- setType(typeSelected);
-
- final Button dateButton = (Button) findViewById(R.id.date);
- dateButton.setOnClickListener(new DateListener());
- setDate(date);
+ waitDialog = ProgressDialog.show(VisitCacheActivity.this, null, res.getString(R.string.log_saving), true);
+ waitDialog.setCancelable(true);
- final EditText logView = (EditText) findViewById(R.id.log);
- logView.setText("");
-
- clearButton.setOnClickListener(new ClearListener());
-
- showToast(res.getString(R.string.info_log_cleared));
- }
- }
-
- private class LoadDataThread extends Thread {
-
- public LoadDataThread() {
- super("Load data for logging");
- if (cacheid == null) {
- showToast(res.getString(R.string.err_detail_cache_forgot_visit));
-
- finish();
- return;
- }
- if (!Settings.isLogin()) { // allow offline logging
- showToast(res.getString(R.string.err_login));
- }
- }
-
- @Override
- public void run() {
- if (!Settings.isLogin()) {
- // enable only offline logging, don't get the current state of the cache
- return;
- }
- final Parameters params = new Parameters();
-
- gettingViewstate = true;
- attempts++;
-
- try {
- if (StringUtils.isNotBlank(cacheid)) {
- params.put("ID", cacheid);
- } else {
- loadDataHandler.sendEmptyMessage(0);
- return;
- }
-
- final String page = Network.getResponseData(Network.getRequest("http://www.geocaching.com/seek/log.aspx", params));
-
- viewstates = Login.getViewstates(page);
- trackables = GCParser.parseTrackableLog(page);
-
- final List<LogType> typesPre = GCParser.parseTypes(page);
- if (CollectionUtils.isNotEmpty(typesPre)) {
- possibleLogTypes.clear();
- possibleLogTypes.addAll(typesPre);
- possibleLogTypes.remove(LogType.UPDATE_COORDINATES);
- }
- } catch (Exception e) {
- Log.e("cgeovisit.loadData.run: " + e.toString());
- }
-
- loadDataHandler.sendEmptyMessage(0);
+ final Thread thread = new PostLogThread(postLogHandler, currentLogText());
+ thread.start();
}
}
@@ -680,17 +532,17 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
if (status == StatusCode.NO_ERROR) {
final LogEntry logNow = new LogEntry(date, typeSelected, log);
- cache.getLogs().prepend(logNow);
+ cache.getLogs().add(0, logNow);
if (typeSelected == LogType.FOUND_IT) {
cache.setFound(true);
}
- app.updateCache(cache);
+ cgData.saveChangedCache(cache);
}
if (status == StatusCode.NO_ERROR) {
- app.clearLogOffline(geocode);
+ cgData.clearLogOffline(geocode);
}
if (status == StatusCode.NO_ERROR && typeSelected == LogType.FOUND_IT && Settings.isUseTwitter()
@@ -705,7 +557,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
return status;
} catch (Exception e) {
- Log.e("cgeovisit.postLogFn: " + e.toString());
+ Log.e("cgeovisit.postLogFn", e);
}
return StatusCode.LOG_POST_ERROR;
@@ -717,7 +569,7 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
// Do not erase the saved log if the user has removed all the characters
// without using "Clear". This may be a manipulation mistake, and erasing
// again will be easy using "Clear" while retyping the text may not be.
- if (force || (log.length() > 0 && !StringUtils.equals(log, text))) {
+ if (force || (StringUtils.isNotEmpty(log) && !StringUtils.equals(log, text))) {
cache.logOffline(this, log, date, typeSelected);
}
text = log;
@@ -727,40 +579,76 @@ public class VisitCacheActivity extends AbstractLoggingActivity implements DateD
return ((EditText) findViewById(R.id.log)).getText().toString();
}
- private class ActivityState {
- private final String[] viewstates;
- private final List<TrackableLog> trackables;
- private final int attempts;
- private final List<LogType> possibleLogTypes;
- private final LogType typeSelected;
- private final double rating;
-
- public ActivityState() {
- this.viewstates = VisitCacheActivity.this.viewstates;
- this.trackables = VisitCacheActivity.this.trackables;
- this.attempts = VisitCacheActivity.this.attempts;
- this.possibleLogTypes = VisitCacheActivity.this.possibleLogTypes;
- this.typeSelected = VisitCacheActivity.this.typeSelected;
- this.rating = VisitCacheActivity.this.rating;
- }
-
- public void restore(final VisitCacheActivity activity) {
- activity.viewstates = this.viewstates;
- activity.trackables = this.trackables;
- activity.attempts = this.attempts;
- activity.possibleLogTypes = this.possibleLogTypes;
- activity.typeSelected = this.typeSelected;
- activity.rating = this.rating;
+ @Override
+ protected LogContext getLogContext() {
+ return new LogContext(cache);
+ }
+
+ private void selectAllTrackablesAction() {
+ Builder alert = new AlertDialog.Builder(this);
+ alert.setTitle(res.getString(R.string.log_tb_changeall));
+ String[] tbLogTypes = getTBLogTypes();
+ alert.setItems(tbLogTypes, new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int position) {
+ final LogTypeTrackable logType = LogTypeTrackable.values()[position];
+ for (TrackableLog tb : trackables) {
+ tb.action = logType;
+ }
+ tbChanged = true;
+ updateTrackablesList();
+ dialog.dismiss();
+ }
+ });
+ alert.create().show();
+ }
+
+ private String[] getTBLogTypes() {
+ final LogTypeTrackable[] logTypeValues = LogTypeTrackable.values();
+ String[] logTypes = new String[logTypeValues.length];
+ for (int i = 0; i < logTypes.length; i++) {
+ logTypes[i] = res.getString(logTypeValues[i].resourceId);
}
+ return logTypes;
}
- @Override
- public Object onRetainNonConfigurationInstance() {
- return new ActivityState();
+ private void selectLogType() {
+ Builder alert = new AlertDialog.Builder(this);
+ String[] choices = new String[possibleLogTypes.size()];
+ for (int i = 0; i < choices.length; i++) {
+ choices[i] = possibleLogTypes.get(i).getL10n();
+ }
+ alert.setSingleChoiceItems(choices, possibleLogTypes.indexOf(typeSelected), new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int position) {
+ setType(possibleLogTypes.get(position));
+ dialog.dismiss();
+ }
+ });
+ alert.create().show();
}
- @Override
- protected LogContext getLogContext() {
- return new LogContext(cache);
+ private void selectTrackableAction(View view) {
+ final int realViewId = view.getId();
+ Builder alert = new AlertDialog.Builder(this);
+ final TrackableLog trackableLog = actionButtons.get(realViewId);
+ alert.setTitle(trackableLog.name);
+ String[] tbLogTypes = getTBLogTypes();
+ alert.setItems(tbLogTypes, new OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int position) {
+ final LogTypeTrackable logType = LogTypeTrackable.values()[position];
+ tbChanged = true;
+ trackableLog.action = logType;
+ Log.i("Trackable " + trackableLog.trackCode + " (" + trackableLog.name + ") has new action: #" + logType);
+ updateTrackablesList();
+ dialog.dismiss();
+ }
+ });
+ alert.create().show();
}
+
}
diff --git a/main/src/cgeo/geocaching/cgWaypoint.java b/main/src/cgeo/geocaching/Waypoint.java
index 0e21c08..1d88c40 100644
--- a/main/src/cgeo/geocaching/cgWaypoint.java
+++ b/main/src/cgeo/geocaching/Waypoint.java
@@ -8,13 +8,15 @@ import org.apache.commons.lang3.StringUtils;
import android.content.res.Resources;
import android.widget.TextView;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
-public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
+public class Waypoint implements IWaypoint, Comparable<Waypoint> {
public static final String PREFIX_OWN = "OWN";
private static final int ORDER_UNDEFINED = -2;
- private int id = 0;
+ private int id = -1;
private String geocode = "geocode";
private WaypointType waypointType = WaypointType.WAYPOINT;
private String prefix = "";
@@ -32,7 +34,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
* @param name
* @param type
*/
- public cgWaypoint(final String name, final WaypointType type, final boolean own) {
+ public Waypoint(final String name, final WaypointType type, final boolean own) {
this.name = name;
this.waypointType = type;
this.own = own;
@@ -43,17 +45,17 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
*
* @param other
*/
- public cgWaypoint(final cgWaypoint other) {
+ public Waypoint(final Waypoint other) {
merge(other);
this.waypointType = other.waypointType;
- id = 0;
+ id = -1;
}
public void setIcon(final Resources res, final TextView nameView) {
nameView.setCompoundDrawablesWithIntrinsicBounds(res.getDrawable(waypointType.markerId), null, null, null);
}
- public void merge(final cgWaypoint old) {
+ public void merge(final Waypoint old) {
if (StringUtils.isBlank(prefix)) {
setPrefix(old.prefix);
}
@@ -77,31 +79,25 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
note = old.note;
}
}
+ if (id < 0) {
+ id = old.id;
+ }
}
- public static void mergeWayPoints(List<cgWaypoint> newPoints,
- List<cgWaypoint> oldPoints, boolean forceMerge) {
- // copy user modified details of the waypoints
- if (newPoints != null && oldPoints != null) {
- for (cgWaypoint old : oldPoints) {
- if (old != null) {
- boolean merged = false;
- if (old.name != null && old.name.length() > 0) {
- for (cgWaypoint waypoint : newPoints) {
- if (waypoint != null && waypoint.name != null) {
- if (old.name.equalsIgnoreCase(waypoint.name)) {
- waypoint.merge(old);
- merged = true;
- break;
- }
- }
- }
- }
- // user added waypoints should also be in the new list
- if (!merged && (old.isUserDefined() || forceMerge)) {
- newPoints.add(old);
- }
- }
+ public static void mergeWayPoints(final List<Waypoint> newPoints, final List<Waypoint> oldPoints, final boolean forceMerge) {
+ // Build a map of new waypoints for faster subsequent lookups
+ final Map<String, Waypoint> newPrefixes = new HashMap<String, Waypoint>(newPoints.size());
+ for (final Waypoint waypoint : newPoints) {
+ newPrefixes.put(waypoint.getPrefix(), waypoint);
+ }
+
+ // Copy user modified details of the old waypoints over the new ones
+ for (final Waypoint oldWaypoint : oldPoints) {
+ final String prefix = oldWaypoint.getPrefix();
+ if (newPrefixes.containsKey(prefix)) {
+ newPrefixes.get(prefix).merge(oldWaypoint);
+ } else if (oldWaypoint.isUserDefined() || forceMerge) {
+ newPoints.add(oldWaypoint);
}
}
}
@@ -142,7 +138,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
}
@Override
- public int compareTo(cgWaypoint other) {
+ public int compareTo(Waypoint other) {
return order() - other.order();
}
@@ -156,7 +152,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
}
public String getUrl() {
- return "http://www.geocaching.com//seek/cache_details.aspx?wp=" + geocode.toUpperCase();
+ return "http://www.geocaching.com//seek/cache_details.aspx?wp=" + geocode;
}
@Override
@@ -174,7 +170,7 @@ public class cgWaypoint implements IWaypoint, Comparable<cgWaypoint> {
}
public void setGeocode(String geocode) {
- this.geocode = geocode;
+ this.geocode = StringUtils.upperCase(geocode);
}
@Override
diff --git a/main/src/cgeo/geocaching/WaypointPopup.java b/main/src/cgeo/geocaching/WaypointPopup.java
index 7fbfe10..766d43d 100644
--- a/main/src/cgeo/geocaching/WaypointPopup.java
+++ b/main/src/cgeo/geocaching/WaypointPopup.java
@@ -17,9 +17,8 @@ import android.widget.LinearLayout;
import android.widget.TextView;
public class WaypointPopup extends AbstractPopupActivity {
- private static final String EXTRA_WAYPOINT_ID = "waypoint_id";
private int waypointId = 0;
- private cgWaypoint waypoint = null;
+ private Waypoint waypoint = null;
public WaypointPopup() {
super("c:geo-waypoint-info", R.layout.waypoint_popup);
@@ -31,19 +30,19 @@ public class WaypointPopup extends AbstractPopupActivity {
// get parameters
final Bundle extras = getIntent().getExtras();
if (extras != null) {
- waypointId = extras.getInt(EXTRA_WAYPOINT_ID);
+ waypointId = extras.getInt(Intents.EXTRA_WAYPOINT_ID);
}
}
@Override
protected void init() {
super.init();
- waypoint = app.loadWaypoint(waypointId);
+ waypoint = cgData.loadWaypoint(waypointId);
try {
if (StringUtils.isNotBlank(waypoint.getName())) {
setTitle(waypoint.getName());
} else {
- setTitle(waypoint.getGeocode().toUpperCase());
+ setTitle(waypoint.getGeocode());
}
// actionbar icon
@@ -53,7 +52,7 @@ public class WaypointPopup extends AbstractPopupActivity {
details = new CacheDetailsCreator(this, (LinearLayout) findViewById(R.id.waypoint_details_list));
//Waypoint geocode
- details.add(R.string.cache_geocode, waypoint.getPrefix().toUpperCase() + waypoint.getGeocode().toUpperCase().substring(2));
+ details.add(R.string.cache_geocode, waypoint.getPrefix() + waypoint.getGeocode().substring(2));
// Edit Button
final Button buttonEdit = (Button) findViewById(R.id.edit);
@@ -73,7 +72,7 @@ public class WaypointPopup extends AbstractPopupActivity {
addCacheDetails();
} catch (Exception e) {
- Log.e("cgeopopup.init: " + e.toString());
+ Log.e("cgeopopup.init", e);
}
}
@@ -83,7 +82,7 @@ public class WaypointPopup extends AbstractPopupActivity {
}
/**
- * Tries to navigate to the {@link cgCache} of this activity.
+ * Tries to navigate to the {@link Geocache} of this activity.
*/
@Override
protected void startDefaultNavigation2() {
@@ -97,8 +96,8 @@ public class WaypointPopup extends AbstractPopupActivity {
public static void startActivity(final Context context, final int waypointId, final String geocode) {
final Intent popupIntent = new Intent(context, WaypointPopup.class);
- popupIntent.putExtra(EXTRA_WAYPOINT_ID, waypointId);
- popupIntent.putExtra(EXTRA_GEOCODE, geocode);
+ popupIntent.putExtra(Intents.EXTRA_WAYPOINT_ID, waypointId);
+ popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);
context.startActivity(popupIntent);
}
diff --git a/main/src/cgeo/geocaching/activity/AbstractActivity.java b/main/src/cgeo/geocaching/activity/AbstractActivity.java
index a648486..557665e 100644
--- a/main/src/cgeo/geocaching/activity/AbstractActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractActivity.java
@@ -5,16 +5,16 @@ import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.network.Cookies;
-import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.EditText;
-public abstract class AbstractActivity extends Activity implements IAbstractActivity {
+public abstract class AbstractActivity extends FragmentActivity implements IAbstractActivity {
- private String helpTopic;
+ final private String helpTopic;
protected cgeoapplication app = null;
protected Resources res = null;
diff --git a/main/src/cgeo/geocaching/activity/AbstractListActivity.java b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
index dc9c0fe..f96a769 100644
--- a/main/src/cgeo/geocaching/activity/AbstractListActivity.java
+++ b/main/src/cgeo/geocaching/activity/AbstractListActivity.java
@@ -3,13 +3,13 @@ package cgeo.geocaching.activity;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.compatibility.Compatibility;
-import android.app.ListActivity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.support.v4.app.FragmentListActivity;
import android.view.View;
-public abstract class AbstractListActivity extends ListActivity implements
+public abstract class AbstractListActivity extends FragmentListActivity implements
IAbstractActivity {
private String helpTopic;
diff --git a/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
new file mode 100644
index 0000000..366a59d
--- /dev/null
+++ b/main/src/cgeo/geocaching/activity/AbstractViewPagerActivity.java
@@ -0,0 +1,276 @@
+package cgeo.geocaching.activity;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.utils.Log;
+
+import com.viewpagerindicator.TitlePageIndicator;
+import com.viewpagerindicator.TitleProvider;
+
+import org.apache.commons.lang3.tuple.Pair;
+
+import android.app.Activity;
+import android.os.Parcelable;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v4.view.ViewPager.OnPageChangeListener;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstract activity with the ability to manage pages in a view pager.
+ *
+ * @param <Page>
+ * Enum listing all available pages of this activity. The pages available at a certain point of time are
+ * defined by overriding {@link #getOrderedPages()}.
+ */
+public abstract class AbstractViewPagerActivity<Page extends Enum<Page>> extends AbstractActivity {
+
+ protected AbstractViewPagerActivity(String helpTopic) {
+ super(helpTopic);
+ }
+
+ /**
+ * A {@link List} of all available pages.
+ *
+ * TODO Move to adapter
+ */
+ private final List<Page> pageOrder = new ArrayList<Page>();
+
+ /**
+ * Instances of all {@link PageViewCreator}.
+ */
+ private final Map<Page, PageViewCreator> viewCreators = new HashMap<Page, PageViewCreator>();
+
+ /**
+ * The {@link ViewPager} for this activity.
+ */
+ private ViewPager viewPager;
+
+ /**
+ * The {@link ViewPagerAdapter} for this activity.
+ */
+ private ViewPagerAdapter viewPagerAdapter;
+
+ /**
+ * The {@link TitlePageIndicator} for this activity.
+ */
+ private TitlePageIndicator titleIndicator;
+
+ public interface PageViewCreator {
+ /**
+ * Returns a validated view.
+ *
+ * @return
+ */
+ public View getDispatchedView();
+
+ /**
+ * Returns a (maybe cached) view.
+ *
+ * @return
+ */
+ public View getView();
+
+ /**
+ * Handles changed data-sets.
+ */
+ public void notifyDataSetChanged();
+ }
+
+ /**
+ * Page selection interface for the view pager.
+ *
+ */
+ protected interface OnPageSelectedListener {
+ public void onPageSelected(int position);
+ }
+
+ /**
+ * The ViewPagerAdapter for scrolling through pages of the CacheDetailActivity.
+ */
+ private class ViewPagerAdapter extends PagerAdapter implements TitleProvider {
+
+ @Override
+ public void destroyItem(View container, int position, Object object) {
+ ((ViewPager) container).removeView((View) object);
+ }
+
+ @Override
+ public void finishUpdate(View container) {
+ }
+
+ @Override
+ public int getCount() {
+ return pageOrder.size();
+ }
+
+ @Override
+ public Object instantiateItem(View container, int position) {
+ final Page page = pageOrder.get(position);
+
+ PageViewCreator creator = viewCreators.get(page);
+
+ if (null == creator && null != page) {
+ creator = AbstractViewPagerActivity.this.createViewCreator(page);
+ viewCreators.put(page, creator);
+ }
+
+ View view = null;
+
+ try {
+ if (null != creator) {
+ // Result from getView() is maybe cached, but it should be valid because the
+ // creator should be informed about data-changes with notifyDataSetChanged()
+ view = creator.getView();
+ ((ViewPager) container).addView(view, 0);
+ }
+ } catch (Exception e) {
+ Log.e("ViewPagerAdapter.instantiateItem ", e);
+ }
+
+ return view;
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == object;
+ }
+
+ @Override
+ public void restoreState(Parcelable arg0, ClassLoader arg1) {
+ }
+
+ @Override
+ public Parcelable saveState() {
+ return null;
+ }
+
+ @Override
+ public void startUpdate(View arg0) {
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ // We are doing the caching. So pretend that the view is gone.
+ // The ViewPager will get it back in instantiateItem()
+ return POSITION_NONE;
+ }
+
+ @Override
+ public String getTitle(int position) {
+ final Page page = pageOrder.get(position);
+ if (null == page) {
+ return "";
+ }
+ return AbstractViewPagerActivity.this.getTitle(page);
+ }
+
+ }
+
+ /**
+ * Create the view pager. Call this from the {@link Activity#onCreate} implementation.
+ *
+ * @param startPageIndex
+ * index of the page shown first
+ * @param pageSelectedListener
+ * page selection listener or <code>null</code>
+ */
+ protected final void createViewPager(int startPageIndex, final OnPageSelectedListener pageSelectedListener) {
+ // initialize ViewPager
+ viewPager = (ViewPager) findViewById(R.id.viewpager);
+ viewPagerAdapter = new ViewPagerAdapter();
+ viewPager.setAdapter(viewPagerAdapter);
+
+ titleIndicator = (TitlePageIndicator) findViewById(R.id.pager_indicator);
+ titleIndicator.setViewPager(viewPager);
+ if (pageSelectedListener != null) {
+ titleIndicator.setOnPageChangeListener(new OnPageChangeListener() {
+ @Override
+ public void onPageSelected(int position) {
+ pageSelectedListener.onPageSelected(position);
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+ });
+ }
+
+ // switch to entry page (last used or 2)
+ if (viewPagerAdapter.getCount() < startPageIndex) {
+ for (int i = 0; i <= startPageIndex; i++) {
+ // we can't switch to a page that is out of bounds, so we add null-pages
+ pageOrder.add(null);
+ }
+ }
+ viewPager.setCurrentItem(startPageIndex, false);
+ }
+
+ /**
+ * create the view creator for the given page
+ *
+ * @return new view creator
+ */
+ protected abstract PageViewCreator createViewCreator(Page page);
+
+ /**
+ * get the title for the given page
+ */
+ protected abstract String getTitle(Page page);
+
+ protected final void reinitializeViewPager() {
+ // notify all creators that the data has changed
+ for (PageViewCreator creator : viewCreators.values()) {
+ creator.notifyDataSetChanged();
+ }
+
+ pageOrder.clear();
+ final Pair<List<? extends Page>, Integer> pagesAndIndex = getOrderedPages();
+ pageOrder.addAll(pagesAndIndex.getLeft());
+
+ // switch to details page, if we're out of bounds
+ final int defaultPage = pagesAndIndex.getRight();
+ if (getCurrentItem() < 0 || getCurrentItem() >= viewPagerAdapter.getCount()) {
+ viewPager.setCurrentItem(defaultPage, false);
+ }
+
+ // notify the adapter that the data has changed
+ viewPagerAdapter.notifyDataSetChanged();
+
+ // notify the indicator that the data has changed
+ titleIndicator.notifyDataSetChanged();
+ }
+
+ /**
+ * @return the currently available list of ordered pages, together with the index of the default page
+ */
+ protected abstract Pair<List<? extends Page>, Integer> getOrderedPages();
+
+ public final Page getPage(int position) {
+ return pageOrder.get(position);
+ }
+
+ protected final int getPageIndex(Page page) {
+ return pageOrder.indexOf(page);
+ }
+
+ protected final PageViewCreator getViewCreator(Page page) {
+ return viewCreators.get(page);
+ }
+
+ protected final boolean isCurrentPage(Page page) {
+ return getCurrentItem() == getPageIndex(page);
+ }
+
+ protected int getCurrentItem() {
+ return viewPager.getCurrentItem();
+ }
+}
diff --git a/main/src/cgeo/geocaching/activity/FilteredActivity.java b/main/src/cgeo/geocaching/activity/FilteredActivity.java
new file mode 100644
index 0000000..0370d63
--- /dev/null
+++ b/main/src/cgeo/geocaching/activity/FilteredActivity.java
@@ -0,0 +1,11 @@
+package cgeo.geocaching.activity;
+
+import android.view.View;
+
+public interface FilteredActivity {
+ /**
+ * called from the filter bar view
+ */
+ public void showFilterMenu(final View view);
+
+}
diff --git a/main/src/cgeo/geocaching/activity/Progress.java b/main/src/cgeo/geocaching/activity/Progress.java
index 1aa1942..34e7623 100644
--- a/main/src/cgeo/geocaching/activity/Progress.java
+++ b/main/src/cgeo/geocaching/activity/Progress.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.activity;
-import cgeo.geocaching.ui.CustomProgressDialog;
+import cgeo.geocaching.ui.dialog.CustomProgressDialog;
import android.app.ProgressDialog;
import android.content.Context;
diff --git a/main/src/cgeo/geocaching/apps/AbstractApp.java b/main/src/cgeo/geocaching/apps/AbstractApp.java
index 678b98c..c95e8b4 100644
--- a/main/src/cgeo/geocaching/apps/AbstractApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractApp.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.apps;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.cgeo;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.utils.ProcessUtils;
@@ -56,7 +56,7 @@ public abstract class AbstractApp implements App {
}
@Override
- public boolean isEnabled(cgCache cache) {
+ public boolean isEnabled(Geocache cache) {
return cache != null;
}
}
diff --git a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
index ac6fc1c..53620e4 100644
--- a/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
+++ b/main/src/cgeo/geocaching/apps/AbstractLocusApp.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -22,6 +22,7 @@ import android.location.Location;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
/**
* for the Locus API:
@@ -30,7 +31,7 @@ import java.util.List;
*/
public abstract class AbstractLocusApp extends AbstractApp {
private static final String INTENT = Intent.ACTION_VIEW;
- private static final SimpleDateFormat ISO8601DATE = new SimpleDateFormat("yyyy-MM-dd'T'");
+ private static final SimpleDateFormat ISO8601DATE = new SimpleDateFormat("yyyy-MM-dd'T'", Locale.US);
protected AbstractLocusApp() {
super(getString(R.string.caches_map_locus), INTENT);
@@ -47,11 +48,11 @@ public abstract class AbstractLocusApp extends AbstractApp {
/**
* Display a list of caches / waypoints in Locus
- *
+ *
* @param objectsToShow
* which caches/waypoints to show
* @param withCacheWaypoints
- * wether to give waypoints of caches to Locus or not
+ * Whether to give waypoints of caches to Locus or not
* @param activity
*/
protected static boolean showInLocus(final List<?> objectsToShow, final boolean withCacheWaypoints, final boolean export,
@@ -65,10 +66,10 @@ public abstract class AbstractLocusApp extends AbstractApp {
for (Object o : objectsToShow) {
Point p = null;
// get icon and Point
- if (o instanceof cgCache) {
- p = getCachePoint((cgCache) o, withCacheWaypoints, withCacheDetails);
- } else if (o instanceof cgWaypoint) {
- p = getWaypointPoint((cgWaypoint) o);
+ if (o instanceof Geocache) {
+ p = getCachePoint((Geocache) o, withCacheWaypoints, withCacheDetails);
+ } else if (o instanceof Waypoint) {
+ p = getWaypointPoint((Waypoint) o);
}
if (p != null) {
pd.addPoint(p);
@@ -85,7 +86,7 @@ public abstract class AbstractLocusApp extends AbstractApp {
final ArrayList<PointsData> data = new ArrayList<PointsData>();
data.add(pd);
DisplayData.sendDataCursor(activity, data,
- "content://" + LocusDataStorageProvider.class.getCanonicalName().toLowerCase(),
+ "content://" + LocusDataStorageProvider.class.getCanonicalName().toLowerCase(Locale.US),
export);
}
@@ -103,7 +104,7 @@ public abstract class AbstractLocusApp extends AbstractApp {
* should be false for all if more then 200 Caches are transferred
* @return null, when the <code>Point</code> could not be constructed
*/
- private static Point getCachePoint(cgCache cache, boolean withWaypoints, boolean withCacheDetails) {
+ private static Point getCachePoint(Geocache cache, boolean withWaypoints, boolean withCacheDetails) {
if (cache == null || cache.getCoords() == null) {
return null;
}
@@ -145,7 +146,7 @@ public abstract class AbstractLocusApp extends AbstractApp {
if (withWaypoints && cache.hasWaypoints()) {
pg.waypoints = new ArrayList<PointGeocachingDataWaypoint>();
- for (cgWaypoint waypoint : cache.getWaypoints()) {
+ for (Waypoint waypoint : cache.getWaypoints()) {
if (waypoint == null || waypoint.getCoords() == null) {
continue;
}
@@ -181,7 +182,7 @@ public abstract class AbstractLocusApp extends AbstractApp {
* @param waypoint
* @return null, when the <code>Point</code> could not be constructed
*/
- private static Point getWaypointPoint(cgWaypoint waypoint) {
+ private static Point getWaypointPoint(Waypoint waypoint) {
if (waypoint == null || waypoint.getCoords() == null) {
return null;
}
diff --git a/main/src/cgeo/geocaching/apps/App.java b/main/src/cgeo/geocaching/apps/App.java
index 9d6d371..bc99526 100644
--- a/main/src/cgeo/geocaching/apps/App.java
+++ b/main/src/cgeo/geocaching/apps/App.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.apps;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
public interface App {
public boolean isInstalled();
@@ -17,5 +17,5 @@ public interface App {
* @param cache
* @return
*/
- boolean isEnabled(final cgCache cache);
+ boolean isEnabled(final Geocache cache);
}
diff --git a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java b/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java
index 6897f95..03954f5 100644
--- a/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java
+++ b/main/src/cgeo/geocaching/apps/LocusDataStorageProvider.java
@@ -4,16 +4,12 @@ import menion.android.locus.addon.publiclib.geoData.PointsData;
import menion.android.locus.addon.publiclib.utils.DataCursor;
import menion.android.locus.addon.publiclib.utils.DataStorage;
-import org.apache.commons.collections.CollectionUtils;
-
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
-import java.util.ArrayList;
-
/**
* code provided by menion - developer of Locus
*/
@@ -23,20 +19,14 @@ public class LocusDataStorageProvider extends ContentProvider {
public Cursor query(Uri aUri, String[] aProjection, String aSelection,
String[] aSelectionArgs, String aSortOrder) {
- DataCursor cursor = new DataCursor(new String[] { "data" });
-
- ArrayList<PointsData> data = DataStorage.getData();
- if (CollectionUtils.isEmpty(data)) {
- return cursor;
- }
+ final DataCursor cursor = new DataCursor(new String[] { "data" });
- for (int i = 0; i < data.size(); i++) {
- // get byte array
- Parcel par = Parcel.obtain();
- data.get(i).writeToParcel(par, 0);
- byte[] byteData = par.marshall();
- // add to row
- cursor.addRow(new Object[] { byteData });
+ for (final PointsData item : DataStorage.getData()) {
+ final Parcel par = Parcel.obtain();
+ item.writeToParcel(par, 0);
+ // add byte array to row
+ cursor.addRow(new Object[] { par.marshall() });
+ par.recycle();
}
// data filled to cursor, clear reference to prevent some memory issue
DataStorage.clearData();
diff --git a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java
index 61528ea..fd7d4b5 100644
--- a/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/AbstractGeneralApp.java
@@ -1,25 +1,24 @@
package cgeo.geocaching.apps.cache;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.AbstractApp;
+import cgeo.geocaching.apps.cache.navi.CacheNavigationApp;
import android.app.Activity;
import android.content.Intent;
-abstract class AbstractGeneralApp extends AbstractApp implements GeneralApp {
+abstract class AbstractGeneralApp extends AbstractApp implements CacheNavigationApp {
protected AbstractGeneralApp(String name, String packageName) {
super(name, null, packageName);
}
@Override
- public boolean invoke(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
final Intent intent = getLaunchIntent();
if (intent != null) {
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.startActivity(intent);
- return true;
}
- return false;
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
index 6e7cdca..9cfafb4 100644
--- a/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/CacheBeaconApp.java
@@ -1,21 +1,18 @@
package cgeo.geocaching.apps.cache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.enumerations.CacheAttribute;
public class CacheBeaconApp extends AbstractGeneralApp {
- protected CacheBeaconApp() {
+ public CacheBeaconApp() {
super(getString(R.string.cache_menu_cachebeacon), "de.fun2code.android.cachebeacon");
}
@Override
- public boolean isEnabled(cgCache cache) {
- if (cache == null) {
- return false;
- }
- return cache.hasAttribute(CacheAttribute.WIRELESS_BEACON, true);
+ public boolean isEnabled(Geocache cache) {
+ return cache.hasAttribute(CacheAttribute.WIRELESSBEACON, true);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/GccApp.java b/main/src/cgeo/geocaching/apps/cache/GccApp.java
index 9000d9e..b129b45 100644
--- a/main/src/cgeo/geocaching/apps/cache/GccApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/GccApp.java
@@ -2,8 +2,8 @@ package cgeo.geocaching.apps.cache;
import cgeo.geocaching.R;
-class GccApp extends AbstractGeneralApp {
- GccApp() {
+public class GccApp extends AbstractGeneralApp {
+ public GccApp() {
super(getString(R.string.cache_menu_gcc), "eisbehr.gcc");
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/GeneralApp.java b/main/src/cgeo/geocaching/apps/cache/GeneralApp.java
deleted file mode 100644
index cdbedd5..0000000
--- a/main/src/cgeo/geocaching/apps/cache/GeneralApp.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package cgeo.geocaching.apps.cache;
-
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.apps.App;
-
-import android.app.Activity;
-
-interface GeneralApp extends App {
-
- public boolean invoke(Activity activity, cgCache cache);
-
-}
diff --git a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java b/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java
deleted file mode 100644
index 57eb957..0000000
--- a/main/src/cgeo/geocaching/apps/cache/GeneralAppsFactory.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cgeo.geocaching.apps.cache;
-
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.apps.AbstractAppFactory;
-import cgeo.geocaching.utils.Log;
-
-import org.apache.commons.lang3.ArrayUtils;
-
-import android.app.Activity;
-import android.view.Menu;
-import android.view.MenuItem;
-
-public final class GeneralAppsFactory extends AbstractAppFactory {
- private static GeneralApp[] apps = new GeneralApp[] {};
-
- private static GeneralApp[] getGeneralApps() {
- if (ArrayUtils.isEmpty(apps)) {
- apps = new GeneralApp[] {
- new CacheBeaconApp(),
- new GccApp(),
- new WhereYouGoApp()
- };
- }
- return apps;
- }
-
- public static void addMenuItems(Menu menu, cgCache cache) {
- for (GeneralApp app : getGeneralApps()) {
- if (app.isInstalled() && app.isEnabled(cache)) {
- menu.add(0, app.getId(), 0, app.getName());
- }
- }
- }
-
- public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgCache cache) {
- final GeneralApp app = (GeneralApp) getAppFromMenuItem(item, apps);
- if (app == null) {
- return false;
- }
- try {
- app.invoke(activity, cache);
- } catch (Exception e) {
- Log.e("GeneralAppsFactory.onMenuItemSelected: " + e.toString());
- }
- return true;
- }
-
-}
diff --git a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
index 8c16eaf..39e1963 100644
--- a/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/WhereYouGoApp.java
@@ -1,16 +1,16 @@
package cgeo.geocaching.apps.cache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheType;
-class WhereYouGoApp extends AbstractGeneralApp {
- WhereYouGoApp() {
+public class WhereYouGoApp extends AbstractGeneralApp {
+ public WhereYouGoApp() {
super(getString(R.string.cache_menu_whereyougo), "menion.android.whereyougo");
}
@Override
- public boolean isEnabled(cgCache cache) {
- return cache != null && cache.getType() == CacheType.WHERIGO;
+ public boolean isEnabled(Geocache cache) {
+ return cache.getType() == CacheType.WHERIGO;
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java
deleted file mode 100644
index 27cb47c..0000000
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractNavigationApp.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package cgeo.geocaching.apps.cache.navi;
-
-import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.apps.AbstractApp;
-import cgeo.geocaching.geopoint.Geopoint;
-
-abstract class AbstractNavigationApp extends AbstractApp implements NavigationApp {
-
- protected AbstractNavigationApp(String name, String intent, String packageName) {
- super(name, intent, packageName);
- }
-
- protected AbstractNavigationApp(String name, String intent) {
- super(name, intent);
- }
-
- @Override
- public boolean isEnabled(cgWaypoint waypoint) {
- return waypoint != null;
- }
-
- @Override
- public boolean isEnabled(Geopoint geopoint) {
- return geopoint != null;
- }
-}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
index ca8c7db..a3ea57e 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractPointNavigationApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps.cache.navi;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.apps.AbstractApp;
import android.app.Activity;
@@ -20,22 +20,22 @@ abstract class AbstractPointNavigationApp extends AbstractApp implements CacheNa
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
navigate(activity, cache.getCoords());
}
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
navigate(activity, waypoint.getCoords());
}
@Override
- public boolean isEnabled(cgCache cache) {
+ public boolean isEnabled(Geocache cache) {
return cache.getCoords() != null;
}
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return waypoint.getCoords() != null;
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
index f27b53c..d089e82 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/AbstractStaticMapsApp.java
@@ -4,9 +4,9 @@ import cgeo.geocaching.ILogable;
import cgeo.geocaching.R;
import cgeo.geocaching.StaticMapsActivity;
import cgeo.geocaching.StaticMapsProvider;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractApp;
@@ -15,7 +15,7 @@ import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNavigationApp {
- public AbstractStaticMapsApp(String name) {
+ protected AbstractStaticMapsApp(String name) {
super(name, null);
}
@@ -29,18 +29,19 @@ abstract class AbstractStaticMapsApp extends AbstractApp implements CacheNavigat
return false;
}
- protected static boolean hasStaticMap(cgWaypoint waypoint) {
- if (waypoint==null)
+ protected static boolean hasStaticMap(Waypoint waypoint) {
+ if (waypoint==null) {
return false;
+ }
String geocode = waypoint.getGeocode();
int id = waypoint.getId();
- if (StringUtils.isNotEmpty(geocode) && cgeoapplication.getInstance().isOffline(geocode, null)) {
+ if (StringUtils.isNotEmpty(geocode) && cgData.isOffline(geocode, null)) {
return StaticMapsProvider.hasStaticMapForWaypoint(geocode, id);
}
return false;
}
- protected static boolean invokeStaticMaps(final Activity activity, final cgCache cache, final cgWaypoint waypoint, final boolean download) {
+ protected static boolean invokeStaticMaps(final Activity activity, final Geocache cache, final Waypoint waypoint, final boolean download) {
final ILogable logable = cache != null && cache.getListId() != 0 ? cache : waypoint;
// If the cache is not stored for offline, cache seems to be null and waypoint may be null too
if (logable==null || logable.getGeocode()==null ) {
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java
index e47150f..d47bdc0 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/CacheNavigationApp.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.apps.cache.navi;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.App;
import android.app.Activity;
@@ -10,8 +10,8 @@ import android.app.Activity;
*
*/
public interface CacheNavigationApp extends App {
- void navigate(final Activity activity, final cgCache cache);
+ void navigate(final Activity activity, final Geocache cache);
@Override
- boolean isEnabled(final cgCache cache);
+ boolean isEnabled(final Geocache cache);
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
index 5275d53..1ded9ac 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/CompassApp.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgeonavigate;
import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.geopoint.Geopoint;
@@ -27,24 +27,24 @@ class CompassApp extends AbstractApp implements CacheNavigationApp, WaypointNavi
}
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
cgeonavigate.startActivity(activity, waypoint.getPrefix() + "/" + waypoint.getLookup(), waypoint.getName(), waypoint.getCoords(), null,
waypoint.getWaypointType().getL10n());
}
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return waypoint.getCoords() != null;
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
cgeonavigate.startActivity(activity, cache.getGeocode(), cache.getName(), cache.getCoords(), null,
Formatter.formatCacheInfoShort(cache));
}
@Override
- public boolean isEnabled(cgCache cache) {
+ public boolean isEnabled(Geocache cache) {
return cache.getGeocode() != null;
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
index faf3c36..bc422d4 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/DownloadStaticMapsApp.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import android.app.Activity;
@@ -13,22 +13,22 @@ class DownloadStaticMapsApp extends AbstractStaticMapsApp {
}
@Override
- public boolean isEnabled(cgCache cache) {
+ public boolean isEnabled(Geocache cache) {
return !cache.hasStaticMap();
}
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return !hasStaticMap(waypoint);
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
invokeStaticMaps(activity, cache, null, true);
}
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
invokeStaticMaps(activity, null, waypoint, true);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
new file mode 100644
index 0000000..db4fc1c
--- /dev/null
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleMapsDirectionApp.java
@@ -0,0 +1,48 @@
+package cgeo.geocaching.apps.cache.navi;
+
+import cgeo.geocaching.IGeoData;
+import cgeo.geocaching.R;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.maps.MapProviderFactory;
+import cgeo.geocaching.utils.Log;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+
+public class GoogleMapsDirectionApp extends AbstractPointNavigationApp {
+
+ protected GoogleMapsDirectionApp() {
+ super(getString(R.string.cache_menu_maps_directions), null);
+ }
+
+ @Override
+ public boolean isInstalled() {
+ return MapProviderFactory.isGoogleMapsInstalled();
+ }
+
+ @Override
+ public void navigate(Activity activity, Geopoint coords) {
+ try {
+ IGeoData geo = cgeoapplication.getInstance().currentGeo();
+ final Geopoint coordsNow = geo == null ? null : geo.getCoords();
+
+ if (coordsNow != null) {
+ activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
+ .parse("http://maps.google.com/maps?f=d&saddr="
+ + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + "&daddr="
+ + coords.getLatitude() + "," + coords.getLongitude())));
+ } else {
+ activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
+ .parse("http://maps.google.com/maps?f=d&daddr="
+ + coords.getLatitude() + "," + coords.getLongitude())));
+ }
+
+ } catch (Exception e) {
+ Log.i("GoogleMapsDirection: application not available.");
+ }
+
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
index 7258e11..f1616ad 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/GoogleNavigationApp.java
@@ -1,10 +1,6 @@
package cgeo.geocaching.apps.cache.navi;
-import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
-import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgeoapplication;
-import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.Log;
@@ -12,10 +8,13 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
-class GoogleNavigationApp extends AbstractPointNavigationApp {
+abstract class GoogleNavigationApp extends AbstractPointNavigationApp {
- GoogleNavigationApp() {
- super(getString(R.string.cache_menu_tbt), null);
+ private final String mode;
+
+ protected GoogleNavigationApp(final int nameResourceId, final String mode) {
+ super(getString(nameResourceId), null);
+ this.mode = mode;
}
@Override
@@ -23,49 +22,27 @@ class GoogleNavigationApp extends AbstractPointNavigationApp {
return true;
}
- private static boolean navigateToCoordinates(Activity activity, final Geopoint coords) {
- IGeoData geo = cgeoapplication.getInstance().currentGeo();
- final Geopoint coordsNow = geo == null ? null : geo.getCoords();
-
- // Google Navigation
- if (Settings.isUseGoogleNavigation()) {
- try {
- activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
- .parse("google.navigation:ll=" + coords.getLatitude() + ","
- + coords.getLongitude())));
-
- return true;
- } catch (Exception e) {
- // nothing
- }
- }
-
- // Google Maps Directions
+ @Override
+ public void navigate(Activity activity, Geopoint coords) {
try {
- if (coordsNow != null) {
- activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
- .parse("http://maps.google.com/maps?f=d&saddr="
- + coordsNow.getLatitude() + "," + coordsNow.getLongitude() + "&daddr="
- + coords.getLatitude() + "," + coords.getLongitude())));
- } else {
- activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
- .parse("http://maps.google.com/maps?f=d&daddr="
- + coords.getLatitude() + "," + coords.getLongitude())));
- }
+ activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri
+ .parse("google.navigation:ll=" + coords.getLatitude() + ","
+ + coords.getLongitude() + mode)));
- return true;
} catch (Exception e) {
- // nothing
+ Log.i("cgBase.runNavigation: No navigation application available.");
}
+ }
- Log.i("cgBase.runNavigation: No navigation application available.");
- return false;
+ static class GoogleNavigationWalkingApp extends GoogleNavigationApp {
+ GoogleNavigationWalkingApp() {
+ super(R.string.cache_menu_navigation_walk, "&mode=w");
+ }
}
- @Override
- public void navigate(Activity activity, Geopoint coords) {
- if (!navigateToCoordinates(activity, coords)) {
- ActivityMixin.showToast(activity, getString(R.string.err_navigation_no));
+ static class GoogleNavigationDrivingApp extends GoogleNavigationApp {
+ GoogleNavigationDrivingApp() {
+ super(R.string.cache_menu_navigation_drive, "&mode=d");
}
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
index 8185f40..2990f93 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/InternalMap.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
@@ -27,22 +27,22 @@ class InternalMap extends AbstractApp implements CacheNavigationApp, WaypointNav
}
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
CGeoMap.startActivityCoords(activity, waypoint.getCoords(), waypoint.getWaypointType(), waypoint.getName());
}
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return waypoint.getCoords() != null;
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
CGeoMap.startActivityGeoCode(activity, cache.getGeocode());
}
@Override
- public boolean isEnabled(cgCache cache) {
+ public boolean isEnabled(Geocache cache) {
return cache.getCoords() != null;
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
index a20f2ce..2d7702d 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/LocusApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps.cache.navi;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.apps.AbstractLocusApp;
import android.app.Activity;
@@ -11,7 +11,7 @@ import java.util.Collections;
class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointNavigationApp {
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return waypoint.getCoords() != null;
}
@@ -21,12 +21,12 @@ class LocusApp extends AbstractLocusApp implements CacheNavigationApp, WaypointN
*
*/
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
showInLocus(Collections.singletonList(waypoint), true, false, activity);
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
showInLocus(Collections.singletonList(cache), true, false, activity);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java
deleted file mode 100644
index 52d16cf..0000000
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationApp.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package cgeo.geocaching.apps.cache.navi;
-
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.apps.App;
-import cgeo.geocaching.geopoint.Geopoint;
-
-import android.app.Activity;
-
-public interface NavigationApp extends App {
- public boolean invoke(final Activity activity,
- final cgCache cache, final cgWaypoint waypoint,
- final Geopoint coords);
-
- boolean isEnabled(final cgWaypoint waypoint);
-
- boolean isEnabled(final Geopoint geopoint);
-}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
index 57a71bb..5545936 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/NavigationAppFactory.java
@@ -1,13 +1,18 @@
package cgeo.geocaching.apps.cache.navi;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.apps.AbstractAppFactory;
import cgeo.geocaching.apps.App;
+import cgeo.geocaching.apps.cache.CacheBeaconApp;
+import cgeo.geocaching.apps.cache.GccApp;
+import cgeo.geocaching.apps.cache.WhereYouGoApp;
+import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationDrivingApp;
+import cgeo.geocaching.apps.cache.navi.GoogleNavigationApp.GoogleNavigationWalkingApp;
import cgeo.geocaching.geopoint.Geopoint;
import android.app.Activity;
@@ -40,7 +45,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
/** Google Maps */
GOOGLE_MAPS(new GoogleMapsApp(), 6),
/** Google Navigation */
- GOOGLE_NAVIGATION(new GoogleNavigationApp(), 7),
+ GOOGLE_NAVIGATION(new GoogleNavigationDrivingApp(), 7),
/** Google Streetview */
GOOGLE_STREETVIEW(new StreetviewApp(), 8),
/** The external OruxMaps app */
@@ -48,7 +53,19 @@ public final class NavigationAppFactory extends AbstractAppFactory {
/** The external navigon app */
NAVIGON(new NavigonApp(), 10),
/** The external Sygic app */
- SYGIC(new SygicNavigationApp(), 11);
+ SYGIC(new SygicNavigationApp(), 11),
+ /**
+ * Google Navigation in walking mode
+ */
+ GOOGLE_NAVIGATION_WALK(new GoogleNavigationWalkingApp(), 12),
+ /**
+ * Google Maps Directions
+ */
+ GOOGLE_MAPS_DIRECTIONS(new GoogleMapsDirectionApp(), 13),
+
+ CACHE_BEACON(new CacheBeaconApp(), 14),
+ GCC(new GccApp(), 15),
+ WHERE_YOU_GO(new WhereYouGoApp(), 16);
NavigationAppsEnum(App app, int id) {
this.app = app;
@@ -79,7 +96,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* Default way to handle selection of navigation tool.<br />
* A dialog is created for tool selection and the selected tool is started afterwards.
* <p />
- * Delegates to {@link #showNavigationMenu(Activity, cgCache, cgWaypoint, Geopoint, boolean, boolean)} with
+ * Delegates to {@link #showNavigationMenu(Activity, cgeo.geocaching.Geocache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} with
* <code>showInternalMap = true</code> and <code>showDefaultNavigation = false</code>
*
* @param activity
@@ -88,7 +105,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param destination
*/
public static void showNavigationMenu(final Activity activity,
- final cgCache cache, final cgWaypoint waypoint, final Geopoint destination) {
+ final Geocache cache, final Waypoint waypoint, final Geopoint destination) {
showNavigationMenu(activity, cache, waypoint, destination, true, false);
}
@@ -108,14 +125,13 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param showDefaultNavigation
* should be <code>false</code> by default
*
- * @see #showNavigationMenu(Activity, cgCache, cgWaypoint, Geopoint)
+ * @see #showNavigationMenu(Activity, cgeo.geocaching.Geocache, cgeo.geocaching.Waypoint, Geopoint)
*/
public static void showNavigationMenu(final Activity activity,
- final cgCache cache, final cgWaypoint waypoint, final Geopoint destination,
+ final Geocache cache, final Waypoint waypoint, final Geopoint destination,
final boolean showInternalMap, final boolean showDefaultNavigation) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.cache_menu_navigate);
- builder.setIcon(R.drawable.ic_menu_mapmode);
final List<NavigationAppsEnum> items = new ArrayList<NavigationAppFactory.NavigationAppsEnum>();
final int defaultNavigationTool = Settings.getDefaultNavigationTool();
for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
@@ -146,17 +162,15 @@ public final class NavigationAppFactory extends AbstractAppFactory {
@Override
public void onClick(DialogInterface dialog, int item) {
NavigationAppsEnum selectedItem = adapter.getItem(item);
+ App app = selectedItem.app;
if (cache != null) {
- CacheNavigationApp cacheApp = (CacheNavigationApp) selectedItem.app;
- cacheApp.navigate(activity, cache);
+ navigateCache(activity, cache, app);
}
else if (waypoint != null) {
- WaypointNavigationApp waypointApp = (WaypointNavigationApp) selectedItem.app;
- waypointApp.navigate(activity, waypoint);
+ navigateWaypoint(activity, waypoint, app);
}
else {
- GeopointNavigationApp geopointApp = (GeopointNavigationApp) selectedItem.app;
- geopointApp.navigate(activity, destination);
+ navigateGeopoint(activity, destination, app);
}
}
});
@@ -202,15 +216,15 @@ public final class NavigationAppFactory extends AbstractAppFactory {
/**
* Adds the installed navigation tools to the given menu.
- * Use {@link #onMenuItemSelected(MenuItem, Activity, cgCache)} on
+ * Use {@link #onMenuItemSelected(MenuItem, Activity, cgeo.geocaching.Geocache)} on
* selection event to start the selected navigation tool.
*
- * <b>Only use this way if {@link #showNavigationMenu(Activity, cgCache, cgWaypoint, Geopoint, boolean, boolean)} is
+ * <b>Only use this way if {@link #showNavigationMenu(Activity, cgeo.geocaching.Geocache, cgeo.geocaching.Waypoint, Geopoint, boolean, boolean)} is
* not suitable for the given usecase.</b>
*
* @param menu
*/
- public static void addMenuItems(final Menu menu, final cgCache cache) {
+ public static void addMenuItems(final Menu menu, final Geocache cache) {
for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if (navApp.app instanceof CacheNavigationApp) {
CacheNavigationApp cacheApp = (CacheNavigationApp) navApp.app;
@@ -221,7 +235,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
}
- public static void addMenuItems(final Menu menu, final cgWaypoint waypoint) {
+ public static void addMenuItems(final Menu menu, final Waypoint waypoint) {
for (NavigationAppsEnum navApp : getInstalledNavigationApps()) {
if (navApp.app instanceof WaypointNavigationApp) {
WaypointNavigationApp waypointApp = (WaypointNavigationApp) navApp.app;
@@ -233,33 +247,33 @@ public final class NavigationAppFactory extends AbstractAppFactory {
}
/**
- * Handles menu selections for menu entries created with {@link #addMenuItems(Menu, cgCache)}.
+ * Handles menu selections for menu entries created with {@link #addMenuItems(Menu, cgeo.geocaching.Geocache)}.
*
* @param item
* @param activity
* @param cache
* @return
*/
- public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgCache cache) {
+ public static boolean onMenuItemSelected(final MenuItem item, Activity activity, Geocache cache) {
final App menuItem = getAppFromMenuItem(item);
navigateCache(activity, cache, menuItem);
return menuItem != null;
}
- private static void navigateCache(Activity activity, cgCache cache, App app) {
+ private static void navigateCache(Activity activity, Geocache cache, App app) {
if (app instanceof CacheNavigationApp) {
CacheNavigationApp cacheApp = (CacheNavigationApp) app;
cacheApp.navigate(activity, cache);
}
}
- public static boolean onMenuItemSelected(final MenuItem item, Activity activity, cgWaypoint waypoint) {
+ public static boolean onMenuItemSelected(final MenuItem item, Activity activity, Waypoint waypoint) {
final App menuItem = getAppFromMenuItem(item);
navigateWaypoint(activity, waypoint, menuItem);
return menuItem != null;
}
- private static void navigateWaypoint(Activity activity, cgWaypoint waypoint, App app) {
+ private static void navigateWaypoint(Activity activity, Waypoint waypoint, App app) {
if (app instanceof WaypointNavigationApp) {
WaypointNavigationApp waypointApp = (WaypointNavigationApp) app;
waypointApp.navigate(activity, waypoint);
@@ -291,7 +305,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param activity
* @param cache
*/
- public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, cgCache cache) {
+ public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Geocache cache) {
if (cache == null || cache.getCoords() == null) {
ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown));
return;
@@ -313,7 +327,7 @@ public final class NavigationAppFactory extends AbstractAppFactory {
* @param activity
* @param waypoint
*/
- public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, cgWaypoint waypoint) {
+ public static void startDefaultNavigationApplication(int defaultNavigation, Activity activity, Waypoint waypoint) {
if (waypoint == null || waypoint.getCoords() == null) {
ActivityMixin.showToast(activity, cgeoapplication.getInstance().getString(R.string.err_location_unknown));
return;
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
index a481813..2c6a8fc 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/RMapsApp.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter.Format;
@@ -21,7 +21,7 @@ class RMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNaviga
}
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
navigate(activity, waypoint.getCoords(), waypoint.getLookup(), waypoint.getName());
}
@@ -34,12 +34,12 @@ class RMapsApp extends AbstractApp implements CacheNavigationApp, WaypointNaviga
}
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return waypoint.getCoords() != null;
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
navigate(activity, cache.getCoords(), cache.getGeocode(), cache.getName());
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
index eb01f23..1dd57a3 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/StaticMapApp.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.apps.cache.navi;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.Geocache;
import android.app.Activity;
@@ -13,22 +13,22 @@ class StaticMapApp extends AbstractStaticMapsApp {
}
@Override
- public boolean isEnabled(cgCache cache) {
+ public boolean isEnabled(Geocache cache) {
return cache.hasStaticMap();
}
@Override
- public boolean isEnabled(cgWaypoint waypoint) {
+ public boolean isEnabled(Waypoint waypoint) {
return hasStaticMap(waypoint);
}
@Override
- public void navigate(Activity activity, cgCache cache) {
+ public void navigate(Activity activity, Geocache cache) {
invokeStaticMaps(activity, cache, null, false);
}
@Override
- public void navigate(Activity activity, cgWaypoint waypoint) {
+ public void navigate(Activity activity, Waypoint waypoint) {
invokeStaticMaps(activity, null, waypoint, false);
}
}
diff --git a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java
index 7d3a706..c26ec3e 100644
--- a/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java
+++ b/main/src/cgeo/geocaching/apps/cache/navi/WaypointNavigationApp.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.apps.cache.navi;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import android.app.Activity;
@@ -9,7 +9,7 @@ import android.app.Activity;
*
*/
public interface WaypointNavigationApp {
- void navigate(final Activity activity, final cgWaypoint waypoint);
+ void navigate(final Activity activity, final Waypoint waypoint);
- boolean isEnabled(final cgWaypoint waypoint);
+ boolean isEnabled(final Waypoint waypoint);
}
diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java
index 519b394..ac5809e 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListApp.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.apps.cachelist;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.App;
import android.app.Activity;
@@ -10,7 +10,7 @@ import java.util.List;
interface CacheListApp extends App {
- boolean invoke(final List<cgCache> caches,
+ boolean invoke(final List<Geocache> caches,
final Activity activity, final SearchResult search);
}
diff --git a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
index fbfb9fc..b747eee 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/CacheListAppFactory.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.apps.cachelist;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.apps.AbstractAppFactory;
import cgeo.geocaching.utils.Log;
@@ -55,7 +55,7 @@ public final class CacheListAppFactory extends AbstractAppFactory {
}
}
- public static boolean onMenuItemSelected(final MenuItem item, final List<cgCache> caches, final IAbstractActivity activity,
+ public static boolean onMenuItemSelected(final MenuItem item, final List<Geocache> caches, final IAbstractActivity activity,
final SearchResult search) {
final CacheListApp app = (CacheListApp) getAppFromMenuItem(item, LazyHolder.apps);
if (app != null) {
@@ -64,7 +64,7 @@ public final class CacheListAppFactory extends AbstractAppFactory {
activity.invalidateOptionsMenuCompatible();
return result;
} catch (Exception e) {
- Log.e("CacheListAppFactory.onMenuItemSelected: " + e.toString());
+ Log.e("CacheListAppFactory.onMenuItemSelected", e);
}
}
return false;
diff --git a/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java b/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java
index d6e1fed..38fb499 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/InternalCacheListMap.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.apps.cachelist;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.AbstractApp;
import cgeo.geocaching.maps.CGeoMap;
@@ -22,7 +22,7 @@ class InternalCacheListMap extends AbstractApp implements CacheListApp {
}
@Override
- public boolean invoke(List<cgCache> caches, Activity activity, final SearchResult search) {
+ public boolean invoke(List<Geocache> caches, Activity activity, final SearchResult search) {
CGeoMap.startActivitySearch(activity, search, null);
return true;
}
diff --git a/main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java b/main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java
index 65760c7..cd0289a 100644
--- a/main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java
+++ b/main/src/cgeo/geocaching/apps/cachelist/LocusCacheListApp.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.apps.cachelist;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.apps.AbstractLocusApp;
import org.apache.commons.collections.CollectionUtils;
@@ -27,7 +27,7 @@ class LocusCacheListApp extends AbstractLocusApp implements CacheListApp {
* @see AbstractLocusApp#showInLocus
*/
@Override
- public boolean invoke(List<cgCache> cacheList, Activity activity, final SearchResult search) {
+ public boolean invoke(List<Geocache> cacheList, Activity activity, final SearchResult search) {
if (CollectionUtils.isEmpty(cacheList)) {
return false;
}
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java
index 94eb3fd..13546f3 100644
--- a/main/src/cgeo/geocaching/cgData.java
+++ b/main/src/cgeo/geocaching/cgData.java
@@ -23,7 +23,6 @@ import android.content.ContextWrapper;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DatabaseUtils;
-import android.database.DatabaseUtils.InsertHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDoneException;
@@ -48,6 +47,10 @@ import java.util.regex.Pattern;
public class cgData {
+ private cgData() {
+ // utility class
+ }
+
public enum StorageLocation {
HEAP,
CACHE,
@@ -56,11 +59,15 @@ public class cgData {
/** The list of fields needed for mapping. */
private static final String[] CACHE_COLUMNS = new String[] {
- "_id", "updated", "reason", "detailed", "detailedupdate", "visiteddate", "geocode", "cacheid", "guid", "type", "name", "own", "owner", "owner_real", "hidden", "hint", "size",
- "difficulty", "distance", "direction", "terrain", "latlon", "location", "latitude", "longitude", "elevation", "shortdesc",
- "favourite_cnt", "rating", "votes", "myvote", "disabled", "archived", "members", "found", "favourite", "inventorycoins", "inventorytags",
- "inventoryunknown", "onWatchlist", "personal_note", "reliable_latlon", "coordsChanged", "finalDefined"
- // reason is replaced by listId in cgCache
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+ "updated", "reason", "detailed", "detailedupdate", "visiteddate", "geocode", "cacheid", "guid", "type", "name", "owner", "owner_real", "hidden", "hint", "size",
+ // 15 16 17 18 19 20 21 22 23
+ "difficulty", "direction", "distance", "terrain", "latlon", "location", "elevation", "personal_note", "shortdesc",
+ // 24 25 26 27 28 29 30 31 32
+ "favourite_cnt", "rating", "votes", "myvote", "disabled", "archived", "members", "found", "favourite",
+ // 33 34 35 36 37 38 39 40 41 42
+ "inventoryunknown", "onWatchlist", "reliable_latlon", "coordsChanged", "latitude", "longitude", "finalDefined", "_id", "inventorycoins", "inventorytags"
+ // reason is replaced by listId in Geocache
};
/** The list of fields needed for mapping. */
private static final String[] WAYPOINT_COLUMNS = new String[] { "_id", "geocode", "updated", "type", "prefix", "lookup", "name", "latlon", "latitude", "longitude", "note", "own" };
@@ -72,9 +79,9 @@ public class cgData {
* holds the column indexes of the cache table to avoid lookups
*/
private static int[] cacheColumnIndex;
- private CacheCache cacheCache = new CacheCache();
- private SQLiteDatabase database = null;
- private static final int dbVersion = 64;
+ private static CacheCache cacheCache = new CacheCache();
+ private static SQLiteDatabase database = null;
+ private static final int dbVersion = 65;
public static final int customListIdOffset = 10;
private static final String dbName = "data";
private static final String dbTableCaches = "cg_caches";
@@ -101,7 +108,6 @@ public class cgData {
+ "guid text, "
+ "type text, "
+ "name text, "
- + "own integer not null default 0, "
+ "owner text, "
+ "owner_real text, "
+ "hidden long, "
@@ -151,9 +157,6 @@ public class cgData {
+ "updated long not null, " // date of save
+ "attribute text "
+ "); ";
- private final static int ATTRIBUTES_GEOCODE = 2;
- private final static int ATTRIBUTES_UPDATED = 3;
- private final static int ATTRIBUTES_ATTRIBUTE = 4;
private static final String dbCreateWaypoints = ""
+ "create table " + dbTableWaypoints + " ("
@@ -191,14 +194,6 @@ public class cgData {
+ "found integer not null default 0, "
+ "friend integer "
+ "); ";
- private final static int LOGS_GEOCODE = 2;
- private final static int LOGS_UPDATED = 3;
- private final static int LOGS_TYPE = 4;
- private final static int LOGS_AUTHOR = 5;
- private final static int LOGS_LOG = 6;
- private final static int LOGS_DATE = 7;
- private final static int LOGS_FOUND = 8;
- private final static int LOGS_FRIEND = 9;
private static final String dbCreateLogCount = ""
+ "create table " + dbTableLogCount + " ("
@@ -246,10 +241,10 @@ public class cgData {
+ "longitude double "
+ "); ";
- private HashMap<String, SQLiteStatement> statements = new HashMap<String, SQLiteStatement>();
private static boolean newlyCreatedDatabase = false;
+ private static boolean databaseCleaned = false;
- public synchronized void init() {
+ public synchronized static void init() {
if (database != null) {
return;
}
@@ -262,35 +257,28 @@ public class cgData {
}
}
- public void closeDb() {
+ public static void closeDb() {
if (database == null) {
return;
}
cacheCache.removeAllFromCache();
- clearPreparedStatements();
+ PreparedStatements.clearPreparedStatements();
database.close();
database = null;
}
- private void clearPreparedStatements() {
- for (SQLiteStatement statement : statements.values()) {
- statement.close();
- }
- statements.clear();
- }
-
- private static File backupFile() {
+ private static File getBackupFile() {
return new File(LocalStorage.getStorage(), "cgeo.sqlite");
}
- public String backupDatabase() {
+ public static String backupDatabase() {
if (!LocalStorage.isExternalStorageAvailable()) {
Log.w("Database wasn't backed up: no external memory");
return null;
}
- final File target = backupFile();
+ final File target = getBackupFile();
closeDb();
final boolean backupDone = LocalStorage.copy(databasePath(), target);
init();
@@ -304,7 +292,7 @@ public class cgData {
return target.getPath();
}
- public boolean moveDatabase() {
+ public static boolean moveDatabase() {
if (!LocalStorage.isExternalStorageAvailable()) {
Log.w("Database was not moved: external memory not available");
return false;
@@ -340,18 +328,18 @@ public class cgData {
return databasePath(Settings.isDbOnSDCard());
}
- public static File isRestoreFile() {
- final File fileSourceFile = backupFile();
+ public static File getRestoreFile() {
+ final File fileSourceFile = getBackupFile();
return fileSourceFile.exists() ? fileSourceFile : null;
}
- public boolean restoreDatabase() {
+ public static boolean restoreDatabase() {
if (!LocalStorage.isExternalStorageAvailable()) {
Log.w("Database wasn't restored: no external memory");
return false;
}
- final File sourceFile = backupFile();
+ final File sourceFile = getBackupFile();
closeDb();
final boolean restoreDone = LocalStorage.copy(sourceFile, databasePath());
init();
@@ -475,7 +463,7 @@ public class cgData {
try {
db.execSQL(dbCreateLogImages);
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 54: " + e.toString());
+ Log.e("Failed to upgrade to ver. 54", e);
}
}
@@ -484,7 +472,7 @@ public class cgData {
try {
db.execSQL("alter table " + dbTableCaches + " add column personal_note text");
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 55: " + e.toString());
+ Log.e("Failed to upgrade to ver. 55", e);
}
}
@@ -496,7 +484,7 @@ public class cgData {
"lower(attribute) where attribute like \"%_yes\" " +
"or attribute like \"%_no\"");
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 56: " + e.toString());
+ Log.e("Failed to upgrade to ver. 56", e);
}
}
@@ -511,7 +499,7 @@ public class cgData {
db.execSQL("drop index in_f");
createIndices(db);
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 57: " + e.toString());
+ Log.e("Failed to upgrade to ver. 57", e);
}
}
@@ -629,7 +617,7 @@ public class cgData {
db.execSQL("alter table " + dbTableLogs + " add column friend integer");
db.execSQL("alter table " + dbTableCaches + " add column coordsChanged integer default 0");
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 61: " + e.toString());
+ Log.e("Failed to upgrade to ver. 61", e);
}
}
@@ -640,7 +628,7 @@ public class cgData {
db.execSQL("alter table " + dbTableWaypoints + " add column own integer default 0");
db.execSQL("update " + dbTableWaypoints + " set own = 1 where type = 'own'");
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 62: " + e.toString());
+ Log.e("Failed to upgrade to ver. 62", e);
}
}
@@ -648,7 +636,7 @@ public class cgData {
try {
removeDoubleUnderscoreMapFiles();
} catch (Exception e) {
- Log.e("Failed to upgrade to ver. 63: " + e.toString());
+ Log.e("Failed to upgrade to ver. 63", e);
}
}
@@ -663,6 +651,15 @@ public class cgData {
Log.e("Failed to upgrade to ver. 64", e);
}
}
+
+ if (oldVersion < 65) {
+ try {
+ // Set all waypoints where name is Original coordinates to type ORIGINAL
+ db.execSQL("update " + dbTableWaypoints + " set type='original', own=0 where name='Original Coordinates'");
+ } catch (Exception e) {
+ Log.e("Failed to upgrade to ver. 65:", e);
+ }
+ }
}
db.setTransactionSuccessful();
@@ -692,7 +689,7 @@ public class cgData {
// to NPE traces.
final int staleHistorySearches = db.delete(dbTableSearchDestionationHistory, "date is null", null);
if (staleHistorySearches > 0) {
- Log.w(String.format("cgData.dbHelper.onOpen: removed %d bad search history entries", staleHistorySearches));
+ Log.w(String.format(Locale.getDefault(), "cgData.dbHelper.onOpen: removed %d bad search history entries", staleHistorySearches));
}
}
@@ -705,13 +702,15 @@ public class cgData {
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
- return (filename.startsWith("map_") && filename.contains("__"));
+ return filename.startsWith("map_") && filename.contains("__");
}
};
- for (File dir : geocodeDirs) {
- File[] wrongFiles = dir.listFiles(filter);
- for (File wrongFile : wrongFiles) {
- wrongFile.delete();
+ for (final File dir : geocodeDirs) {
+ final File[] wrongFiles = dir.listFiles(filter);
+ if (wrongFiles != null) {
+ for (final File wrongFile : wrongFiles) {
+ wrongFile.delete();
+ }
}
}
}
@@ -776,15 +775,12 @@ public class cgData {
db.execSQL("drop table if exists " + dbTableTrackables);
}
- public String[] allDetailedThere() {
+ public static String[] getRecentGeocodesForSearch() {
init();
- Cursor cursor = null;
- List<String> list = new ArrayList<String>();
-
try {
long timestamp = System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED;
- cursor = database.query(
+ final Cursor cursor = database.query(
dbTableCaches,
new String[]{"geocode"},
"(detailed = 1 and detailedupdate > ?) or reason > 0",
@@ -794,43 +790,23 @@ public class cgData {
"detailedupdate desc",
"100");
- if (cursor != null) {
- int index;
-
- if (cursor.getCount() > 0) {
- cursor.moveToFirst();
- index = cursor.getColumnIndex("geocode");
-
- do {
- list.add(cursor.getString(index));
- } while (cursor.moveToNext());
- } else {
- cursor.close();
- return null;
- }
- }
- } catch (Exception e) {
- Log.e("cgData.allDetailedThere: " + e.toString());
- }
-
- if (cursor != null) {
- cursor.close();
+ return getFirstColumn(cursor);
+ } catch (final Exception e) {
+ Log.e("cgData.allDetailedThere", e);
+ return new String[0];
}
-
- return list.toArray(new String[list.size()]);
}
- public boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) {
+ public static boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) {
init();
- Cursor cursor = null;
-
- int cnt = 0;
long dataUpdated = 0;
long dataDetailedUpdate = 0;
int dataDetailed = 0;
try {
+ Cursor cursor;
+
if (StringUtils.isNotBlank(geocode)) {
cursor = database.query(
dbTableCaches,
@@ -855,55 +831,38 @@ public class cgData {
return false;
}
- if (cursor != null) {
- int index;
- cnt = cursor.getCount();
-
- if (cnt > 0) {
- cursor.moveToFirst();
-
- index = cursor.getColumnIndex("updated");
- dataUpdated = cursor.getLong(index);
- index = cursor.getColumnIndex("detailedupdate");
- dataDetailedUpdate = cursor.getLong(index);
- index = cursor.getColumnIndex("detailed");
- dataDetailed = cursor.getInt(index);
- }
+ if (cursor.moveToFirst()) {
+ dataDetailed = cursor.getInt(0);
+ dataDetailedUpdate = cursor.getLong(1);
+ dataUpdated = cursor.getLong(2);
}
- } catch (Exception e) {
- Log.e("cgData.isThere: " + e.toString());
- }
- if (cursor != null) {
cursor.close();
+ } catch (final Exception e) {
+ Log.e("cgData.isThere", e);
}
- if (cnt > 0) {
- if (detailed && dataDetailed == 0) {
- // we want details, but these are not stored
- return false;
- }
-
- if (checkTime && detailed && dataDetailedUpdate < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) {
- // we want to check time for detailed cache, but data are older than 3 hours
- return false;
- }
+ if (detailed && dataDetailed == 0) {
+ // we want details, but these are not stored
+ return false;
+ }
- if (checkTime && !detailed && dataUpdated < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) {
- // we want to check time for short cache, but data are older than 3 hours
- return false;
- }
+ if (checkTime && detailed && dataDetailedUpdate < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) {
+ // we want to check time for detailed cache, but data are older than 3 hours
+ return false;
+ }
- // we have some cache
- return true;
+ if (checkTime && !detailed && dataUpdated < (System.currentTimeMillis() - DAYS_AFTER_CACHE_IS_DELETED)) {
+ // we want to check time for short cache, but data are older than 3 hours
+ return false;
}
- // we have no such cache stored in cache
- return false;
+ // we have some cache
+ return true;
}
/** is cache stored in one of the lists (not only temporary) */
- public boolean isOffline(String geocode, String guid) {
+ public static boolean isOffline(String geocode, String guid) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid)) {
return false;
}
@@ -913,11 +872,11 @@ public class cgData {
final SQLiteStatement listId;
final String value;
if (StringUtils.isNotBlank(geocode)) {
- listId = getStatementListIdFromGeocode();
+ listId = PreparedStatements.getListIdOfGeocode();
value = geocode;
}
else {
- listId = getStatementListIdFromGuid();
+ listId = PreparedStatements.getListIdOfGuid();
value = guid;
}
synchronized (listId) {
@@ -933,14 +892,14 @@ public class cgData {
return false;
}
- public String getGeocodeForGuid(String guid) {
+ public static String getGeocodeForGuid(String guid) {
if (StringUtils.isBlank(guid)) {
return null;
}
init();
try {
- final SQLiteStatement description = getStatementGeocode();
+ final SQLiteStatement description = PreparedStatements.getGeocodeOfGuid();
synchronized (description) {
description.bindString(1, guid);
return description.simpleQueryForString();
@@ -954,14 +913,14 @@ public class cgData {
return null;
}
- public String getCacheidForGeocode(String geocode) {
+ public static String getCacheidForGeocode(String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
try {
- final SQLiteStatement description = getStatementCacheId();
+ final SQLiteStatement description = PreparedStatements.getCacheIdOfGeocode();
synchronized (description) {
description.bindString(1, geocode);
return description.simpleQueryForString();
@@ -984,7 +943,7 @@ public class cgData {
*
* @return true = cache saved successfully to the CacheCache/DB
*/
- public boolean saveCache(cgCache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) {
+ public static boolean saveCache(Geocache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) {
if (cache == null) {
throw new IllegalArgumentException("cache must not be null");
}
@@ -1028,7 +987,6 @@ public class cgData {
values.put("guid", cache.getGuid());
values.put("type", cache.getType().id);
values.put("name", cache.getName());
- values.put("own", cache.isOwn() ? 1 : 0);
values.put("owner", cache.getOwnerDisplayName());
values.put("owner_real", cache.getOwnerUserId());
if (cache.getHiddenDate() == null) {
@@ -1064,12 +1022,12 @@ public class cgData {
values.put("coordsChanged", cache.hasUserModifiedCoords() ? 1 : 0);
values.put("finalDefined", cache.hasFinalDefined() ? 1 : 0);
- boolean result = false;
init();
//try to update record else insert fresh..
database.beginTransaction();
+ boolean result = false;
try {
saveAttributesWithoutTransaction(cache);
saveOriginalWaypointsWithoutTransaction(cache);
@@ -1087,7 +1045,7 @@ public class cgData {
database.setTransactionSuccessful();
result = true;
} catch (Exception e) {
- // nothing
+ Log.e("SaveCache", e);
} finally {
database.endTransaction();
}
@@ -1095,25 +1053,21 @@ public class cgData {
return result;
}
- private void saveAttributesWithoutTransaction(final cgCache cache) {
+ private static void saveAttributesWithoutTransaction(final Geocache cache) {
String geocode = cache.getGeocode();
database.delete(dbTableAttributes, "geocode = ?", new String[]{geocode});
- if (cache.getAttributes().isNotEmpty()) {
-
- InsertHelper helper = new InsertHelper(database, dbTableAttributes);
- long timeStamp = System.currentTimeMillis();
-
- for (String attribute : cache.getAttributes()) {
- helper.prepareForInsert();
-
- helper.bind(ATTRIBUTES_GEOCODE, geocode);
- helper.bind(ATTRIBUTES_UPDATED, timeStamp);
- helper.bind(ATTRIBUTES_ATTRIBUTE, attribute);
+ if (cache.getAttributes().isEmpty()) {
+ return;
+ }
+ SQLiteStatement statement = PreparedStatements.getInsertAttribute();
+ final long timestamp = System.currentTimeMillis();
+ for (String attribute : cache.getAttributes()) {
+ statement.bindString(1, geocode);
+ statement.bindLong(2, timestamp);
+ statement.bindString(3, attribute);
- helper.execute();
- }
- helper.close();
+ statement.executeInsert();
}
}
@@ -1123,16 +1077,14 @@ public class cgData {
* @param destination
* a destination to save
*/
- public void saveSearchedDestination(final Destination destination) {
+ public static void saveSearchedDestination(final Destination destination) {
init();
database.beginTransaction();
try {
- ContentValues values = new ContentValues();
- values.put("date", destination.getDate());
- putCoords(values, destination.getCoords());
- database.insert(dbTableSearchDestionationHistory, null, values);
+ SQLiteStatement insertDestination = PreparedStatements.getInsertSearchDestination(destination);
+ insertDestination.executeInsert();
database.setTransactionSuccessful();
} catch (Exception e) {
Log.e("Updating searchedDestinations db failed", e);
@@ -1141,11 +1093,11 @@ public class cgData {
}
}
- public boolean saveWaypoints(final cgCache cache) {
- boolean result = false;
+ public static boolean saveWaypoints(final Geocache cache) {
init();
database.beginTransaction();
+ boolean result = false;
try {
saveOriginalWaypointsWithoutTransaction(cache);
database.setTransactionSuccessful();
@@ -1158,15 +1110,14 @@ public class cgData {
return result;
}
- private void saveOriginalWaypointsWithoutTransaction(final cgCache cache) {
+ private static void saveOriginalWaypointsWithoutTransaction(final Geocache cache) {
String geocode = cache.getGeocode();
- database.delete(dbTableWaypoints, "geocode = ? and type <> ? and own = 0", new String[]{geocode, "own"});
- List<cgWaypoint> waypoints = cache.getWaypoints();
+ List<Waypoint> waypoints = cache.getWaypoints();
if (CollectionUtils.isNotEmpty(waypoints)) {
ContentValues values = new ContentValues();
long timeStamp = System.currentTimeMillis();
- for (cgWaypoint oneWaypoint : waypoints) {
+ for (Waypoint oneWaypoint : waypoints) {
if (oneWaypoint.isUserDefined()) {
continue;
}
@@ -1183,8 +1134,12 @@ public class cgData {
values.put("note", oneWaypoint.getNote());
values.put("own", oneWaypoint.isUserDefined() ? 1 : 0);
- final long rowId = database.insert(dbTableWaypoints, null, values);
- oneWaypoint.setId((int) rowId);
+ if (oneWaypoint.getId() < 0) {
+ final long rowId = database.insert(dbTableWaypoints, null, values);
+ oneWaypoint.setId((int) rowId);
+ } else {
+ database.update(dbTableWaypoints, values, "_id = ?", new String[] { Integer.toString(oneWaypoint.getId(), 10) });
+ }
}
}
}
@@ -1221,15 +1176,15 @@ public class cgData {
return new Geopoint(cursor.getDouble(indexLat), cursor.getDouble(indexLon));
}
- public boolean saveWaypoint(int id, String geocode, cgWaypoint waypoint) {
+ private static boolean saveWaypointInternal(int id, String geocode, Waypoint waypoint) {
if ((StringUtils.isBlank(geocode) && id <= 0) || waypoint == null) {
return false;
}
init();
- boolean ok = false;
database.beginTransaction();
+ boolean ok = false;
try {
ContentValues values = new ContentValues();
values.put("geocode", geocode);
@@ -1259,7 +1214,7 @@ public class cgData {
return ok;
}
- public boolean deleteWaypoint(int id) {
+ public static boolean deleteWaypoint(int id) {
if (id == 0) {
return false;
}
@@ -1269,28 +1224,32 @@ public class cgData {
return database.delete(dbTableWaypoints, "_id = " + id, null) > 0;
}
- private void saveSpoilersWithoutTransaction(final cgCache cache) {
+ private static void saveSpoilersWithoutTransaction(final Geocache cache) {
String geocode = cache.getGeocode();
database.delete(dbTableSpoilers, "geocode = ?", new String[]{geocode});
- List<cgImage> spoilers = cache.getSpoilers();
+ List<Image> spoilers = cache.getSpoilers();
if (CollectionUtils.isNotEmpty(spoilers)) {
- ContentValues values = new ContentValues();
- long timeStamp = System.currentTimeMillis();
- for (cgImage spoiler : spoilers) {
- values.clear();
- values.put("geocode", geocode);
- values.put("updated", timeStamp);
- values.put("url", spoiler.getUrl());
- values.put("title", spoiler.getTitle());
- values.put("description", spoiler.getDescription());
-
- database.insert(dbTableSpoilers, null, values);
+ SQLiteStatement insertSpoiler = PreparedStatements.getInsertSpoiler();
+ final long timestamp = System.currentTimeMillis();
+ for (Image spoiler : spoilers) {
+ insertSpoiler.bindString(1, geocode);
+ insertSpoiler.bindLong(2, timestamp);
+ insertSpoiler.bindString(3, spoiler.getUrl());
+ insertSpoiler.bindString(4, spoiler.getTitle());
+ final String description = spoiler.getDescription();
+ if (description != null) {
+ insertSpoiler.bindString(5, description);
+ }
+ else {
+ insertSpoiler.bindNull(5);
+ }
+ insertSpoiler.executeInsert();
}
}
}
- private void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) {
+ private static void saveLogsWithoutTransaction(final String geocode, final Iterable<LogEntry> logs) {
// TODO delete logimages referring these logs
database.delete(dbTableLogs, "geocode = ?", new String[]{geocode});
@@ -1298,59 +1257,51 @@ public class cgData {
return;
}
- InsertHelper helper = new InsertHelper(database, dbTableLogs);
- long timeStamp = System.currentTimeMillis();
+ SQLiteStatement insertLog = PreparedStatements.getInsertLog();
+ final long timestamp = System.currentTimeMillis();
for (LogEntry log : logs) {
- helper.prepareForInsert();
-
- helper.bind(LOGS_GEOCODE, geocode);
- helper.bind(LOGS_UPDATED, timeStamp);
- helper.bind(LOGS_TYPE, log.type.id);
- helper.bind(LOGS_AUTHOR, log.author);
- helper.bind(LOGS_LOG, log.log);
- helper.bind(LOGS_DATE, log.date);
- helper.bind(LOGS_FOUND, log.found);
- helper.bind(LOGS_FRIEND, log.friend);
-
- long log_id = helper.execute();
-
+ insertLog.bindString(1, geocode);
+ insertLog.bindLong(2, timestamp);
+ insertLog.bindLong(3, log.type.id);
+ insertLog.bindString(4, log.author);
+ insertLog.bindString(5, log.log);
+ insertLog.bindLong(6, log.date);
+ insertLog.bindLong(7, log.found);
+ insertLog.bindLong(8, log.friend ? 1 : 0);
+ long logId = insertLog.executeInsert();
if (log.hasLogImages()) {
- ContentValues values = new ContentValues();
- for (cgImage img : log.getLogImages()) {
- values.clear();
- values.put("log_id", log_id);
- values.put("title", img.getTitle());
- values.put("url", img.getUrl());
- database.insert(dbTableLogImages, null, values);
+ SQLiteStatement insertImage = PreparedStatements.getInsertLogImage();
+ for (Image img : log.getLogImages()) {
+ insertImage.bindLong(1, logId);
+ insertImage.bindString(2, img.getTitle());
+ insertImage.bindString(3, img.getUrl());
+ insertImage.executeInsert();
}
}
}
- helper.close();
}
- private void saveLogCountsWithoutTransaction(final cgCache cache) {
+ private static void saveLogCountsWithoutTransaction(final Geocache cache) {
String geocode = cache.getGeocode();
database.delete(dbTableLogCount, "geocode = ?", new String[]{geocode});
Map<LogType, Integer> logCounts = cache.getLogCounts();
if (MapUtils.isNotEmpty(logCounts)) {
- ContentValues values = new ContentValues();
-
Set<Entry<LogType, Integer>> logCountsItems = logCounts.entrySet();
- long timeStamp = System.currentTimeMillis();
+ SQLiteStatement insertLogCounts = PreparedStatements.getInsertLogCounts();
+ final long timestamp = System.currentTimeMillis();
for (Entry<LogType, Integer> pair : logCountsItems) {
- values.clear();
- values.put("geocode", geocode);
- values.put("updated", timeStamp);
- values.put("type", pair.getKey().id);
- values.put("count", pair.getValue());
+ insertLogCounts.bindString(1, geocode);
+ insertLogCounts.bindLong(2, timestamp);
+ insertLogCounts.bindLong(3, pair.getKey().id);
+ insertLogCounts.bindLong(4, pair.getValue());
- database.insert(dbTableLogCount, null, values);
+ insertLogCounts.executeInsert();
}
}
}
- public boolean saveTrackable(final cgTrackable trackable) {
+ public static boolean saveTrackable(final Trackable trackable) {
init();
database.beginTransaction();
@@ -1364,7 +1315,7 @@ public class cgData {
return true;
}
- private void saveInventoryWithoutTransaction(final String geocode, final List<cgTrackable> trackables) {
+ private static void saveInventoryWithoutTransaction(final String geocode, final List<Trackable> trackables) {
if (geocode != null) {
database.delete(dbTableTrackables, "geocode = ?", new String[]{geocode});
}
@@ -1372,7 +1323,7 @@ public class cgData {
if (CollectionUtils.isNotEmpty(trackables)) {
ContentValues values = new ContentValues();
long timeStamp = System.currentTimeMillis();
- for (cgTrackable trackable : trackables) {
+ for (Trackable trackable : trackables) {
final String tbCode = trackable.getGeocode();
if (StringUtils.isNotBlank(tbCode)) {
database.delete(dbTableTrackables, "tbcode = ?", new String[] { tbCode });
@@ -1401,12 +1352,12 @@ public class cgData {
}
}
- public Viewport getBounds(final Set<String> geocodes) {
+ public static Viewport getBounds(final Set<String> geocodes) {
if (CollectionUtils.isEmpty(geocodes)) {
return null;
}
- final Set<cgCache> caches = loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
+ final Set<Geocache> caches = loadCaches(geocodes, LoadFlags.LOAD_CACHE_OR_DB);
return Viewport.containing(caches);
}
@@ -1417,12 +1368,12 @@ public class cgData {
* The Geocode GCXXXX
* @return the loaded cache (if found). Can be null
*/
- public cgCache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) {
+ public static Geocache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) {
if (StringUtils.isBlank(geocode)) {
throw new IllegalArgumentException("geocode must not be empty");
}
- final Set<cgCache> caches = loadCaches(Collections.singleton(geocode), loadFlags);
+ final Set<Geocache> caches = loadCaches(Collections.singleton(geocode), loadFlags);
return caches.isEmpty() ? null : caches.iterator().next();
}
@@ -1432,17 +1383,17 @@ public class cgData {
* @param geocodes
* @return Set of loaded caches. Never null.
*/
- public Set<cgCache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
+ public static Set<Geocache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
- return new HashSet<cgCache>();
+ return new HashSet<Geocache>();
}
- Set<cgCache> result = new HashSet<cgCache>();
+ Set<Geocache> result = new HashSet<Geocache>();
Set<String> remaining = new HashSet<String>(geocodes);
if (loadFlags.contains(LoadFlag.LOAD_CACHE_BEFORE)) {
for (String geocode : new HashSet<String>(remaining)) {
- cgCache cache = cacheCache.getCacheFromCache(geocode);
+ Geocache cache = cacheCache.getCacheFromCache(geocode);
if (cache != null) {
result.add(cache);
remaining.remove(cache.getGeocode());
@@ -1458,16 +1409,16 @@ public class cgData {
loadFlags.contains(LoadFlag.LOAD_INVENTORY) ||
loadFlags.contains(LoadFlag.LOAD_OFFLINE_LOG)) {
- final Set<cgCache> cachesFromDB = loadCachesFromGeocodes(remaining, loadFlags);
+ final Set<Geocache> cachesFromDB = loadCachesFromGeocodes(remaining, loadFlags);
result.addAll(cachesFromDB);
- for (final cgCache cache : cachesFromDB) {
+ for (final Geocache cache : cachesFromDB) {
remaining.remove(cache.getGeocode());
}
}
if (loadFlags.contains(LoadFlag.LOAD_CACHE_AFTER)) {
for (String geocode : new HashSet<String>(remaining)) {
- cgCache cache = cacheCache.getCacheFromCache(geocode);
+ Geocache cache = cacheCache.getCacheFromCache(geocode);
if (cache != null) {
result.add(cache);
remaining.remove(cache.getGeocode());
@@ -1476,7 +1427,7 @@ public class cgData {
}
if (remaining.size() >= 1) {
- Log.e("cgData.loadCaches(" + remaining.toString() + ") failed");
+ Log.i("cgData.loadCaches(" + remaining.toString() + ") failed");
}
return result;
}
@@ -1488,7 +1439,7 @@ public class cgData {
* @param loadFlags
* @return Set of loaded caches. Never null.
*/
- private Set<cgCache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
+ private static Set<Geocache> loadCachesFromGeocodes(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
return Collections.emptySet();
}
@@ -1516,29 +1467,25 @@ public class cgData {
Cursor cursor = database.rawQuery(query.toString(), null);
try {
- if (!cursor.moveToFirst()) {
- return Collections.emptySet();
- }
-
- final Set<cgCache> caches = new HashSet<cgCache>();
+ final Set<Geocache> caches = new HashSet<Geocache>();
int logIndex = -1;
- do {
- //Extracted Method = LOADDBMINIMAL
- cgCache cache = cgData.createCacheFromDatabaseContent(cursor);
+
+ while (cursor.moveToNext()) {
+ Geocache cache = cgData.createCacheFromDatabaseContent(cursor);
if (loadFlags.contains(LoadFlag.LOAD_ATTRIBUTES)) {
cache.setAttributes(loadAttributes(cache.getGeocode()));
}
if (loadFlags.contains(LoadFlag.LOAD_WAYPOINTS)) {
- final List<cgWaypoint> waypoints = loadWaypoints(cache.getGeocode());
+ final List<Waypoint> waypoints = loadWaypoints(cache.getGeocode());
if (CollectionUtils.isNotEmpty(waypoints)) {
cache.setWaypoints(waypoints, false);
}
}
if (loadFlags.contains(LoadFlag.LOAD_SPOILERS)) {
- final List<cgImage> spoilers = loadSpoilers(cache.getGeocode());
+ final List<Image> spoilers = loadSpoilers(cache.getGeocode());
cache.setSpoilers(spoilers);
}
@@ -1552,10 +1499,10 @@ public class cgData {
}
if (loadFlags.contains(LoadFlag.LOAD_INVENTORY)) {
- final List<cgTrackable> inventory = loadInventory(cache.getGeocode());
+ final List<Trackable> inventory = loadInventory(cache.getGeocode());
if (CollectionUtils.isNotEmpty(inventory)) {
if (cache.getInventory() == null) {
- cache.setInventory(new ArrayList<cgTrackable>());
+ cache.setInventory(new ArrayList<Trackable>());
} else {
cache.getInventory().clear();
}
@@ -1573,7 +1520,7 @@ public class cgData {
cacheCache.putCacheInCache(cache);
caches.add(cache);
- } while (cursor.moveToNext());
+ }
return caches;
} finally {
cursor.close();
@@ -1599,53 +1546,14 @@ public class cgData {
* @param cursor
* @return Cache from DB
*/
- private static cgCache createCacheFromDatabaseContent(Cursor cursor) {
- int index;
- cgCache cache = new cgCache();
+ private static Geocache createCacheFromDatabaseContent(Cursor cursor) {
+ Geocache cache = new Geocache();
if (cacheColumnIndex == null) {
- int[] local_cci = new int[41]; // use a local variable to avoid having the not yet fully initialized array be visible to other threads
- local_cci[0] = cursor.getColumnIndex("updated");
- local_cci[1] = cursor.getColumnIndex("reason");
- local_cci[2] = cursor.getColumnIndex("detailed");
- local_cci[3] = cursor.getColumnIndex("detailedupdate");
- local_cci[4] = cursor.getColumnIndex("visiteddate");
- local_cci[5] = cursor.getColumnIndex("geocode");
- local_cci[6] = cursor.getColumnIndex("cacheid");
- local_cci[7] = cursor.getColumnIndex("guid");
- local_cci[8] = cursor.getColumnIndex("type");
- local_cci[9] = cursor.getColumnIndex("name");
- local_cci[10] = cursor.getColumnIndex("own");
- local_cci[11] = cursor.getColumnIndex("owner");
- local_cci[12] = cursor.getColumnIndex("owner_real");
- local_cci[13] = cursor.getColumnIndex("hidden");
- local_cci[14] = cursor.getColumnIndex("hint");
- local_cci[15] = cursor.getColumnIndex("size");
- local_cci[16] = cursor.getColumnIndex("difficulty");
- local_cci[17] = cursor.getColumnIndex("direction");
- local_cci[18] = cursor.getColumnIndex("distance");
- local_cci[19] = cursor.getColumnIndex("terrain");
- local_cci[20] = cursor.getColumnIndex("latlon");
- local_cci[21] = cursor.getColumnIndex("location");
- local_cci[22] = cursor.getColumnIndex("elevation");
- local_cci[23] = cursor.getColumnIndex("personal_note");
- local_cci[24] = cursor.getColumnIndex("shortdesc");
- local_cci[25] = cursor.getColumnIndex("favourite_cnt");
- local_cci[26] = cursor.getColumnIndex("rating");
- local_cci[27] = cursor.getColumnIndex("votes");
- local_cci[28] = cursor.getColumnIndex("myvote");
- local_cci[29] = cursor.getColumnIndex("disabled");
- local_cci[30] = cursor.getColumnIndex("archived");
- local_cci[31] = cursor.getColumnIndex("members");
- local_cci[32] = cursor.getColumnIndex("found");
- local_cci[33] = cursor.getColumnIndex("favourite");
- local_cci[34] = cursor.getColumnIndex("inventoryunknown");
- local_cci[35] = cursor.getColumnIndex("onWatchlist");
- local_cci[36] = cursor.getColumnIndex("reliable_latlon");
- local_cci[37] = cursor.getColumnIndex("coordsChanged");
- local_cci[38] = cursor.getColumnIndex("latitude");
- local_cci[39] = cursor.getColumnIndex("longitude");
- local_cci[40] = cursor.getColumnIndex("finalDefined");
+ final int[] local_cci = new int[CACHE_COLUMNS.length]; // use a local variable to avoid having the not yet fully initialized array be visible to other threads
+ for (int i = 0; i < CACHE_COLUMNS.length; i++) {
+ local_cci[i] = cursor.getColumnIndex(CACHE_COLUMNS[i]);
+ }
cacheColumnIndex = local_cci;
}
@@ -1659,71 +1567,70 @@ public class cgData {
cache.setGuid(cursor.getString(cacheColumnIndex[7]));
cache.setType(CacheType.getById(cursor.getString(cacheColumnIndex[8])));
cache.setName(cursor.getString(cacheColumnIndex[9]));
- cache.setOwn(cursor.getInt(cacheColumnIndex[10]) == 1);
- cache.setOwnerDisplayName(cursor.getString(cacheColumnIndex[11]));
- cache.setOwnerUserId(cursor.getString(cacheColumnIndex[12]));
- long dateValue = cursor.getLong(cacheColumnIndex[13]);
+ cache.setOwnerDisplayName(cursor.getString(cacheColumnIndex[10]));
+ cache.setOwnerUserId(cursor.getString(cacheColumnIndex[11]));
+ long dateValue = cursor.getLong(cacheColumnIndex[12]);
if (dateValue != 0) {
cache.setHidden(new Date(dateValue));
}
- cache.setHint(cursor.getString(cacheColumnIndex[14]));
- cache.setSize(CacheSize.getById(cursor.getString(cacheColumnIndex[15])));
- cache.setDifficulty(cursor.getFloat(cacheColumnIndex[16]));
- index = cacheColumnIndex[17];
+ cache.setHint(cursor.getString(cacheColumnIndex[13]));
+ cache.setSize(CacheSize.getById(cursor.getString(cacheColumnIndex[14])));
+ cache.setDifficulty(cursor.getFloat(cacheColumnIndex[15]));
+ int index = cacheColumnIndex[16];
if (cursor.isNull(index)) {
cache.setDirection(null);
} else {
cache.setDirection(cursor.getFloat(index));
}
- index = cacheColumnIndex[18];
+ index = cacheColumnIndex[17];
if (cursor.isNull(index)) {
cache.setDistance(null);
} else {
cache.setDistance(cursor.getFloat(index));
}
- cache.setTerrain(cursor.getFloat(cacheColumnIndex[19]));
- cache.setLatlon(cursor.getString(cacheColumnIndex[20]));
- cache.setLocation(cursor.getString(cacheColumnIndex[21]));
- cache.setCoords(getCoords(cursor, cacheColumnIndex[38], cacheColumnIndex[39]));
- index = cacheColumnIndex[22];
+ cache.setTerrain(cursor.getFloat(cacheColumnIndex[18]));
+ cache.setLatlon(cursor.getString(cacheColumnIndex[19]));
+ cache.setLocation(cursor.getString(cacheColumnIndex[20]));
+ cache.setCoords(getCoords(cursor, cacheColumnIndex[37], cacheColumnIndex[38]));
+ index = cacheColumnIndex[21];
if (cursor.isNull(index)) {
cache.setElevation(null);
} else {
cache.setElevation(cursor.getDouble(index));
}
- cache.setPersonalNote(cursor.getString(cacheColumnIndex[23]));
- cache.setShortdesc(cursor.getString(cacheColumnIndex[24]));
+ cache.setPersonalNote(cursor.getString(cacheColumnIndex[22]));
+ cache.setShortdesc(cursor.getString(cacheColumnIndex[23]));
// do not set cache.description !
- cache.setFavoritePoints(cursor.getInt(cacheColumnIndex[25]));
- cache.setRating(cursor.getFloat(cacheColumnIndex[26]));
- cache.setVotes(cursor.getInt(cacheColumnIndex[27]));
- cache.setMyVote(cursor.getFloat(cacheColumnIndex[28]));
- cache.setDisabled(cursor.getInt(cacheColumnIndex[29]) == 1);
- cache.setArchived(cursor.getInt(cacheColumnIndex[30]) == 1);
- cache.setPremiumMembersOnly(cursor.getInt(cacheColumnIndex[31]) == 1);
- cache.setFound(cursor.getInt(cacheColumnIndex[32]) == 1);
- cache.setFavorite(cursor.getInt(cacheColumnIndex[33]) == 1);
- cache.setInventoryItems(cursor.getInt(cacheColumnIndex[34]));
- cache.setOnWatchlist(cursor.getInt(cacheColumnIndex[35]) == 1);
- cache.setReliableLatLon(cursor.getInt(cacheColumnIndex[36]) > 0);
- cache.setUserModifiedCoords(cursor.getInt(cacheColumnIndex[37]) > 0);
- cache.setFinalDefined(cursor.getInt(cacheColumnIndex[40]) > 0);
+ cache.setFavoritePoints(cursor.getInt(cacheColumnIndex[24]));
+ cache.setRating(cursor.getFloat(cacheColumnIndex[25]));
+ cache.setVotes(cursor.getInt(cacheColumnIndex[26]));
+ cache.setMyVote(cursor.getFloat(cacheColumnIndex[27]));
+ cache.setDisabled(cursor.getInt(cacheColumnIndex[28]) == 1);
+ cache.setArchived(cursor.getInt(cacheColumnIndex[29]) == 1);
+ cache.setPremiumMembersOnly(cursor.getInt(cacheColumnIndex[30]) == 1);
+ cache.setFound(cursor.getInt(cacheColumnIndex[31]) == 1);
+ cache.setFavorite(cursor.getInt(cacheColumnIndex[32]) == 1);
+ cache.setInventoryItems(cursor.getInt(cacheColumnIndex[33]));
+ cache.setOnWatchlist(cursor.getInt(cacheColumnIndex[34]) == 1);
+ cache.setReliableLatLon(cursor.getInt(cacheColumnIndex[35]) > 0);
+ cache.setUserModifiedCoords(cursor.getInt(cacheColumnIndex[36]) > 0);
+ cache.setFinalDefined(cursor.getInt(cacheColumnIndex[39]) > 0);
Log.d("Loading " + cache.toString() + " (" + cache.getListId() + ") from DB");
return cache;
}
- public List<String> loadAttributes(String geocode) {
+ public static List<String> loadAttributes(String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- ArrayList<String> attributes = new ArrayList<String>();
+ final ArrayList<String> attributes = new ArrayList<String>();
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableAttributes,
new String[]{"attribute"},
"geocode = ?",
@@ -1733,32 +1640,23 @@ public class cgData {
null,
"100");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
- int index = cursor.getColumnIndex("attribute");
-
- do {
- attributes.add(cursor.getString(index));
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ attributes.add(cursor.getString(0));
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return attributes;
}
- public cgWaypoint loadWaypoint(int id) {
+ public static Waypoint loadWaypoint(int id) {
if (id == 0) {
return null;
}
init();
- cgWaypoint waypoint = null;
-
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableWaypoints,
WAYPOINT_COLUMNS,
"_id = ?",
@@ -1770,29 +1668,23 @@ public class cgData {
Log.d("cgData.loadWaypoint(" + id + ")");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
+ final Waypoint waypoint = cursor.moveToFirst() ? createWaypointFromDatabaseContent(cursor) : null;
- waypoint = createWaypointFromDatabaseContent(cursor);
- }
-
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return waypoint;
}
- public List<cgWaypoint> loadWaypoints(final String geocode) {
+ public static List<Waypoint> loadWaypoints(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- List<cgWaypoint> waypoints = new ArrayList<cgWaypoint>();
+ final List<Waypoint> waypoints = new ArrayList<Waypoint>();
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableWaypoints,
WAYPOINT_COLUMNS,
"geocode = ?",
@@ -1802,29 +1694,20 @@ public class cgData {
"_id",
"100");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
-
- do {
-
- cgWaypoint waypoint = createWaypointFromDatabaseContent(cursor);
-
- waypoints.add(waypoint);
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ waypoints.add(createWaypointFromDatabaseContent(cursor));
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return waypoints;
}
- private static cgWaypoint createWaypointFromDatabaseContent(Cursor cursor) {
- String name = cursor.getString(cursor.getColumnIndex("name"));
- WaypointType type = WaypointType.findById(cursor.getString(cursor.getColumnIndex("type")));
- boolean own = cursor.getInt(cursor.getColumnIndex("own")) != 0;
- cgWaypoint waypoint = new cgWaypoint(name, type, own);
+ private static Waypoint createWaypointFromDatabaseContent(final Cursor cursor) {
+ final String name = cursor.getString(cursor.getColumnIndex("name"));
+ final WaypointType type = WaypointType.findById(cursor.getString(cursor.getColumnIndex("type")));
+ final boolean own = cursor.getInt(cursor.getColumnIndex("own")) != 0;
+ final Waypoint waypoint = new Waypoint(name, type, own);
waypoint.setId(cursor.getInt(cursor.getColumnIndex("_id")));
waypoint.setGeocode(cursor.getString(cursor.getColumnIndex("geocode")));
@@ -1837,16 +1720,16 @@ public class cgData {
return waypoint;
}
- private List<cgImage> loadSpoilers(String geocode) {
+ private static List<Image> loadSpoilers(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- List<cgImage> spoilers = new ArrayList<cgImage>();
+ final List<Image> spoilers = new ArrayList<Image>();
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableSpoilers,
new String[]{"url", "title", "description"},
"geocode = ?",
@@ -1856,22 +1739,11 @@ public class cgData {
null,
"100");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
- int indexUrl = cursor.getColumnIndex("url");
- int indexTitle = cursor.getColumnIndex("title");
- int indexDescription = cursor.getColumnIndex("description");
-
- do {
- cgImage spoiler = new cgImage(cursor.getString(indexUrl), cursor.getString(indexTitle), cursor.getString(indexDescription));
-
- spoilers.add(spoiler);
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ spoilers.add(new Image(cursor.getString(0), cursor.getString(1), cursor.getString(2)));
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return spoilers;
}
@@ -1882,10 +1754,10 @@ public class cgData {
*
* @return A list of previously entered destinations or an empty list.
*/
- public List<Destination> loadHistoryOfSearchedLocations() {
+ public static List<Destination> loadHistoryOfSearchedLocations() {
init();
- Cursor cursor = database.query(dbTableSearchDestionationHistory,
+ final Cursor cursor = database.query(dbTableSearchDestionationHistory,
new String[]{"_id", "date", "latitude", "longitude"},
null,
null,
@@ -1896,36 +1768,25 @@ public class cgData {
final List<Destination> destinations = new LinkedList<Destination>();
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
- int indexId = cursor.getColumnIndex("_id");
- int indexDate = cursor.getColumnIndex("date");
- int indexLatitude = cursor.getColumnIndex("latitude");
- int indexLongitude = cursor.getColumnIndex("longitude");
-
- do {
- final Destination dest = new Destination(cursor.getLong(indexId), cursor.getLong(indexDate), getCoords(cursor, indexLatitude, indexLongitude));
+ while (cursor.moveToNext()) {
+ final Destination dest = new Destination(cursor.getLong(0), cursor.getLong(1), getCoords(cursor, 2, 3));
- // If coordinates are non-existent or invalid, do not consider
- // this point.
- if (dest.getCoords() != null) {
- destinations.add(dest);
- }
- } while (cursor.moveToNext());
+ // If coordinates are non-existent or invalid, do not consider this point.
+ if (dest.getCoords() != null) {
+ destinations.add(dest);
+ }
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return destinations;
}
- public boolean clearSearchedDestinations() {
- boolean success = true;
+ public static boolean clearSearchedDestinations() {
init();
database.beginTransaction();
+ boolean success = true;
try {
database.delete(dbTableSearchDestionationHistory, null, null);
database.setTransactionSuccessful();
@@ -1939,7 +1800,7 @@ public class cgData {
return success;
}
- public List<LogEntry> loadLogs(String geocode) {
+ public static List<LogEntry> loadLogs(String geocode) {
List<LogEntry> logs = new ArrayList<LogEntry>();
if (StringUtils.isBlank(geocode)) {
@@ -1948,60 +1809,45 @@ public class cgData {
init();
- Cursor cursor = database.rawQuery(
- "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url FROM "
- + dbTableLogs + " LEFT OUTER JOIN " + dbTableLogImages
+ final Cursor cursor = database.rawQuery(
+ /* 0 1 2 3 4 5 6 7 8 9 10 */
+ "SELECT cg_logs._id as cg_logs_id, type, author, log, date, found, friend, " + dbTableLogImages + "._id as cg_logImages_id, log_id, title, url"
+ + " FROM " + dbTableLogs + " LEFT OUTER JOIN " + dbTableLogImages
+ " ON ( cg_logs._id = log_id ) WHERE geocode = ? ORDER BY date desc, cg_logs._id asc", new String[]{geocode});
- if (cursor != null && cursor.getCount() > 0) {
- LogEntry log = null;
- int indexLogsId = cursor.getColumnIndex("cg_logs_id");
- int indexType = cursor.getColumnIndex("type");
- int indexAuthor = cursor.getColumnIndex("author");
- int indexLog = cursor.getColumnIndex("log");
- int indexDate = cursor.getColumnIndex("date");
- int indexFound = cursor.getColumnIndex("found");
- int indexFriend = cursor.getColumnIndex("friend");
- int indexLogImagesId = cursor.getColumnIndex("cg_logImages_id");
- int indexTitle = cursor.getColumnIndex("title");
- int indexUrl = cursor.getColumnIndex("url");
- while (cursor.moveToNext() && logs.size() < 100) {
- if (log == null || log.id != cursor.getInt(indexLogsId)) {
- log = new LogEntry(
- cursor.getString(indexAuthor),
- cursor.getLong(indexDate),
- LogType.getById(cursor.getInt(indexType)),
- cursor.getString(indexLog));
- log.id = cursor.getInt(indexLogsId);
- log.found = cursor.getInt(indexFound);
- log.friend = cursor.getInt(indexFriend) == 1;
- logs.add(log);
- }
- if (!cursor.isNull(indexLogImagesId)) {
- String title = cursor.getString(indexTitle);
- String url = cursor.getString(indexUrl);
- log.addLogImage(new cgImage(url, title));
- }
+ LogEntry log = null;
+ while (cursor.moveToNext() && logs.size() < 100) {
+ if (log == null || log.id != cursor.getInt(0)) {
+ log = new LogEntry(
+ cursor.getString(2),
+ cursor.getLong(4),
+ LogType.getById(cursor.getInt(1)),
+ cursor.getString(3));
+ log.id = cursor.getInt(0);
+ log.found = cursor.getInt(5);
+ log.friend = cursor.getInt(6) == 1;
+ logs.add(log);
+ }
+ if (!cursor.isNull(7)) {
+ log.addLogImage(new Image(cursor.getString(10), cursor.getString(9)));
}
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return logs;
}
- public Map<LogType, Integer> loadLogCounts(String geocode) {
+ public static Map<LogType, Integer> loadLogCounts(String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>();
+ final Map<LogType, Integer> logCounts = new HashMap<LogType, Integer>();
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableLogCount,
new String[]{"type", "count"},
"geocode = ?",
@@ -2011,36 +1857,25 @@ public class cgData {
null,
"100");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
- int indexType = cursor.getColumnIndex("type");
- int indexCount = cursor.getColumnIndex("count");
-
- do {
- LogType type = LogType.getById(cursor.getInt(indexType));
- Integer count = cursor.getInt(indexCount);
-
- logCounts.put(type, count);
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ logCounts.put(LogType.getById(cursor.getInt(0)), cursor.getInt(1));
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return logCounts;
}
- private List<cgTrackable> loadInventory(String geocode) {
+ private static List<Trackable> loadInventory(String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- List<cgTrackable> trackables = new ArrayList<cgTrackable>();
+ final List<Trackable> trackables = new ArrayList<Trackable>();
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableTrackables,
new String[]{"_id", "updated", "tbcode", "guid", "title", "owner", "released", "goal", "description"},
"geocode = ?",
@@ -2050,33 +1885,23 @@ public class cgData {
"title COLLATE NOCASE ASC",
"100");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
-
- do {
- cgTrackable trackable = createTrackableFromDatabaseContent(cursor);
-
- trackables.add(trackable);
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ trackables.add(createTrackableFromDatabaseContent(cursor));
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return trackables;
}
- public cgTrackable loadTrackable(String geocode) {
+ public static Trackable loadTrackable(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- cgTrackable trackable = new cgTrackable();
-
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableTrackables,
new String[]{"updated", "tbcode", "guid", "title", "owner", "released", "goal", "description"},
"tbcode = ?",
@@ -2086,30 +1911,25 @@ public class cgData {
null,
"1");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
- trackable = createTrackableFromDatabaseContent(cursor);
- }
+ final Trackable trackable = cursor.moveToFirst() ? createTrackableFromDatabaseContent(cursor) : null;
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return trackable;
}
- private cgTrackable createTrackableFromDatabaseContent(Cursor cursor) {
- cgTrackable trackable = new cgTrackable();
+ private static Trackable createTrackableFromDatabaseContent(final Cursor cursor) {
+ final Trackable trackable = new Trackable();
trackable.setGeocode(cursor.getString(cursor.getColumnIndex("tbcode")));
trackable.setGuid(cursor.getString(cursor.getColumnIndex("guid")));
trackable.setName(cursor.getString(cursor.getColumnIndex("title")));
trackable.setOwner(cursor.getString(cursor.getColumnIndex("owner")));
- String released = cursor.getString(cursor.getColumnIndex("released"));
+ final String released = cursor.getString(cursor.getColumnIndex("released"));
if (released != null) {
try {
long releaseMilliSeconds = Long.parseLong(released);
trackable.setReleased(new Date(releaseMilliSeconds));
- } catch (NumberFormatException e) {
+ } catch (final NumberFormatException e) {
Log.e("createTrackableFromDatabaseContent", e);
}
}
@@ -2120,103 +1940,99 @@ public class cgData {
}
/**
- * Number of caches stored. The number is shown on the starting activity of c:geo
+ * Number of caches stored for a given type and/or list
*
- * @param detailedOnly
* @param cacheType
* @param list
* @return
*/
- public int getAllStoredCachesCount(final boolean detailedOnly, final CacheType cacheType, final int list) {
+ public static int getAllStoredCachesCount(final CacheType cacheType, final int list) {
if (cacheType == null) {
throw new IllegalArgumentException("cacheType must not be null");
}
- init();
-
- String listSql;
- String listSqlW;
- if (list == 0) {
- listSql = " where reason >= 1";
- listSqlW = " and reason >= 1";
- } else if (list >= 1) {
- listSql = " where reason = " + list;
- listSqlW = " and reason = " + list;
- } else {
- return 0;
+ if (list <= 0) {
+ throw new IllegalArgumentException("list must be > 0");
}
+ init();
- int count = 0;
try {
- String sql;
- if (!detailedOnly) {
- if (cacheType == CacheType.ALL) {
- sql = "select count(_id) from " + dbTableCaches + listSql;
- } else {
- sql = "select count(_id) from " + dbTableCaches + " where type = " + DatabaseUtils.sqlEscapeString(cacheType.id) + listSqlW;
- }
+ StringBuilder sql = new StringBuilder("select count(_id) from " + dbTableCaches + " where detailed = 1");
+ String typeKey;
+ int reasonIndex;
+ if (cacheType != CacheType.ALL) {
+ sql.append(" and type = ?");
+ typeKey = cacheType.id;
+ reasonIndex = 2;
+ }
+ else {
+ typeKey = "all_types";
+ reasonIndex = 1;
+ }
+ String listKey;
+ if (list == StoredList.ALL_LIST_ID) {
+ sql.append(" and reason > 0");
+ listKey = "all_list";
} else {
- if (cacheType == CacheType.ALL) {
- sql = "select count(_id) from " + dbTableCaches + " where detailed = 1" + listSqlW;
- } else {
- sql = "select count(_id) from " + dbTableCaches + " where detailed = 1 and type = " + DatabaseUtils.sqlEscapeString(cacheType.id) + listSqlW;
- }
+ sql.append(" and reason = ?");
+ listKey = "list";
}
- SQLiteStatement compiledStmnt = database.compileStatement(sql);
- count = (int) compiledStmnt.simpleQueryForLong();
- compiledStmnt.close();
+
+ String key = "CountCaches_" + typeKey + "_" + listKey;
+
+ SQLiteStatement compiledStmnt = PreparedStatements.getStatement(key, sql.toString());
+ if (cacheType != CacheType.ALL) {
+ compiledStmnt.bindString(1, cacheType.id);
+ }
+ if (list != StoredList.ALL_LIST_ID) {
+ compiledStmnt.bindLong(reasonIndex, list);
+ }
+ return (int) compiledStmnt.simpleQueryForLong();
} catch (Exception e) {
- Log.e("cgData.loadAllStoredCachesCount: " + e.toString());
+ Log.e("cgData.loadAllStoredCachesCount", e);
}
- return count;
+ return 0;
}
- public int getAllHistoricCachesCount() {
+ public static int getAllHistoryCachesCount() {
init();
- int count = 0;
-
try {
- SQLiteStatement sqlCount = database.compileStatement("select count(_id) from " + dbTableCaches + " where visiteddate > 0");
- count = (int) sqlCount.simpleQueryForLong();
- sqlCount.close();
+ return (int) PreparedStatements.getCountHistoryCaches().simpleQueryForLong();
} catch (Exception e) {
- Log.e("cgData.getAllHistoricCachesCount: " + e.toString());
+ Log.e("cgData.getAllHistoricCachesCount", e);
}
- return count;
+ return 0;
}
/**
* Return a batch of stored geocodes.
*
- * @param detailedOnly
* @param coords
* the current coordinates to sort by distance, or null to sort by geocode
* @param cacheType
* @param listId
- * @return
+ * @return a non-null set of geocodes
*/
- public Set<String> loadBatchOfStoredGeocodes(final boolean detailedOnly, final Geopoint coords, final CacheType cacheType, final int listId) {
+ private static Set<String> loadBatchOfStoredGeocodes(final Geopoint coords, final CacheType cacheType, final int listId) {
if (cacheType == null) {
throw new IllegalArgumentException("cacheType must not be null");
}
init();
- Set<String> geocodes = new HashSet<String>();
+ final Set<String> geocodes = new HashSet<String>();
- StringBuilder specifySql = new StringBuilder();
+ final StringBuilder selection = new StringBuilder();
- specifySql.append("reason ");
- specifySql.append(listId != StoredList.ALL_LIST_ID ? "=" + Math.max(listId, 1) : ">= " + StoredList.STANDARD_LIST_ID);
-
- if (detailedOnly) {
- specifySql.append(" and detailed = 1 ");
- }
+ selection.append("reason ");
+ selection.append(listId != StoredList.ALL_LIST_ID ? "=" + Math.max(listId, 1) : ">= " + StoredList.STANDARD_LIST_ID);
+ selection.append(" and detailed = 1 ");
+ String[] selectionArgs = null;
if (cacheType != CacheType.ALL) {
- specifySql.append(" and type = ");
- specifySql.append(DatabaseUtils.sqlEscapeString(cacheType.id));
+ selection.append(" and type = ?");
+ selectionArgs = new String[] { String.valueOf(cacheType.id) };
}
try {
@@ -2226,8 +2042,8 @@ public class cgData {
dbTableCaches,
new String[]{"geocode", "(abs(latitude-" + String.format((Locale) null, "%.6f", coords.getLatitude()) +
") + abs(longitude-" + String.format((Locale) null, "%.6f", coords.getLongitude()) + ")) as dif"},
- specifySql.toString(),
- null,
+ selection.toString(),
+ selectionArgs,
null,
null,
"dif",
@@ -2236,86 +2052,69 @@ public class cgData {
cursor = database.query(
dbTableCaches,
new String[]{"geocode"},
- specifySql.toString(),
- null,
+ selection.toString(),
+ selectionArgs,
null,
null,
"geocode");
}
- if (cursor.moveToFirst()) {
- final int index = cursor.getColumnIndex("geocode");
-
- do {
- geocodes.add(cursor.getString(index));
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ geocodes.add(cursor.getString(0));
}
cursor.close();
-
- } catch (Exception e) {
- Log.e("cgData.loadBatchOfStoredGeocodes: " + e.toString());
+ } catch (final Exception e) {
+ Log.e("cgData.loadBatchOfStoredGeocodes", e);
}
return geocodes;
}
- public Set<String> loadBatchOfHistoricGeocodes(final boolean detailedOnly, final CacheType cacheType) {
+ private static Set<String> loadBatchOfHistoricGeocodes(final boolean detailedOnly, final CacheType cacheType) {
init();
- Set<String> geocodes = new HashSet<String>();
+ final Set<String> geocodes = new HashSet<String>();
- StringBuilder specifySql = new StringBuilder();
- specifySql.append("visiteddate > 0");
+ final StringBuilder selection = new StringBuilder("visiteddate > 0");
if (detailedOnly) {
- specifySql.append(" and detailed = 1");
+ selection.append(" and detailed = 1");
}
+ String[] selectionArgs = null;
if (cacheType != CacheType.ALL) {
- specifySql.append(" and type = ");
- specifySql.append(DatabaseUtils.sqlEscapeString(cacheType.id));
+ selection.append(" and type = ?");
+ selectionArgs = new String[] { String.valueOf(cacheType.id) };
}
try {
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableCaches,
new String[]{"geocode"},
- specifySql.toString(),
- null,
+ selection.toString(),
+ selectionArgs,
null,
null,
"visiteddate",
null);
-
- if (cursor != null) {
- if (cursor.getCount() > 0) {
- cursor.moveToFirst();
- int index = cursor.getColumnIndex("geocode");
-
- do {
- geocodes.add(cursor.getString(index));
- } while (cursor.moveToNext());
- } else {
- cursor.close();
- return null;
- }
-
- cursor.close();
+ while (cursor.moveToNext()) {
+ geocodes.add(cursor.getString(0));
}
+ cursor.close();
} catch (Exception e) {
- Log.e("cgData.loadBatchOfHistoricGeocodes: " + e.toString());
+ Log.e("cgData.loadBatchOfHistoricGeocodes", e);
}
return geocodes;
}
/** Retrieve all stored caches from DB */
- public Set<String> loadCachedInViewport(final Viewport viewport, final CacheType cacheType) {
+ public static SearchResult loadCachedInViewport(final Viewport viewport, final CacheType cacheType) {
return loadInViewport(false, viewport, cacheType);
}
/** Retrieve stored caches from DB with listId >= 1 */
- public Set<String> loadStoredInViewport(final Viewport viewport, final CacheType cacheType) {
+ public static SearchResult loadStoredInViewport(final Viewport viewport, final CacheType cacheType) {
return loadInViewport(true, viewport, cacheType);
}
@@ -2331,7 +2130,7 @@ public class cgData {
* @param cacheType
* @return Set with geocodes
*/
- private Set<String> loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) {
+ private static SearchResult loadInViewport(final boolean stored, final Viewport viewport, final CacheType cacheType) {
init();
final Set<String> geocodes = new HashSet<String>();
@@ -2342,47 +2141,45 @@ public class cgData {
}
// viewport limitation
- final StringBuilder where = new StringBuilder(buildCoordinateWhere(dbTableCaches, viewport));
+ final StringBuilder selection = new StringBuilder(buildCoordinateWhere(dbTableCaches, viewport));
// cacheType limitation
+ String[] selectionArgs = null;
if (cacheType != CacheType.ALL) {
- where.append(" and type = ");
- where.append(DatabaseUtils.sqlEscapeString(cacheType.id));
+ selection.append(" and type = ?");
+ selectionArgs = new String[] { String.valueOf(cacheType.id) };
}
// offline caches only
if (stored) {
- where.append(" and reason >= " + StoredList.STANDARD_LIST_ID);
+ selection.append(" and reason >= " + StoredList.STANDARD_LIST_ID);
}
try {
final Cursor cursor = database.query(
dbTableCaches,
new String[]{"geocode"},
- where.toString(),
- null,
+ selection.toString(),
+ selectionArgs,
null,
null,
null,
"500");
- if (cursor.moveToFirst()) {
- final int index = cursor.getColumnIndex("geocode");
-
- do {
- geocodes.add(cursor.getString(index));
- } while (cursor.moveToNext());
+ while (cursor.moveToNext()) {
+ geocodes.add(cursor.getString(0));
}
+
cursor.close();
- } catch (Exception e) {
- Log.e("cgData.loadInViewport: " + e.toString());
+ } catch (final Exception e) {
+ Log.e("cgData.loadInViewport", e);
}
- return geocodes;
+ return new SearchResult(geocodes);
}
/** delete caches from the DB store 3 days or more before */
- public void clean() {
+ public static void clean() {
clean(false);
}
@@ -2392,15 +2189,17 @@ public class cgData {
* @param more
* true = all caches false = caches stored 3 days or more before
*/
- public void clean(boolean more) {
+ public static void clean(final boolean more) {
+ if (databaseCleaned) {
+ return;
+ }
+
init();
Log.d("Database clean: started");
- Cursor cursor;
- Set<String> geocodes = new HashSet<String>();
-
try {
+ Cursor cursor;
if (more) {
cursor = database.query(
dbTableCaches,
@@ -2425,44 +2224,31 @@ public class cgData {
null);
}
- if (cursor != null) {
- if (cursor.getCount() > 0) {
- cursor.moveToFirst();
- final int index = cursor.getColumnIndex("geocode");
-
- do {
- geocodes.add(cursor.getString(index));
- } while (cursor.moveToNext());
- }
-
- cursor.close();
+ Set<String> geocodes = new HashSet<String>();
+ while (cursor.moveToNext()) {
+ geocodes.add(cursor.getString(0));
}
- final int size = geocodes.size();
- if (size > 0) {
- Log.d("Database clean: removing " + size + " geocaches from listId=0");
+ cursor.close();
+ if (!geocodes.isEmpty()) {
+ Log.d("Database clean: removing " + geocodes.size() + " geocaches from listId=0");
removeCaches(geocodes, LoadFlags.REMOVE_ALL);
}
-
- final SQLiteStatement countSql = database.compileStatement("select count(_id) from " + dbTableCaches + " where reason = 0");
- final int count = (int) countSql.simpleQueryForLong();
- countSql.close();
- Log.d("Database clean: " + count + " geocaches remaining for listId=0");
-
- } catch (Exception e) {
- Log.w("cgData.clean: " + e.toString());
+ } catch (final Exception e) {
+ Log.w("cgData.clean", e);
}
Log.d("Database clean: finished");
+ databaseCleaned = true;
}
- public void removeAllFromCache() {
+ public static void removeAllFromCache() {
// clean up CacheCache
cacheCache.removeAllFromCache();
}
- public void removeCache(final String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
+ public static void removeCache(final String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
removeCaches(Collections.singleton(geocode), removeFlags);
}
@@ -2472,7 +2258,7 @@ public class cgData {
* @param geocodes
* list of geocodes to drop from cache
*/
- public void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
+ public static void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
if (CollectionUtils.isEmpty(geocodes)) {
return;
}
@@ -2519,7 +2305,7 @@ public class cgData {
}
}
- public boolean saveLogOffline(String geocode, Date date, LogType type, String log) {
+ public static boolean saveLogOffline(String geocode, Date date, LogType type, String log) {
if (StringUtils.isBlank(geocode)) {
Log.e("cgData.saveLogOffline: cannot log a blank geocode");
return false;
@@ -2546,16 +2332,15 @@ public class cgData {
return id != -1;
}
- public LogEntry loadLogOffline(String geocode) {
+ public static LogEntry loadLogOffline(String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
- LogEntry log = null;
- Cursor cursor = database.query(
+ final Cursor cursor = database.query(
dbTableLogsOffline,
new String[]{"_id", "type", "log", "date"},
"geocode = ?",
@@ -2565,24 +2350,20 @@ public class cgData {
"_id desc",
"1");
- if (cursor != null && cursor.getCount() > 0) {
- cursor.moveToFirst();
-
- log = new LogEntry(
- cursor.getLong(cursor.getColumnIndex("date")),
- LogType.getById(cursor.getInt(cursor.getColumnIndex("type"))),
- cursor.getString(cursor.getColumnIndex("log")));
- log.id = cursor.getInt(cursor.getColumnIndex("_id"));
+ LogEntry log = null;
+ if (cursor.moveToFirst()) {
+ log = new LogEntry(cursor.getLong(3),
+ LogType.getById(cursor.getInt(1)),
+ cursor.getString(2));
+ log.id = cursor.getInt(0);
}
- if (cursor != null) {
- cursor.close();
- }
+ cursor.close();
return log;
}
- public void clearLogOffline(String geocode) {
+ public static void clearLogOffline(String geocode) {
if (StringUtils.isBlank(geocode)) {
return;
}
@@ -2592,35 +2373,14 @@ public class cgData {
database.delete(dbTableLogsOffline, "geocode = ?", new String[]{geocode});
}
- private SQLiteStatement getStatementLogCount() {
- return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + dbTableLogsOffline + " WHERE geocode = ?");
- }
-
- private synchronized SQLiteStatement getStatement(final String key, final String query) {
- SQLiteStatement statement = statements.get(key);
- if (statement == null) {
- statement = database.compileStatement(query);
- statements.put(key, statement);
- }
- return statement;
- }
-
- private SQLiteStatement getStatementCountStandardList() {
- return getStatement("CountStandardList", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason = " + StoredList.STANDARD_LIST_ID);
- }
-
- private SQLiteStatement getStatementCountAllLists() {
- return getStatement("CountAllLists", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason >= " + StoredList.STANDARD_LIST_ID);
- }
-
- public boolean hasLogOffline(final String geocode) {
+ public static boolean hasLogOffline(final String geocode) {
if (StringUtils.isBlank(geocode)) {
return false;
}
init();
try {
- final SQLiteStatement logCount = getStatementLogCount();
+ final SQLiteStatement logCount = PreparedStatements.getLogCountOfGeocode();
synchronized (logCount) {
logCount.bindString(1, geocode);
return logCount.simpleQueryForLong() > 0;
@@ -2632,7 +2392,7 @@ public class cgData {
return false;
}
- public void setVisitDate(List<String> geocodes, long visitedDate) {
+ private static void setVisitDate(List<String> geocodes, long visitedDate) {
if (geocodes.isEmpty()) {
return;
}
@@ -2641,11 +2401,12 @@ public class cgData {
database.beginTransaction();
try {
- ContentValues values = new ContentValues();
- values.put("visiteddate", visitedDate);
+ SQLiteStatement setVisit = PreparedStatements.getUpdateVisitDate();
for (String geocode : geocodes) {
- database.update(dbTableCaches, values, "geocode = ?", new String[]{geocode});
+ setVisit.bindLong(1, visitedDate);
+ setVisit.bindString(2, geocode);
+ setVisit.execute();
}
database.setTransactionSuccessful();
} finally {
@@ -2653,11 +2414,12 @@ public class cgData {
}
}
- public List<StoredList> getLists(Resources res) {
+ public static List<StoredList> getLists() {
init();
- List<StoredList> lists = new ArrayList<StoredList>();
- lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) getStatementCountStandardList().simpleQueryForLong()));
+ final Resources res = cgeoapplication.getInstance().getResources();
+ final List<StoredList> lists = new ArrayList<StoredList>();
+ lists.add(new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong()));
try {
String query = "SELECT l._id as _id, l.title as title, COUNT(c._id) as count" +
@@ -2666,47 +2428,38 @@ public class cgData {
" GROUP BY l._id" +
" ORDER BY l.title COLLATE NOCASE ASC";
- Cursor cursor = database.rawQuery(query, null);
+ final Cursor cursor = database.rawQuery(query, null);
ArrayList<StoredList> storedLists = getListsFromCursor(cursor);
lists.addAll(storedLists);
-
- } catch (Exception e) {
- Log.e("cgData.readLists: " + e.toString());
+ cursor.close();
+ } catch (final Exception e) {
+ Log.e("cgData.readLists", e);
}
return lists;
}
- private static ArrayList<StoredList> getListsFromCursor(Cursor cursor) {
- ArrayList<StoredList> result = new ArrayList<StoredList>();
- if (cursor != null) {
- if (cursor.getCount() > 0) {
- cursor.moveToFirst();
- int indexId = cursor.getColumnIndex("_id");
- int indexTitle = cursor.getColumnIndex("title");
- int indexCount = cursor.getColumnIndex("count");
- do {
- int count = 0;
- if (indexCount >= 0) {
- count = cursor.getInt(indexCount);
- }
- StoredList list = new StoredList(cursor.getInt(indexId) + customListIdOffset, cursor.getString(indexTitle), count);
- result.add(list);
- } while (cursor.moveToNext());
- }
-
- cursor.close();
+ private static ArrayList<StoredList> getListsFromCursor(final Cursor cursor) {
+ final int indexId = cursor.getColumnIndex("_id");
+ final int indexTitle = cursor.getColumnIndex("title");
+ final int indexCount = cursor.getColumnIndex("count");
+ final ArrayList<StoredList> result = new ArrayList<StoredList>();
+ while (cursor.moveToNext()) {
+ final int count = indexCount != -1 ? cursor.getInt(indexCount) : 0;
+ final StoredList list = new StoredList(cursor.getInt(indexId) + customListIdOffset, cursor.getString(indexTitle), count);
+ result.add(list);
}
+ cursor.close();
return result;
}
- public StoredList getList(int id, Resources res) {
+ public static StoredList getList(int id) {
init();
if (id >= customListIdOffset) {
Cursor cursor = database.query(
dbTableLists,
new String[]{"_id", "title"},
- "_id = " + (id - customListIdOffset),
- null,
+ "_id = ? ",
+ new String[] { String.valueOf(id - customListIdOffset) },
null,
null,
null);
@@ -2716,18 +2469,23 @@ public class cgData {
}
}
+ Resources res = cgeoapplication.getInstance().getResources();
if (id == StoredList.ALL_LIST_ID) {
- return new StoredList(StoredList.ALL_LIST_ID, res.getString(R.string.list_all_lists), (int) getStatementCountAllLists().simpleQueryForLong());
+ return new StoredList(StoredList.ALL_LIST_ID, res.getString(R.string.list_all_lists), getAllCachesCount());
}
// fall back to standard list in case of invalid list id
if (id == StoredList.STANDARD_LIST_ID || id >= customListIdOffset) {
- return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) getStatementCountStandardList().simpleQueryForLong());
+ return new StoredList(StoredList.STANDARD_LIST_ID, res.getString(R.string.list_inbox), (int) PreparedStatements.getCountCachesOnStandardList().simpleQueryForLong());
}
return null;
}
+ public static int getAllCachesCount() {
+ return (int) PreparedStatements.getCountAllCaches().simpleQueryForLong();
+ }
+
/**
* Create a new list
*
@@ -2735,7 +2493,7 @@ public class cgData {
* Name
* @return new listId
*/
- public int createList(String name) {
+ public static int createList(String name) {
int id = -1;
if (StringUtils.isBlank(name)) {
return id;
@@ -2765,15 +2523,15 @@ public class cgData {
* New name of list
* @return Number of lists changed
*/
- public int renameList(final int listId, final String name) {
+ public static int renameList(final int listId, final String name) {
if (StringUtils.isBlank(name) || StoredList.STANDARD_LIST_ID == listId) {
return 0;
}
init();
- int count = 0;
database.beginTransaction();
+ int count = 0;
try {
ContentValues values = new ContentValues();
values.put("title", name);
@@ -2794,23 +2552,23 @@ public class cgData {
* @param listId
* @return true if the list got deleted, false else
*/
- public boolean removeList(int listId) {
- boolean status = false;
+ public static boolean removeList(int listId) {
if (listId < customListIdOffset) {
- return status;
+ return false;
}
init();
database.beginTransaction();
+ boolean status = false;
try {
int cnt = database.delete(dbTableLists, "_id = " + (listId - customListIdOffset), null);
if (cnt > 0) {
// move caches from deleted list to standard list
- ContentValues values = new ContentValues();
- values.put("reason", StoredList.STANDARD_LIST_ID);
- database.update(dbTableCaches, values, "reason = " + listId, null);
+ SQLiteStatement moveToStandard = PreparedStatements.getMoveToStandardList();
+ moveToStandard.bindLong(1, listId);
+ moveToStandard.execute();
status = true;
}
@@ -2823,7 +2581,11 @@ public class cgData {
return status;
}
- public void moveToList(final List<cgCache> caches, final int listId) {
+ public static void moveToList(final Geocache cache, final int listId) {
+ moveToList(Collections.singletonList(cache), listId);
+ }
+
+ public static void moveToList(final List<Geocache> caches, final int listId) {
if (listId == StoredList.ALL_LIST_ID) {
return;
}
@@ -2832,13 +2594,14 @@ public class cgData {
}
init();
- final ContentValues values = new ContentValues();
- values.put("reason", listId);
+ SQLiteStatement move = PreparedStatements.getMoveToList();
database.beginTransaction();
try {
- for (cgCache cache : caches) {
- database.update(dbTableCaches, values, "geocode = ?", new String[]{cache.getGeocode()});
+ for (Geocache cache : caches) {
+ move.bindLong(1, listId);
+ move.bindString(2, cache.getGeocode());
+ move.execute();
cache.setListId(listId);
}
database.setTransactionSuccessful();
@@ -2847,61 +2610,39 @@ public class cgData {
}
}
- public synchronized boolean status() {
+ public static boolean isInitialized() {
return database != null;
-
}
- public boolean removeSearchedDestination(Destination destination) {
- boolean success = true;
+ public static boolean removeSearchedDestination(Destination destination) {
if (destination == null) {
- success = false;
- } else {
- init();
-
- database.beginTransaction();
- try {
- database.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null);
- database.setTransactionSuccessful();
- } catch (Exception e) {
- Log.e("Unable to remove searched destination", e);
- success = false;
- } finally {
- database.endTransaction();
- }
+ return false;
}
+ init();
- return success;
- }
-
- private SQLiteStatement getStatementDescription() {
- return getStatement("descriptionFromGeocode", "SELECT description FROM " + dbTableCaches + " WHERE geocode = ?");
- }
-
- private SQLiteStatement getStatementListIdFromGeocode() {
- return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE geocode = ?");
- }
-
- private SQLiteStatement getStatementListIdFromGuid() {
- return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE guid = ?");
- }
-
- private SQLiteStatement getStatementCacheId() {
- return getStatement("cacheIdFromGeocode", "SELECT cacheid FROM " + dbTableCaches + " WHERE geocode = ?");
- }
+ database.beginTransaction();
+ boolean result = false;
+ try {
+ database.delete(dbTableSearchDestionationHistory, "_id = " + destination.getId(), null);
+ database.setTransactionSuccessful();
+ result = true;
+ } catch (Exception e) {
+ Log.e("Unable to remove searched destination", e);
+ } finally {
+ database.endTransaction();
+ }
- private SQLiteStatement getStatementGeocode() {
- return getStatement("geocodeFromGuid", "SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?");
+ return result;
}
- public String getCacheDescription(String geocode) {
+ public static String getCacheDescription(String geocode) {
if (StringUtils.isBlank(geocode)) {
return null;
}
init();
try {
- final SQLiteStatement description = getStatementDescription();
+ final SQLiteStatement description = PreparedStatements.getDescriptionOfGeocode();
synchronized (description) {
description.bindString(1, geocode);
return description.simpleQueryForString();
@@ -2934,7 +2675,7 @@ public class cgData {
private static String whereGeocodeIn(Set<String> geocodes) {
final StringBuilder where = new StringBuilder();
- if (geocodes != null && geocodes.size() > 0) {
+ if (geocodes != null && !geocodes.isEmpty()) {
StringBuilder all = new StringBuilder();
for (String geocode : geocodes) {
if (all.length() > 0) {
@@ -2958,16 +2699,16 @@ public class cgData {
* @return
*/
- public Set<cgWaypoint> loadWaypoints(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) {
+ public static Set<Waypoint> loadWaypoints(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) {
final StringBuilder where = new StringBuilder(buildCoordinateWhere(dbTableWaypoints, viewport));
if (excludeMine) {
- where.append(" and ").append(dbTableCaches).append(".own == 0 and ").append(dbTableCaches).append(".found == 0");
+ where.append(" and ").append(dbTableCaches).append(".found == 0");
}
if (excludeDisabled) {
where.append(" and ").append(dbTableCaches).append(".disabled == 0");
}
if (type != CacheType.ALL) {
- where.append(" and ").append(dbTableCaches).append(".type == '").append(type.id).append("'");
+ where.append(" and ").append(dbTableCaches).append(".type == '").append(type.id).append('\'');
}
init();
@@ -2977,23 +2718,16 @@ public class cgData {
}
query.append(" FROM ").append(dbTableWaypoints).append(", ").append(dbTableCaches).append(" WHERE ").append(dbTableWaypoints).append(".geocode == ").append(dbTableCaches).append(".geocode and ").append(where);
+ final Set<Waypoint> waypoints = new HashSet<Waypoint>();
final Cursor cursor = database.rawQuery(query.toString(), null);
- try {
- if (!cursor.moveToFirst()) {
- return Collections.emptySet();
- }
-
- final Set<cgWaypoint> waypoints = new HashSet<cgWaypoint>();
- do {
- waypoints.add(createWaypointFromDatabaseContent(cursor));
- } while (cursor.moveToNext());
- return waypoints;
- } finally {
- cursor.close();
+ while (cursor.moveToNext()) {
+ waypoints.add(createWaypointFromDatabaseContent(cursor));
}
+ cursor.close();
+ return waypoints;
}
- public String[] getTrackableCodes() {
+ public static String[] getTrackableCodes() {
init();
final Cursor cursor = database.query(
@@ -3005,21 +2739,168 @@ public class cgData {
null,
"updated DESC",
"100");
+ return getFirstColumn(cursor);
+ }
- final ArrayList<String> list = new ArrayList<String>();
- if (cursor != null) {
- if (cursor.getCount() > 0) {
- cursor.moveToFirst();
+ /**
+ * Extract the first column of the cursor rows and close the cursor.
+ *
+ * @param cursor a database cursor
+ * @return the first column of each row
+ */
+ private static String[] getFirstColumn(final Cursor cursor) {
+ final String[] result = new String[cursor.getCount()];
+ for (int i = 0; cursor.moveToNext(); i++) {
+ result[i] = cursor.getString(0);
+ }
+ cursor.close();
+ return result;
+ }
+
+ public static boolean saveChangedCache(Geocache cache) {
+ return cgData.saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE));
+ }
- final int index = cursor.getColumnIndex("tbcode");
- do {
- list.add(cursor.getString(index));
- } while (cursor.moveToNext());
+ private static class PreparedStatements {
+
+ private static HashMap<String, SQLiteStatement> statements = new HashMap<String, SQLiteStatement>();
+
+ public static SQLiteStatement getMoveToStandardList() {
+ return getStatement("MoveToStandardList", "UPDATE " + dbTableCaches + " SET reason = " + StoredList.STANDARD_LIST_ID + " WHERE reason = ?");
+ }
+
+ public static SQLiteStatement getMoveToList() {
+ return getStatement("MoveToList", "UPDATE " + dbTableCaches + " SET reason = ? WHERE geocode = ?");
+ }
+
+ public static SQLiteStatement getUpdateVisitDate() {
+ return getStatement("UpdateVisitDate", "UPDATE " + dbTableCaches + " SET visiteddate = ? WHERE geocode = ?");
+ }
+
+ public static SQLiteStatement getInsertLogImage() {
+ return getStatement("InsertLogImage", "INSERT INTO " + dbTableLogImages + " (log_id, title, url) VALUES (?, ?, ?)");
+ }
+
+ public static SQLiteStatement getInsertLogCounts() {
+ return getStatement("InsertLogCounts", "INSERT INTO " + dbTableLogCount + " (geocode, updated, type, count) VALUES (?, ?, ?, ?)");
+ }
+
+ public static SQLiteStatement getInsertSpoiler() {
+ return getStatement("InsertSpoiler", "INSERT INTO " + dbTableSpoilers + " (geocode, updated, url, title, description) VALUES (?, ?, ?, ?, ?)");
+ }
+
+ public static SQLiteStatement getInsertSearchDestination(Destination destination) {
+ final SQLiteStatement statement = getStatement("InsertSearch", "INSERT INTO " + dbTableSearchDestionationHistory + " (date, latitude, longitude) VALUES (?, ?, ?)");
+ statement.bindLong(1, destination.getDate());
+ final Geopoint coords = destination.getCoords();
+ statement.bindDouble(2, coords.getLatitude());
+ statement.bindDouble(3, coords.getLongitude());
+ return statement;
+ }
+
+ private static void clearPreparedStatements() {
+ for (SQLiteStatement statement : statements.values()) {
+ statement.close();
}
- cursor.close();
+ statements.clear();
}
- return list.toArray(new String[list.size()]);
+ private static synchronized SQLiteStatement getStatement(final String key, final String query) {
+ SQLiteStatement statement = statements.get(key);
+ if (statement == null) {
+ init();
+ statement = database.compileStatement(query);
+ statements.put(key, statement);
+ }
+ return statement;
+ }
+
+ public static SQLiteStatement getCountHistoryCaches() {
+ return getStatement("HistoryCount", "select count(_id) from " + dbTableCaches + " where visiteddate > 0");
+ }
+
+ private static SQLiteStatement getLogCountOfGeocode() {
+ return getStatement("LogCountFromGeocode", "SELECT count(_id) FROM " + cgData.dbTableLogsOffline + " WHERE geocode = ?");
+ }
+
+ private static SQLiteStatement getCountCachesOnStandardList() {
+ return getStatement("CountStandardList", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason = " + StoredList.STANDARD_LIST_ID);
+ }
+
+ private static SQLiteStatement getCountAllCaches() {
+ return getStatement("CountAllLists", "SELECT count(_id) FROM " + dbTableCaches + " WHERE reason >= " + StoredList.STANDARD_LIST_ID);
+ }
+
+ private static SQLiteStatement getInsertLog() {
+ return getStatement("InsertLog", "INSERT INTO " + dbTableLogs + " (geocode, updated, type, author, log, date, found, friend) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+ }
+
+ private static SQLiteStatement getInsertAttribute() {
+ return getStatement("InsertAttribute", "INSERT INTO " + dbTableAttributes + " (geocode, updated, attribute) VALUES (?, ?, ?)");
+ }
+
+ private static SQLiteStatement getDescriptionOfGeocode() {
+ return getStatement("descriptionFromGeocode", "SELECT description FROM " + dbTableCaches + " WHERE geocode = ?");
+ }
+
+ private static SQLiteStatement getListIdOfGeocode() {
+ return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE geocode = ?");
+ }
+
+ private static SQLiteStatement getListIdOfGuid() {
+ return getStatement("listFromGeocode", "SELECT reason FROM " + dbTableCaches + " WHERE guid = ?");
+ }
+
+ private static SQLiteStatement getCacheIdOfGeocode() {
+ return getStatement("cacheIdFromGeocode", "SELECT cacheid FROM " + dbTableCaches + " WHERE geocode = ?");
+ }
+
+ private static SQLiteStatement getGeocodeOfGuid() {
+ return getStatement("geocodeFromGuid", "SELECT geocode FROM " + dbTableCaches + " WHERE guid = ?");
+ }
+
+ }
+
+ public static void saveVisitDate(final String geocode) {
+ setVisitDate(Collections.singletonList(geocode), System.currentTimeMillis());
+ }
+
+ public static void markDropped(List<Geocache> caches) {
+ moveToList(caches, StoredList.TEMPORARY_LIST_ID);
+ }
+
+ public static Viewport getBounds(String geocode) {
+ if (geocode == null) {
+ return null;
+ }
+
+ return cgData.getBounds(Collections.singleton(geocode));
+ }
+
+ public static void clearVisitDate(List<Geocache> caches) {
+ ArrayList<String> geocodes = new ArrayList<String>(caches.size());
+ for (Geocache cache : caches) {
+ geocodes.add(cache.getGeocode());
+ }
+ setVisitDate(geocodes, 0);
+ }
+
+ public static SearchResult getBatchOfStoredCaches(Geopoint coords, CacheType cacheType, int listId) {
+ final Set<String> geocodes = cgData.loadBatchOfStoredGeocodes(coords, cacheType, listId);
+ return new SearchResult(geocodes, cgData.getAllStoredCachesCount(cacheType, listId));
+ }
+
+ public static SearchResult getHistoryOfCaches(boolean detailedOnly, CacheType cacheType) {
+ final Set<String> geocodes = cgData.loadBatchOfHistoricGeocodes(detailedOnly, cacheType);
+ return new SearchResult(geocodes, cgData.getAllHistoryCachesCount());
+ }
+
+ public static boolean saveWaypoint(int id, String geocode, Waypoint waypoint) {
+ if (cgData.saveWaypointInternal(id, geocode, waypoint)) {
+ cgData.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
+ return true;
+ }
+ return false;
}
}
diff --git a/main/src/cgeo/geocaching/cgSelectMapfile.java b/main/src/cgeo/geocaching/cgSelectMapfile.java
index 3757c4f..ded81a7 100644
--- a/main/src/cgeo/geocaching/cgSelectMapfile.java
+++ b/main/src/cgeo/geocaching/cgSelectMapfile.java
@@ -31,7 +31,7 @@ public class cgSelectMapfile extends FileList<FileSelectionListAdapter> implemen
public void close() {
Intent intent = new Intent();
- intent.putExtra("mapfile", mapFile);
+ intent.putExtra(Intents.EXTRA_MAP_FILE, mapFile);
setResult(RESULT_OK, intent);
diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java
index c80ec6f..0091d7c 100644
--- a/main/src/cgeo/geocaching/cgeo.java
+++ b/main/src/cgeo/geocaching/cgeo.java
@@ -8,17 +8,17 @@ import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
import cgeo.geocaching.maps.CGeoMap;
-import cgeo.geocaching.network.StatusUpdater.Status;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.utils.GeoDirHandler;
-import cgeo.geocaching.utils.IObserver;
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;
@@ -27,36 +27,28 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.location.Address;
import android.location.Geocoder;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.view.ContextMenu;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.ImageView;
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 MENU_ABOUT = 0;
- private static final int MENU_HELPERS = 1;
- private static final int MENU_SETTINGS = 2;
- private static final int MENU_HISTORY = 3;
- private static final int MENU_SCAN = 4;
private static final int SCAN_REQUEST_CODE = 1;
- private static final int MENU_OPEN_LIST = 100;
-
public static final int SEARCH_REQUEST_CODE = 2;
private int version = 0;
@@ -172,74 +164,11 @@ public class cgeo extends AbstractActivity {
showToast(res.getString(reason == StatusCode.MAINTENANCE ? reason.getErrorString() : R.string.err_login_failed_toast));
}
} catch (Exception e) {
- Log.w("cgeo.firstLoginHander: " + e.toString());
+ Log.w("cgeo.firstLoginHander", e);
}
}
};
- private class StatusHandler extends Handler implements IObserver<Status> {
-
- @Override
- public void update(final Status data) {
- obtainMessage(0, data).sendToTarget();
- }
-
- @Override
- public void handleMessage(final Message msg) {
- final Status data = (Status) msg.obj;
- updateDisplay(data != null && data.message != null ? data : null);
- }
-
- private void updateDisplay(final Status data) {
- final ViewGroup status = (ViewGroup) findViewById(R.id.status);
- final ImageView statusIcon = (ImageView) findViewById(R.id.status_icon);
- final TextView statusMessage = (TextView) findViewById(R.id.status_message);
-
- if (data == null) {
- status.setVisibility(View.GONE);
- return;
- }
-
- if (data.icon != null) {
- final int iconId = res.getIdentifier(data.icon, "drawable", getPackageName());
- if (iconId != 0) {
- statusIcon.setImageResource(iconId);
- statusIcon.setVisibility(View.VISIBLE);
- } else {
- Log.e("StatusHandler: could not find icon corresponding to @drawable/" + data.icon);
- statusIcon.setVisibility(View.GONE);
- }
- } else {
- statusIcon.setVisibility(View.GONE);
- }
-
- String message = data.message;
- if (data.messageId != null) {
- final int messageId = res.getIdentifier(data.messageId, "string", getPackageName());
- if (messageId != 0) {
- message = res.getString(messageId);
- }
- }
-
- statusMessage.setText(message);
- status.setVisibility(View.VISIBLE);
-
- if (data.url != null) {
- status.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(data.url)));
- }
- });
- } else {
- status.setClickable(false);
- }
- }
-
- }
-
- private StatusHandler statusHandler = new StatusHandler();
-
public cgeo() {
super("c:geo-main-screen");
}
@@ -248,6 +177,12 @@ public class cgeo extends AbstractActivity {
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
@@ -288,7 +223,6 @@ public class cgeo extends AbstractActivity {
@Override
public void onResume() {
super.onResume();
- app.getStatusUpdater().addObserver(statusHandler);
locationUpdater.startGeo();
satellitesHandler.startGeo();
updateUserInfoHandler.sendEmptyMessage(-1);
@@ -312,7 +246,6 @@ public class cgeo extends AbstractActivity {
@Override
public void onPause() {
initialized = false;
- app.getStatusUpdater().deleteObserver(statusHandler);
locationUpdater.stopGeo();
satellitesHandler.stopGeo();
super.onPause();
@@ -320,18 +253,15 @@ public class cgeo extends AbstractActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_SETTINGS, 0, res.getString(R.string.menu_settings)).setIcon(R.drawable.ic_menu_preferences);
- menu.add(0, MENU_HISTORY, 0, res.getString(R.string.menu_history)).setIcon(R.drawable.ic_menu_recent_history);
- menu.add(0, MENU_HELPERS, 0, res.getString(R.string.menu_helpers)).setIcon(R.drawable.ic_menu_shopping);
- menu.add(0, MENU_SCAN, 0, res.getString(R.string.menu_scan_geo)).setIcon(R.drawable.ic_menu_barcode);
- menu.add(0, MENU_ABOUT, 0, res.getString(R.string.menu_about)).setIcon(R.drawable.ic_menu_info_details);
+ 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(MENU_SCAN);
+ MenuItem item = menu.findItem(R.id.menu_scan);
if (item != null) {
item.setEnabled(isIntentAvailable(SCAN_INTENT));
}
@@ -350,26 +280,25 @@ public class cgeo extends AbstractActivity {
public boolean onOptionsItemSelected(MenuItem item) {
final int id = item.getItemId();
switch (id) {
- case MENU_ABOUT:
+ case R.id.menu_about:
showAbout(null);
return true;
- case MENU_HELPERS:
+ case R.id.menu_helpers:
startActivity(new Intent(this, UsefulAppsActivity.class));
return true;
- case MENU_SETTINGS:
+ case R.id.menu_settings:
startActivity(new Intent(this, SettingsActivity.class));
return true;
- case MENU_HISTORY:
+ case R.id.menu_history:
cgeocaches.startActivityHistory(this);
return true;
- case MENU_SCAN:
+ case R.id.menu_scan:
startScannerApplication();
return true;
default:
- break;
+ return super.onOptionsItemSelected(item);
}
- return false;
}
private void startScannerApplication() {
@@ -408,90 +337,6 @@ public class cgeo extends AbstractActivity {
}
}
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
-
- // context menu for offline button
- if (v.getId() == R.id.search_offline) {
- menu.setHeaderTitle(res.getString(R.string.list_title));
- for (final StoredList list : app.getLists()) {
- menu.add(Menu.NONE, MENU_OPEN_LIST + list.id, Menu.NONE, list.getTitleAndCount());
- }
- return;
- }
-
- // standard context menu
- menu.setHeaderTitle(res.getString(R.string.menu_filter));
-
- //first add the most used types
- menu.add(1, 0, 0, CacheType.ALL.getL10n());
- menu.add(1, 1, 0, CacheType.TRADITIONAL.getL10n());
- menu.add(1, 2, 0, CacheType.MULTI.getL10n());
- menu.add(1, 3, 0, CacheType.MYSTERY.getL10n());
-
- // then add all other cache types sorted alphabetically
- List<String> sorted = new ArrayList<String>();
- for (CacheType ct : CacheType.values()) {
- if (ct == CacheType.ALL ||
- ct == CacheType.TRADITIONAL ||
- ct == CacheType.MULTI ||
- ct == CacheType.MYSTERY) {
- continue;
- }
- sorted.add(ct.getL10n());
- }
- Collections.sort(sorted);
- for (String choice : sorted) {
- menu.add(1, menu.size(), 0, choice);
- }
-
- // mark current filter as checked
- menu.setGroupCheckable(1, true, true);
- boolean foundItem = false;
- int itemCount = menu.size();
- String typeTitle = Settings.getCacheType().getL10n();
- for (int i = 0; i < itemCount; i++) {
- if (menu.getItem(i).getTitle().equals(typeTitle)) {
- menu.getItem(i).setChecked(true);
- foundItem = true;
- break;
- }
- }
- if (!foundItem) {
- menu.getItem(0).setChecked(true);
- }
- }
-
- @Override
- public boolean onContextItemSelected(final MenuItem item) {
- final int id = item.getItemId();
- if (id < 0) {
- return false;
- }
-
- if (id == 0) {
- Settings.setCacheType(CacheType.ALL);
- setFilterTitle();
- } else if (id > MENU_OPEN_LIST) {
- Settings.saveLastList(id - MENU_OPEN_LIST);
- cgeocaches.startActivityOffline(this);
- } else {
- final String itemTitle = item.getTitle().toString();
- CacheType cacheType = CacheType.ALL;
- for (final CacheType ct : CacheType.values()) {
- if (ct.getL10n().equalsIgnoreCase(itemTitle)) {
- cacheType = ct;
- break;
- }
- }
- Settings.setCacheType(cacheType);
- setFilterTitle();
- }
-
- return true;
- }
-
private void setFilterTitle() {
if (filterTitle == null) {
filterTitle = (TextView) findViewById(R.id.filter_button_title);
@@ -530,7 +375,22 @@ public class cgeo extends AbstractActivity {
cgeoFindByOffline(v);
}
});
- registerForContextMenu(findByOffline);
+ findByOffline.setOnLongClickListener(new View.OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ new StoredList.UserInterface(cgeo.this).promptForListSelection(R.string.list_title, new RunnableWithArgument<Integer>() {
+
+ @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);
@@ -552,11 +412,18 @@ public class cgeo extends AbstractActivity {
final View filter = findViewById(R.id.filter_button);
filter.setClickable(true);
- registerForContextMenu(filter);
filter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- openContextMenu(v);
+ selectGlobalTypeFilter();
+ }
+ });
+ filter.setOnLongClickListener(new View.OnLongClickListener() {
+
+ @Override
+ public boolean onLongClick(View v) {
+ selectGlobalTypeFilter();
+ return true;
}
});
@@ -567,12 +434,62 @@ public class cgeo extends AbstractActivity {
(new cleanDatabase()).start();
}
- private void updateCacheCounter() {
+ protected void selectGlobalTypeFilter() {
+ final List<CacheType> cacheTypes = new ArrayList<CacheType>();
+
+ //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<CacheType> sorted = new ArrayList<CacheType>();
+ sorted.addAll(Arrays.asList(CacheType.values()));
+ sorted.removeAll(cacheTypes);
+
+ Collections.sort(sorted, new Comparator<CacheType>() {
+
+ @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.isRestoreFile()) {
+ if (!cgData.isNewlyCreatedDatebase() || null == cgData.getRestoreFile()) {
return;
}
new AlertDialog.Builder(this)
@@ -585,7 +502,6 @@ public class cgeo extends AbstractActivity {
dialog.dismiss();
cgData.resetNewlyCreatedDatabase();
app.restoreDatabase(cgeo.this);
- updateCacheCounter();
}
})
.setNegativeButton(getString(android.R.string.no), new DialogInterface.OnClickListener() {
@@ -747,7 +663,7 @@ public class cgeo extends AbstractActivity {
countBubble.setVisibility(View.VISIBLE);
}
} catch (Exception e) {
- Log.w("cgeo.countBubbleHander: " + e.toString());
+ Log.w("cgeo.countBubbleHander", e);
}
}
};
@@ -759,7 +675,7 @@ public class cgeo extends AbstractActivity {
}
int checks = 0;
- while (!app.storageStatus()) {
+ while (!cgData.isInitialized()) {
try {
wait(500);
checks++;
@@ -772,7 +688,7 @@ public class cgeo extends AbstractActivity {
}
}
- countBubbleCnt = app.getAllStoredCachesCount(true, CacheType.ALL);
+ countBubbleCnt = cgData.getAllCachesCount();
countBubbleHandler.sendEmptyMessage(0);
}
@@ -797,7 +713,7 @@ public class cgeo extends AbstractActivity {
}
cleanupRunning = true;
- app.cleanDatabase(more);
+ cgData.clean(more);
cleanupRunning = false;
if (version > 0) {
diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java
index 9e221cd..f25701e 100644
--- a/main/src/cgeo/geocaching/cgeoapplication.java
+++ b/main/src/cgeo/geocaching/cgeoapplication.java
@@ -1,21 +1,10 @@
package cgeo.geocaching;
-import cgeo.geocaching.cgData.StorageLocation;
import cgeo.geocaching.activity.ActivityMixin;
-import cgeo.geocaching.enumerations.CacheType;
-import cgeo.geocaching.enumerations.LoadFlags;
-import cgeo.geocaching.enumerations.LoadFlags.LoadFlag;
-import cgeo.geocaching.enumerations.LoadFlags.RemoveFlag;
-import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
-import cgeo.geocaching.enumerations.LogType;
-import cgeo.geocaching.geopoint.Geopoint;
-import cgeo.geocaching.geopoint.Viewport;
import cgeo.geocaching.network.StatusUpdater;
import cgeo.geocaching.utils.IObserver;
import cgeo.geocaching.utils.Log;
-import org.apache.commons.lang3.StringUtils;
-
import android.app.Activity;
import android.app.Application;
import android.app.ProgressDialog;
@@ -23,27 +12,17 @@ import android.content.res.Resources;
import android.os.Handler;
import android.os.Message;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
public class cgeoapplication extends Application {
- final private cgData storage = new cgData();
private volatile GeoDataProvider geo;
private volatile DirectionProvider dir;
public boolean firstRun = true; // c:geo is just launched
public boolean showLoginToast = true; //login toast shown just once.
- private boolean databaseCleaned = false; // database was cleaned
private boolean liveMapHintShown = false; // livemap hint has been shown
final private StatusUpdater statusUpdater = new StatusUpdater();
- private static cgeoapplication instance = null;
+ private static cgeoapplication instance;
public cgeoapplication() {
instance = this;
@@ -61,29 +40,21 @@ public class cgeoapplication extends Application {
@Override
public void onLowMemory() {
Log.i("Cleaning applications cache.");
- removeAllFromCache();
- }
-
- public void removeAllFromCache() {
- storage.removeAllFromCache();
+ cgData.removeAllFromCache();
}
@Override
public void onTerminate() {
Log.d("Terminating c:geo…");
- storage.clean();
- storage.closeDb();
+ cgData.clean();
+ cgData.closeDb();
super.onTerminate();
}
- public String backupDatabase() {
- return storage.backupDatabase();
- }
-
/**
- * Move the database to/from external storage in a new thread,
+ * Move the database to/from external cgdata in a new thread,
* showing a progress window
*
* @param fromActivity
@@ -105,18 +76,13 @@ public class cgeoapplication extends Application {
@Override
public void run() {
- atomic.set(storage.moveDatabase());
+ atomic.set(cgData.moveDatabase());
handler.sendMessage(handler.obtainMessage());
}
};
moveThread.start();
}
-
- public static File isRestoreFile() {
- return cgData.isRestoreFile();
- }
-
/**
* restore the database in a new thread, showing a progress window
*
@@ -135,12 +101,15 @@ 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();
+ }
}
};
@Override
public void run() {
- atomic.set(storage.restoreDatabase());
+ atomic.set(cgData.restoreDatabase());
handler.sendMessage(handler.obtainMessage());
}
};
@@ -203,280 +172,6 @@ public class cgeoapplication extends Application {
return statusUpdater;
}
- public boolean storageStatus() {
- return storage.status();
- }
-
- public void cleanDatabase(boolean more) {
- if (databaseCleaned) {
- return;
- }
-
- storage.clean(more);
- databaseCleaned = true;
- }
-
- /** {@link cgData#isThere(String, String, boolean, boolean)} */
- public boolean isThere(String geocode, String guid, boolean detailed, boolean checkTime) {
- return storage.isThere(geocode, guid, detailed, checkTime);
- }
-
- /** {@link cgData#isOffline(String, String)} */
- public boolean isOffline(String geocode, String guid) {
- return storage.isOffline(geocode, guid);
- }
-
- /** {@link cgData#getGeocodeForGuid(String)} */
- public String getGeocode(String guid) {
- return storage.getGeocodeForGuid(guid);
- }
-
- /** {@link cgData#getCacheidForGeocode(String)} */
- public String getCacheid(String geocode) {
- return storage.getCacheidForGeocode(geocode);
- }
-
- public boolean hasUnsavedCaches(final SearchResult search) {
- if (search == null) {
- return false;
- }
-
- for (final String geocode : search.getGeocodes()) {
- if (!isOffline(geocode, null)) {
- return true;
- }
- }
- return false;
- }
-
- public cgTrackable getTrackableByGeocode(String geocode) {
- if (StringUtils.isBlank(geocode)) {
- return null;
- }
-
- return storage.loadTrackable(geocode);
- }
-
- /** {@link cgData#allDetailedThere()} */
- public String[] geocodesInCache() {
- return storage.allDetailedThere();
- }
-
- public Viewport getBounds(String geocode) {
- if (geocode == null) {
- return null;
- }
-
- return getBounds(Collections.singleton(geocode));
- }
-
- /** {@link cgData#getBounds(Set)} */
- public Viewport getBounds(final Set<String> geocodes) {
- return storage.getBounds(geocodes);
- }
-
- /** {@link cgData#loadBatchOfStoredGeocodes(boolean, Geopoint, CacheType, int)} */
- public SearchResult getBatchOfStoredCaches(final boolean detailedOnly, final Geopoint coords, final CacheType cacheType, final int listId) {
- final Set<String> geocodes = storage.loadBatchOfStoredGeocodes(detailedOnly, coords, cacheType, listId);
- return new SearchResult(geocodes, getAllStoredCachesCount(true, cacheType, listId));
- }
-
- /** {@link cgData#loadHistoryOfSearchedLocations()} */
- public List<Destination> getHistoryOfSearchedLocations() {
- return storage.loadHistoryOfSearchedLocations();
- }
-
- public SearchResult getHistoryOfCaches(final boolean detailedOnly, final CacheType cacheType) {
- final Set<String> geocodes = storage.loadBatchOfHistoricGeocodes(detailedOnly, cacheType);
- return new SearchResult(geocodes, getAllHistoricCachesCount());
- }
-
- /** {@link cgData#loadCachedInViewport(Viewport, CacheType)} */
- public SearchResult getCachedInViewport(final Viewport viewport, final CacheType cacheType) {
- final Set<String> geocodes = storage.loadCachedInViewport(viewport, cacheType);
- return new SearchResult(geocodes);
- }
-
- /** {@link cgData#loadStoredInViewport(Viewport, CacheType)} */
- public SearchResult getStoredInViewport(final Viewport viewport, final CacheType cacheType) {
- final Set<String> geocodes = storage.loadStoredInViewport(viewport, cacheType);
- return new SearchResult(geocodes);
- }
-
- /** {@link cgData#getAllStoredCachesCount(boolean, CacheType, int)} */
- public int getAllStoredCachesCount(final boolean detailedOnly, final CacheType cacheType) {
- return storage.getAllStoredCachesCount(detailedOnly, cacheType, 0);
- }
-
- /** {@link cgData#getAllStoredCachesCount(boolean, CacheType, int)} */
- public int getAllStoredCachesCount(final boolean detailedOnly, final CacheType cacheType, final Integer list) {
- return storage.getAllStoredCachesCount(detailedOnly, cacheType, list);
- }
-
- /** {@link cgData#getAllHistoricCachesCount()} */
- public int getAllHistoricCachesCount() {
- return storage.getAllHistoricCachesCount();
- }
-
- /** {@link cgData#moveToList(List, int)} */
- public void markStored(List<cgCache> caches, int listId) {
- storage.moveToList(caches, listId);
- }
-
- /** {@link cgData#moveToList(List, int)} */
- public void markDropped(List<cgCache> caches) {
- storage.moveToList(caches, StoredList.TEMPORARY_LIST_ID);
- }
-
- /** {@link cgData#clearSearchedDestinations()} */
- public boolean clearSearchedDestinations() {
- return storage.clearSearchedDestinations();
- }
-
- /** {@link cgData#saveSearchedDestination(Destination)} */
- public void saveSearchedDestination(Destination destination) {
- storage.saveSearchedDestination(destination);
- }
-
- /** {@link cgData#saveWaypoints(cgCache)} */
- public boolean saveWaypoints(final cgCache cache) {
- return storage.saveWaypoints(cache);
- }
-
- public boolean saveWaypoint(int id, String geocode, cgWaypoint waypoint) {
- if (storage.saveWaypoint(id, geocode, waypoint)) {
- this.removeCache(geocode, EnumSet.of(RemoveFlag.REMOVE_CACHE));
- return true;
- }
- return false;
- }
-
- /** {@link cgData#deleteWaypoint(int)} */
- public boolean deleteWaypoint(int id) {
- return storage.deleteWaypoint(id);
- }
-
- public boolean saveTrackable(cgTrackable trackable) {
- return storage.saveTrackable(trackable);
- }
-
- /** {@link cgData#loadLogCounts(String)} */
- public Map<LogType, Integer> loadLogCounts(String geocode) {
- return storage.loadLogCounts(geocode);
- }
-
- /** {@link cgData#loadWaypoint(int)} */
- public cgWaypoint loadWaypoint(int id) {
- return storage.loadWaypoint(id);
- }
-
- /** {@link cgData#saveLogOffline(String, Date, LogType, String)} */
- public boolean saveLogOffline(String geocode, Date date, LogType logtype, String log) {
- return storage.saveLogOffline(geocode, date, logtype, log);
- }
-
- /** {@link cgData#loadLogOffline(String)} */
- public LogEntry loadLogOffline(String geocode) {
- return storage.loadLogOffline(geocode);
- }
-
- /** {@link cgData#clearLogOffline(String)} */
- public void clearLogOffline(String geocode) {
- storage.clearLogOffline(geocode);
- }
-
- /** {@link cgData#setVisitDate(List, long)} */
- public void saveVisitDate(String geocode) {
- storage.setVisitDate(Collections.singletonList(geocode), System.currentTimeMillis());
- }
-
- /** {@link cgData#setVisitDate(List, long)} */
- public void clearVisitDate(List<cgCache> caches) {
- ArrayList<String> geocodes = new ArrayList<String>(caches.size());
- for (cgCache cache : caches) {
- geocodes.add(cache.getGeocode());
- }
- storage.setVisitDate(geocodes, 0);
- }
-
- /** {@link cgData#getLists(Resources)} */
- public List<StoredList> getLists() {
- return storage.getLists(getResources());
- }
-
- /** {@link cgData#getList(int, Resources)} */
- public StoredList getList(int id) {
- return storage.getList(id, getResources());
- }
-
- /** {@link cgData#createList(String)} */
- public int createList(String title) {
- return storage.createList(title);
- }
-
- /** {@link cgData#renameList(int, String)} */
- public int renameList(final int listId, final String title) {
- return storage.renameList(listId, title);
- }
-
- /** {@link cgData#removeList(int)} */
- public boolean removeList(int id) {
- return storage.removeList(id);
- }
-
- /** {@link cgData#removeSearchedDestination(Destination)} */
- public boolean removeSearchedDestinations(Destination destination) {
- return storage.removeSearchedDestination(destination);
- }
-
- /** {@link cgData#moveToList(List, int)} */
- public void moveToList(List<cgCache> caches, int listId) {
- storage.moveToList(caches, listId);
- }
-
- /** {@link cgData#getCacheDescription(String)} */
- public String getCacheDescription(String geocode) {
- return storage.getCacheDescription(geocode);
- }
-
- /** {@link cgData#loadCaches} */
- public cgCache loadCache(final String geocode, final EnumSet<LoadFlag> loadFlags) {
- return storage.loadCache(geocode, loadFlags);
- }
-
- /** {@link cgData#loadCaches} */
- public Set<cgCache> loadCaches(final Set<String> geocodes, final EnumSet<LoadFlag> loadFlags) {
- return storage.loadCaches(geocodes, loadFlags);
- }
-
- /**
- * Update a cache in the DB or in the CacheCace depending on it's storage location
- *
- * {@link cgData#saveCache}
- */
- public boolean updateCache(cgCache cache) {
- return saveCache(cache, cache.getStorageLocation().contains(StorageLocation.DATABASE) ? LoadFlags.SAVE_ALL : EnumSet.of(SaveFlag.SAVE_CACHE));
- }
-
- /** {@link cgData#saveCache} */
- public boolean saveCache(cgCache cache, EnumSet<LoadFlags.SaveFlag> saveFlags) {
- return storage.saveCache(cache, saveFlags);
- }
-
- /** {@link cgData#removeCache} */
- public void removeCache(String geocode, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
- storage.removeCache(geocode, removeFlags);
- }
-
- /** {@link cgData#removeCaches} */
- public void removeCaches(final Set<String> geocodes, EnumSet<LoadFlags.RemoveFlag> removeFlags) {
- storage.removeCaches(geocodes, removeFlags);
- }
-
- public Set<cgWaypoint> getWaypointsInViewport(final Viewport viewport, boolean excludeMine, boolean excludeDisabled, CacheType type) {
- return storage.loadWaypoints(viewport, excludeMine, excludeDisabled, type);
- }
-
public boolean isLiveMapHintShown() {
return liveMapHintShown;
}
@@ -485,20 +180,4 @@ public class cgeoapplication extends Application {
liveMapHintShown = true;
}
- public String[] getTrackableCodes() {
- return storage.getTrackableCodes();
- }
-
- public List<LogEntry> loadLogs(final String geocode) {
- return storage.loadLogs(geocode);
- }
-
- public List<String> loadAttributes(final String geocode) {
- return storage.loadAttributes(geocode);
- }
-
- public List<cgWaypoint> loadWaypoints(final String geocode) {
- return storage.loadWaypoints(geocode);
- }
-
}
diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java
index 688af99..cf10fb5 100644
--- a/main/src/cgeo/geocaching/cgeocaches.java
+++ b/main/src/cgeo/geocaching/cgeocaches.java
@@ -3,9 +3,12 @@ package cgeo.geocaching;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.AbstractListActivity;
import cgeo.geocaching.activity.ActivityMixin;
+import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.apps.cachelist.CacheListAppFactory;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.gc.AbstractSearchThread;
import cgeo.geocaching.connector.gc.GCParser;
import cgeo.geocaching.connector.gc.SearchHandler;
@@ -28,6 +31,8 @@ import cgeo.geocaching.sorting.EventDateComparator;
import cgeo.geocaching.sorting.VisitComparator;
import cgeo.geocaching.ui.CacheListAdapter;
import cgeo.geocaching.ui.LoggingUI;
+import cgeo.geocaching.ui.WeakReferenceHandler;
+import cgeo.geocaching.utils.DateUtils;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.RunnableWithArgument;
@@ -60,18 +65,13 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-public class cgeocaches extends AbstractListActivity {
+public class cgeocaches extends AbstractListActivity implements FilteredActivity {
- private static final String EXTRAS_USERNAME = "username";
- private static final String EXTRAS_ADDRESS = "address";
- private static final String EXTRAS_SEARCH = "search";
- private static final String EXTRAS_KEYWORD = "keyword";
- private static final String EXTRAS_LIST_TYPE = "type";
- private static final String EXTRAS_COORDS = "coords";
private static final int MAX_LIST_ITEMS = 1000;
private static final int MENU_REFRESH_STORED = 2;
private static final int MENU_CACHE_DETAILS = 4;
@@ -98,6 +98,7 @@ public class cgeocaches extends AbstractListActivity {
private static final int MENU_NAVIGATION = 69;
private static final int MENU_STORE_CACHE = 73;
private static final int MENU_FILTER = 74;
+ private static final int MENU_DELETE_EVENTS = 75;
private static final int MSG_DONE = -1;
private static final int MSG_RESTART_GEO_AND_DIR = -2;
@@ -107,7 +108,7 @@ public class cgeocaches extends AbstractListActivity {
private Geopoint coords = null;
private SearchResult search = null;
/** The list of shown caches shared with Adapter. Don't manipulate outside of main thread only with Handler */
- private final List<cgCache> cacheList = new ArrayList<cgCache>();
+ private final List<Geocache> cacheList = new ArrayList<Geocache>();
private CacheListAdapter adapter = null;
private LayoutInflater inflater = null;
private View listFooter = null;
@@ -124,11 +125,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void updateGeoData(final IGeoData geo) {
- if (adapter == null) {
- return;
- }
-
- if (geo.getCoords() != null) {
+ if (geo.getCoords() != null) {
adapter.setActualCoordinates(geo.getCoords());
}
if (!Settings.isUseCompass() || geo.getSpeed() > 5) { // use GPS when speed is higher than 18 km/h
@@ -138,7 +135,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void updateDirection(final float direction) {
- if (adapter == null || !Settings.isLiveList()) {
+ if (!Settings.isLiveList()) {
return;
}
@@ -156,57 +153,42 @@ public class cgeocaches extends AbstractListActivity {
*/
private MenuItem navigationMenu;
- private Handler loadCachesHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- try {
- setAdapter();
-
- updateTitle();
-
- setDateComparatorForEventList();
+ public void handleCachesLoaded() {
+ try {
+ setAdapter();
- showFooterMoreCaches();
+ updateTitle();
- if (search != null && search.getError() == StatusCode.UNAPPROVED_LICENSE) {
- AlertDialog.Builder dialog = new AlertDialog.Builder(cgeocaches.this);
- dialog.setTitle(res.getString(R.string.license));
- dialog.setMessage(res.getString(R.string.err_license));
- dialog.setCancelable(true);
- dialog.setNegativeButton(res.getString(R.string.license_dismiss), new DialogInterface.OnClickListener() {
+ setDateComparatorForEventList();
- @Override
- public void onClick(DialogInterface dialog, int id) {
- Cookies.clearCookies();
- dialog.cancel();
- }
- });
- dialog.setPositiveButton(res.getString(R.string.license_show), new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog, int id) {
- Cookies.clearCookies();
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/software/agreement.aspx?ID=0")));
- }
- });
+ showFooterMoreCaches();
- AlertDialog alert = dialog.create();
- alert.show();
- } else if (search != null && search.getError() != null) {
- showToast(res.getString(R.string.err_download_fail) + ' ' + search.getError().getErrorString(res) + '.');
+ if (search != null && search.getError() == StatusCode.UNAPPROVED_LICENSE) {
+ AlertDialog.Builder dialog = new AlertDialog.Builder(this);
+ dialog.setTitle(res.getString(R.string.license));
+ dialog.setMessage(res.getString(R.string.err_license));
+ dialog.setCancelable(true);
+ dialog.setNegativeButton(res.getString(R.string.license_dismiss), new DialogInterface.OnClickListener() {
- hideLoading();
- showProgress(false);
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ Cookies.clearCookies();
+ dialog.cancel();
+ }
+ });
+ dialog.setPositiveButton(res.getString(R.string.license_show), new DialogInterface.OnClickListener() {
- finish();
- return;
- }
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ Cookies.clearCookies();
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/software/agreement.aspx?ID=0")));
+ }
+ });
- setAdapterCurrentCoordinates(false);
- } catch (Exception e) {
- showToast(res.getString(R.string.err_detail_cache_find_any));
- Log.e("cgeocaches.loadCachesHandler: " + e.toString());
+ AlertDialog alert = dialog.create();
+ alert.show();
+ } else if (search != null && search.getError() != null) {
+ showToast(res.getString(R.string.err_download_fail) + ' ' + search.getError().getErrorString(res) + '.');
hideLoading();
showProgress(false);
@@ -215,29 +197,52 @@ public class cgeocaches extends AbstractListActivity {
return;
}
- try {
- hideLoading();
- showProgress(false);
- } catch (Exception e2) {
- Log.e("cgeocaches.loadCachesHandler.2: " + e2.toString());
- }
+ setAdapterCurrentCoordinates(false);
+ } catch (Exception e) {
+ showToast(res.getString(R.string.err_detail_cache_find_any));
+ Log.e("cgeocaches.loadCachesHandler", e);
- if (adapter != null) {
- adapter.setSelectMode(false);
+ hideLoading();
+ showProgress(false);
+
+ finish();
+ return;
+ }
+
+ try {
+ hideLoading();
+ showProgress(false);
+ } catch (Exception e2) {
+ Log.e("cgeocaches.loadCachesHandler.2", e2);
+ }
+
+ adapter.setSelectMode(false);
+ }
+
+ private Handler loadCachesHandler = new LoadCachesHandler(this);
+
+ private static class LoadCachesHandler extends WeakReferenceHandler<cgeocaches> {
+
+ protected LoadCachesHandler(cgeocaches activity) {
+ super(activity);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ final cgeocaches activity = getActivity();
+ if (activity == null) {
+ return;
}
+ activity.handleCachesLoaded();
}
- };
+ }
+
private Handler loadNextPageHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
try {
- if (search != null) {
- replaceCacheListFromSearch();
- if (adapter != null) {
- adapter.reFilter();
- }
- }
+ replaceCacheListFromSearch();
setAdapter();
updateTitle();
@@ -258,33 +263,41 @@ public class cgeocaches extends AbstractListActivity {
setAdapterCurrentCoordinates(false);
} catch (Exception e) {
showToast(res.getString(R.string.err_detail_cache_find_next));
- Log.e("cgeocaches.loadNextPageHandler: " + e.toString());
+ Log.e("cgeocaches.loadNextPageHandler", e);
}
hideLoading();
showProgress(false);
- if (adapter != null) {
- adapter.setSelectMode(false);
- }
+ adapter.setSelectMode(false);
}
};
- private Set<cgCache> cachesFromSearchResult;
/**
- * Loads the caches and fills the cachelist
+ * Loads the caches and fills the {@link #cacheList} according to {@link #search} content.
+ *
+ * If {@link #search} is <code>null</code>, this does nothing.
*/
private void replaceCacheListFromSearch() {
- if (search!=null) {
- cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ if (search != null) {
+ final Set<Geocache> cachesFromSearchResult = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ cacheList.clear();
+ cacheList.addAll(cachesFromSearchResult);
+ adapter.reFilter();
+ updateTitle();
+ showFooterMoreCaches();
+ }
+ });
}
- refreshCacheListHandler.sendEmptyMessage(0);
}
protected void updateTitle() {
ArrayList<Integer> numbers = new ArrayList<Integer>();
- if (adapter != null && adapter.isFiltered()) {
+ if (adapter.isFiltered()) {
numbers.add(adapter.getCount());
}
if (search != null) {
@@ -307,9 +320,7 @@ public class cgeocaches extends AbstractListActivity {
if (msg.what > -1) {
cacheList.get(msg.what).setStatusChecked(false);
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
+ adapter.notifyDataSetChanged();
int secondsElapsed = (int) ((System.currentTimeMillis() - detailProgressTime) / 1000);
int minutesRemaining = ((detailTotal - detailProgress) * secondsElapsed / ((detailProgress > 0) ? detailProgress : 1) / 60);
@@ -328,7 +339,7 @@ public class cgeocaches extends AbstractListActivity {
startGeoAndDir();
} else {
if (search != null) {
- final Set<cgCache> cacheListTmp = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ final Set<Geocache> cacheListTmp = search.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
if (CollectionUtils.isNotEmpty(cacheListTmp)) {
cacheList.clear();
cacheList.addAll(cacheListTmp);
@@ -353,9 +364,7 @@ public class cgeocaches extends AbstractListActivity {
public void handleMessage(Message msg) {
setAdapter();
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
+ adapter.notifyDataSetChanged();
if (msg.what == 0) { //no caches
progress.setMessage(res.getString(R.string.web_import_waiting));
@@ -377,9 +386,7 @@ public class cgeocaches extends AbstractListActivity {
threadWeb.kill();
}
} else {
- if (adapter != null) {
- adapter.setSelectMode(false);
- }
+ adapter.setSelectMode(false);
replaceCacheListFromSearch();
@@ -392,9 +399,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void handleMessage(Message msg) {
if (msg.what != MSG_CANCEL) {
- if (adapter != null) {
- adapter.setSelectMode(false);
- }
+ adapter.setSelectMode(false);
refreshCurrentList();
@@ -413,9 +418,7 @@ public class cgeocaches extends AbstractListActivity {
if (msg.what > -1) {
progress.setProgress(detailProgress);
} else {
- if (adapter != null) {
- adapter.setSelectMode(false);
- }
+ adapter.setSelectMode(false);
// reload history list
(new LoadByHistoryThread()).start();
@@ -446,9 +449,9 @@ public class cgeocaches extends AbstractListActivity {
// get parameters
Bundle extras = getIntent().getExtras();
if (extras != null) {
- Object typeObject = extras.get(EXTRAS_LIST_TYPE);
+ Object typeObject = extras.get(Intents.EXTRA_LIST_TYPE);
type = (typeObject instanceof CacheListType) ? (CacheListType) typeObject : CacheListType.OFFLINE;
- coords = (Geopoint) extras.getParcelable(EXTRAS_COORDS);
+ coords = (Geopoint) extras.getParcelable(Intents.EXTRAS_COORDS);
}
else {
extras = new Bundle();
@@ -471,7 +474,7 @@ public class cgeocaches extends AbstractListActivity {
Thread threadPure;
AbstractSearchThread thread;
- final String username = extras.getString(EXTRAS_USERNAME);
+ final String username = extras.getString(Intents.EXTRA_USERNAME);
switch (type) {
case OFFLINE:
listId = Settings.getLastList();
@@ -479,7 +482,7 @@ public class cgeocaches extends AbstractListActivity {
listId = StoredList.STANDARD_LIST_ID;
title = res.getString(R.string.stored_caches_button);
} else {
- final StoredList list = app.getList(listId);
+ final StoredList list = cgData.getList(listId);
// list.id may be different if listId was not valid
listId = list.id;
title = list.title;
@@ -523,7 +526,7 @@ public class cgeocaches extends AbstractListActivity {
thread.start();
break;
case KEYWORD:
- final String keyword = extras.getString(EXTRAS_KEYWORD);
+ final String keyword = extras.getString(Intents.EXTRA_KEYWORD);
title = keyword;
setTitle(title);
showProgress(true);
@@ -534,7 +537,7 @@ public class cgeocaches extends AbstractListActivity {
thread.start();
break;
case ADDRESS:
- final String address = extras.getString(EXTRAS_ADDRESS);
+ final String address = extras.getString(Intents.EXTRA_ADDRESS);
if (StringUtils.isNotBlank(address)) {
title = address;
} else {
@@ -577,7 +580,7 @@ public class cgeocaches extends AbstractListActivity {
title = res.getString(R.string.map_map);
setTitle(title);
showProgress(true);
- search = (SearchResult) extras.get(EXTRAS_SEARCH);
+ search = (SearchResult) extras.get(Intents.EXTRA_SEARCH);
replaceCacheListFromSearch();
loadCachesHandler.sendMessage(Message.obtain());
break;
@@ -630,10 +633,8 @@ public class cgeocaches extends AbstractListActivity {
startGeoAndDir();
- if (adapter != null) {
- adapter.setSelectMode(false);
- setAdapterCurrentCoordinates(true);
- }
+ adapter.setSelectMode(false);
+ setAdapterCurrentCoordinates(true);
if (loadCachesHandler != null && search != null) {
replaceCacheListFromSearch();
@@ -642,7 +643,7 @@ public class cgeocaches extends AbstractListActivity {
// refresh standard list if it has changed (new caches downloaded)
if (type == CacheListType.OFFLINE && listId >= StoredList.STANDARD_LIST_ID && search != null) {
- SearchResult newSearch = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId);
+ SearchResult newSearch = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId);
if (newSearch != null && newSearch.getTotal() != search.getTotal()) {
refreshCurrentList();
}
@@ -660,15 +661,6 @@ public class cgeocaches extends AbstractListActivity {
}
@Override
- public void onDestroy() {
- if (adapter != null) {
- adapter = null;
- }
-
- super.onDestroy();
- }
-
- @Override
public void onPause() {
removeGeoAndDir();
@@ -691,6 +683,7 @@ public class cgeocaches extends AbstractListActivity {
subMenu.add(0, MENU_DROP_CACHES_AND_LIST, 0, res.getString(R.string.caches_drop_all_and_list));
subMenu.add(0, MENU_REFRESH_STORED, 0, res.getString(R.string.cache_offline_refresh)); // download details for all caches
subMenu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list));
+ subMenu.add(0, MENU_DELETE_EVENTS, 0, res.getString(R.string.caches_delete_events));
//TODO: add submenu/AlertDialog and use R.string.gpx_import_title
subMenu.add(0, MENU_IMPORT_GPX, 0, res.getString(R.string.gpx_import_title));
@@ -733,7 +726,7 @@ public class cgeocaches extends AbstractListActivity {
super.onPrepareOptionsMenu(menu);
try {
- if (adapter != null && adapter.isSelectMode()) {
+ if (adapter.isSelectMode()) {
menu.findItem(MENU_SWITCH_SELECT_MODE).setTitle(res.getString(R.string.caches_select_mode_exit))
.setIcon(R.drawable.ic_menu_clear_playlist);
menu.findItem(MENU_INVERT_SELECTION).setVisible(true);
@@ -753,6 +746,7 @@ public class cgeocaches extends AbstractListActivity {
setVisible(menu, MENU_REFRESH_STORED, !isEmpty && (isConcrete || type != CacheListType.OFFLINE));
setVisible(menu, MENU_DROP_CACHES, !isEmpty);
setVisible(menu, MENU_DROP_CACHES_AND_LIST, isConcrete && !isEmpty);
+ setVisible(menu, MENU_DELETE_EVENTS, isConcrete && !isEmpty && containsEvents());
setVisible(menu, MENU_MOVE_TO_LIST, !isEmpty);
setVisible(menu, MENU_EXPORT, !isEmpty);
setVisible(menu, MENU_REMOVE_FROM_HISTORY, !isEmpty);
@@ -784,14 +778,14 @@ public class cgeocaches extends AbstractListActivity {
item.setVisible(isNonDefaultList);
}
- final boolean multipleLists = app.getLists().size() >= 2;
+ final boolean multipleLists = cgData.getLists().size() >= 2;
item = menu.findItem(MENU_SWITCH_LIST);
if (item != null) {
item.setVisible(multipleLists);
}
item = menu.findItem(MENU_MOVE_TO_LIST);
if (item != null) {
- item.setVisible(multipleLists && !isEmpty);
+ item.setVisible(!isEmpty);
}
setMenuItemLabel(menu, MENU_REMOVE_FROM_HISTORY, R.string.cache_remove_from_history, R.string.cache_clear_history);
@@ -803,6 +797,15 @@ public class cgeocaches extends AbstractListActivity {
return true;
}
+ private boolean containsEvents() {
+ for (Geocache cache : adapter.getCheckedOrAllCaches()) {
+ if (cache.isEventCache()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void setMenuItemLabel(final Menu menu, final int menuId, final int resIdSelection, final int resId) {
final MenuItem menuItem = menu.findItem(menuId);
if (menuItem == null) {
@@ -821,13 +824,11 @@ public class cgeocaches extends AbstractListActivity {
int itemId = item.getItemId();
switch (itemId) {
case MENU_SWITCH_SELECT_MODE:
- if (adapter != null) {
- adapter.switchSelectMode();
- }
+ adapter.switchSelectMode();
invalidateOptionsMenuCompatible();
return true;
case MENU_REFRESH_STORED:
- refreshStored();
+ refreshStored(adapter.getCheckedOrAllCaches());
invalidateOptionsMenuCompatible();
return true;
case MENU_DROP_CACHES:
@@ -854,9 +855,7 @@ public class cgeocaches extends AbstractListActivity {
renameList();
return false;
case MENU_INVERT_SELECTION:
- if (adapter != null) {
- adapter.invertSelection();
- }
+ adapter.invertSelection();
invalidateOptionsMenuCompatible();
return false;
case MENU_SWITCH_LIST:
@@ -864,20 +863,7 @@ public class cgeocaches extends AbstractListActivity {
invalidateOptionsMenuCompatible();
return false;
case MENU_FILTER:
- new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() {
- @Override
- public void run(IFilter selectedFilter) {
- if (selectedFilter != null) {
- setFilter(selectedFilter);
- }
- else {
- // clear filter
- if (adapter != null) {
- setFilter(null);
- }
- }
- }
- });
+ showFilterMenu(null);
return true;
case MENU_SORT:
new ComparatorUserInterface(this).selectComparator(adapter.getCacheComparator(), new RunnableWithArgument<CacheComparator>() {
@@ -901,36 +887,67 @@ public class cgeocaches extends AbstractListActivity {
moveCachesToOtherList();
invalidateOptionsMenuCompatible();
return true;
+ case MENU_DELETE_EVENTS:
+ deletePastEvents();
+ invalidateOptionsMenuCompatible();
+ return true;
+ default:
+ return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search);
}
+ }
- return CacheListAppFactory.onMenuItemSelected(item, cacheList, this, search);
+ public void deletePastEvents() {
+ progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL));
+ final List<Geocache> deletion = new ArrayList<Geocache>();
+ for (Geocache cache : adapter.getCheckedOrAllCaches()) {
+ if (cache.isEventCache()) {
+ final Date eventDate = cache.getHiddenDate();
+ if (DateUtils.daysSince(eventDate.getTime()) > 0) {
+ deletion.add(cache);
+ }
+ }
+ }
+ new DropDetailsThread(dropDetailsHandler, deletion).start();
+ }
+
+ /**
+ * called from the filter bar view
+ */
+ @Override
+ public void showFilterMenu(final View view) {
+ new FilterUserInterface(this).selectFilter(new RunnableWithArgument<IFilter>() {
+ @Override
+ public void run(IFilter selectedFilter) {
+ if (selectedFilter != null) {
+ setFilter(selectedFilter);
+ }
+ else {
+ // clear filter
+ setFilter(null);
+ }
+ }
+ });
}
private void setComparator(final CacheComparator comparator) {
- if (adapter != null) {
- adapter.setComparator(comparator);
- }
+ adapter.setComparator(comparator);
}
@Override
public void onCreateContextMenu(final ContextMenu menu, final View view, final ContextMenu.ContextMenuInfo info) {
super.onCreateContextMenu(menu, view, info);
- if (adapter == null) {
- return;
- }
-
AdapterContextMenuInfo adapterInfo = null;
try {
adapterInfo = (AdapterContextMenuInfo) info;
} catch (Exception e) {
- Log.w("cgeocaches.onCreateContextMenu: " + e.toString());
+ Log.w("cgeocaches.onCreateContextMenu", e);
}
if (adapterInfo == null || adapterInfo.position >= adapter.getCount()) {
return;
}
- final cgCache cache = adapter.getItem(adapterInfo.position);
+ final Geocache cache = adapter.getItem(adapterInfo.position);
menu.setHeaderTitle(StringUtils.defaultIfBlank(cache.getName(), cache.getGeocode()));
@@ -944,10 +961,7 @@ public class cgeocaches extends AbstractListActivity {
}
if (cache.isOffline()) {
menu.add(0, MENU_DROP_CACHE, 0, res.getString(R.string.cache_offline_drop));
- final List<StoredList> cacheLists = app.getLists();
- if (cacheLists.size() > 1) {
- menu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list));
- }
+ menu.add(0, MENU_MOVE_TO_LIST, 0, res.getString(R.string.cache_menu_move_list));
menu.add(0, MENU_EXPORT, 0, res.getString(R.string.export));
}
else {
@@ -960,12 +974,12 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run(Integer newListId) {
- app.moveToList(adapter.getCheckedOrAllCaches(), newListId);
+ cgData.moveToList(adapter.getCheckedOrAllCaches(), newListId);
adapter.setSelectMode(false);
refreshCurrentList();
}
- }, true);
+ }, true, listId);
}
@Override
@@ -983,10 +997,10 @@ public class cgeocaches extends AbstractListActivity {
try {
adapterInfo = (AdapterContextMenuInfo) info;
} catch (Exception e) {
- Log.w("cgeocaches.onContextItemSelected: " + e.toString());
+ Log.w("cgeocaches.onContextItemSelected", e);
}
- final cgCache cache = adapterInfo != null ? getCacheFromAdapter(adapterInfo) : null;
+ final Geocache cache = adapterInfo != null ? getCacheFromAdapter(adapterInfo) : null;
// just in case the list got resorted while we are executing this code
if (cache == null) {
@@ -1003,8 +1017,8 @@ public class cgeocaches extends AbstractListActivity {
break;
case MENU_CACHE_DETAILS:
final Intent cachesIntent = new Intent(this, CacheDetailActivity.class);
- cachesIntent.putExtra("geocode", cache.getGeocode().toUpperCase());
- cachesIntent.putExtra("name", cache.getName());
+ cachesIntent.putExtra(Intents.EXTRA_GEOCODE, cache.getGeocode());
+ cachesIntent.putExtra(Intents.EXTRA_NAME, cache.getName());
startActivity(cachesIntent);
break;
case MENU_DROP_CACHE:
@@ -1021,15 +1035,14 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run(Integer newListId) {
- app.moveToList(Collections.singletonList(cache), newListId);
+ cgData.moveToList(Collections.singletonList(cache), newListId);
adapter.setSelectMode(false);
refreshCurrentList();
}
- }, true);
+ }, true, listId);
break;
case MENU_STORE_CACHE:
- //FIXME: this must use the same handler like in the CacheDetailActivity. Will be done by moving the handler into the store method.
- cache.store(null);
+ refreshStored(Collections.singletonList(cache));
break;
case MENU_EXPORT:
ExportFactory.showExportMenu(Collections.singletonList(cache), this);
@@ -1052,8 +1065,8 @@ public class cgeocaches extends AbstractListActivity {
* an adapterInfo
* @return the pointed cache
*/
- private cgCache getCacheFromAdapter(final AdapterContextMenuInfo adapterInfo) {
- final cgCache cache = adapter.getItem(adapterInfo.position);
+ private Geocache getCacheFromAdapter(final AdapterContextMenuInfo adapterInfo) {
+ final Geocache cache = adapter.getItem(adapterInfo.position);
if (cache.getGeocode().equalsIgnoreCase(contextMenuGeocode)) {
return cache;
}
@@ -1062,24 +1075,19 @@ public class cgeocaches extends AbstractListActivity {
}
private boolean setFilter(IFilter filter) {
- if (adapter != null) {
- adapter.setFilter(filter);
- prepareFilterBar();
- updateTitle();
- invalidateOptionsMenuCompatible();
- return true;
- }
- return false;
+ adapter.setFilter(filter);
+ prepareFilterBar();
+ updateTitle();
+ invalidateOptionsMenuCompatible();
+ return true;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
- if (adapter != null) {
- if (adapter.isSelectMode()) {
- adapter.setSelectMode(false);
- return true;
- }
+ if (adapter.isSelectMode()) {
+ adapter.setSelectMode(false);
+ return true;
}
}
return super.onKeyDown(keyCode, event);
@@ -1166,8 +1174,27 @@ public class cgeocaches extends AbstractListActivity {
refreshCurrentList();
}
- public void refreshStored() {
- detailTotal = adapter.getCheckedOrAllCount();
+ public void refreshStored(final List<Geocache> caches) {
+ detailTotal = caches.size();
+ if (detailTotal == 0) {
+ return;
+ }
+
+ if (Settings.getChooseList() && type != CacheListType.OFFLINE) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(this).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ refreshStored(caches, selectedListId);
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ refreshStored(caches, this.listId);
+ }
+ }
+
+ private void refreshStored(final List<Geocache> caches, final int storeListId) {
detailProgress = 0;
showProgress(false);
@@ -1185,7 +1212,7 @@ public class cgeocaches extends AbstractListActivity {
detailProgressTime = System.currentTimeMillis();
- threadDetails = new LoadDetailsThread(loadDetailsHandler, listId);
+ threadDetails = new LoadDetailsThread(loadDetailsHandler, caches, storeListId);
threadDetails.start();
}
@@ -1239,7 +1266,7 @@ public class cgeocaches extends AbstractListActivity {
dialog.setCancelable(true);
dialog.setTitle(res.getString(R.string.caches_drop_stored));
- if (adapter != null && adapter.getCheckedCount() > 0) {
+ if (adapter.getCheckedCount() > 0) {
dialog.setMessage(res.getString(R.string.caches_drop_selected_ask));
} else {
dialog.setMessage(res.getString(R.string.caches_drop_all_ask));
@@ -1269,7 +1296,7 @@ public class cgeocaches extends AbstractListActivity {
public void dropSelected() {
progress.show(this, null, res.getString(R.string.caches_drop_progress), true, dropDetailsHandler.obtainMessage(MSG_CANCEL));
- new DropDetailsThread(dropDetailsHandler).start();
+ new DropDetailsThread(dropDetailsHandler, adapter.getCheckedOrAllCaches()).start();
}
private class LoadByOfflineThread extends Thread {
@@ -1283,7 +1310,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run() {
- search = cgeoapplication.getInstance().getBatchOfStoredCaches(true, coords, Settings.getCacheType(), listId);
+ search = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId);
replaceCacheListFromSearch();
loadCachesHandler.sendMessage(Message.obtain());
}
@@ -1292,7 +1319,7 @@ public class cgeocaches extends AbstractListActivity {
private class LoadByHistoryThread extends Thread {
@Override
public void run() {
- search = cgeoapplication.getInstance().getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
+ search = cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL);
replaceCacheListFromSearch();
loadCachesHandler.sendMessage(Message.obtain());
}
@@ -1319,7 +1346,17 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void runSearch() {
+
search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha());
+
+ for (ISearchByCenter centerConn : ConnectorFactory.getSearchByCenterConnectors()) {
+ if (centerConn.isActivated()) {
+ SearchResult temp = centerConn.searchByCenter(coords);
+ if (temp != null) {
+ search.addGeocodes(temp.getGeocodes());
+ }
+ }
+ }
replaceCacheListFromSearch();
}
}
@@ -1394,11 +1431,11 @@ public class cgeocaches extends AbstractListActivity {
final private int listIdLD;
private volatile boolean needToStop = false;
private long last = 0L;
- final private List<cgCache> selected;
+ final private List<Geocache> caches;
- public LoadDetailsThread(Handler handlerIn, int listId) {
+ public LoadDetailsThread(Handler handlerIn, List<Geocache> caches, int listId) {
handler = handlerIn;
- selected = adapter.getCheckedOrAllCaches();
+ this.caches = caches;
// in case of online lists, set the list id to the standard list
this.listIdLD = Math.max(listId, StoredList.STANDARD_LIST_ID);
@@ -1412,8 +1449,8 @@ public class cgeocaches extends AbstractListActivity {
public void run() {
removeGeoAndDir();
- final List<cgCache> cachesWithStaticMaps = new ArrayList<cgCache>(selected.size());
- for (cgCache cache : selected) {
+ final List<Geocache> cachesWithStaticMaps = new ArrayList<Geocache>(this.caches.size());
+ for (Geocache cache : this.caches) {
if (Settings.isStoreOfflineMaps() && cache.hasStaticMap()) {
cachesWithStaticMaps.add(cache);
continue;
@@ -1425,7 +1462,7 @@ public class cgeocaches extends AbstractListActivity {
}
}
- for (cgCache cache : cachesWithStaticMaps) {
+ for (Geocache cache : cachesWithStaticMaps) {
if (!refreshCache(cache)) {
break;
}
@@ -1443,7 +1480,7 @@ public class cgeocaches extends AbstractListActivity {
* @return
* <code>false</code> if the storing was interrupted, <code>true</code> otherwise
*/
- private boolean refreshCache(cgCache cache) {
+ private boolean refreshCache(Geocache cache) {
try {
if (needToStop) {
throw new InterruptedException("Stopped storing process.");
@@ -1458,7 +1495,7 @@ public class cgeocaches extends AbstractListActivity {
Log.i("Waiting for next cache " + delay + " ms");
} catch (Exception e) {
- Log.e("cgeocaches.LoadDetailsThread.sleep: " + e.toString());
+ Log.e("cgeocaches.LoadDetailsThread.sleep", e);
}
}
@@ -1476,7 +1513,7 @@ public class cgeocaches extends AbstractListActivity {
Log.i(e.getMessage());
return false;
} catch (Exception e) {
- Log.e("cgeocaches.LoadDetailsThread: " + e.toString());
+ Log.e("cgeocaches.LoadDetailsThread", e);
}
last = System.currentTimeMillis();
@@ -1501,13 +1538,13 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run() {
- int ret = MSG_DONE;
removeGeoAndDir();
int delay = -1;
int times = 0;
+ int ret = MSG_DONE;
while (!needToStop && times < 3 * 60 / 5) // maximum: 3 minutes, every 5 seconds
{
//download new code
@@ -1525,7 +1562,7 @@ public class cgeocaches extends AbstractListActivity {
handler.sendMessage(handler.obtainMessage(1, response));
yield();
- cgCache.storeCache(null, response, listIdLFW, false, null);
+ Geocache.storeCache(null, response, listIdLFW, false, null);
handler.sendMessage(handler.obtainMessage(2, response));
yield();
@@ -1558,7 +1595,7 @@ public class cgeocaches extends AbstractListActivity {
times = 0;
}
} catch (InterruptedException e) {
- Log.e("cgeocaches.LoadFromWebThread.sleep: " + e.toString());
+ Log.e("cgeocaches.LoadFromWebThread.sleep", e);
}
}
@@ -1571,17 +1608,17 @@ public class cgeocaches extends AbstractListActivity {
private class DropDetailsThread extends Thread {
final private Handler handler;
- final private List<cgCache> selected;
+ final private List<Geocache> selected;
- public DropDetailsThread(Handler handlerIn) {
+ public DropDetailsThread(Handler handlerIn, List<Geocache> selectedIn) {
handler = handlerIn;
- selected = adapter.getCheckedOrAllCaches();
+ selected = selectedIn;
}
@Override
public void run() {
removeGeoAndDir();
- app.markDropped(selected);
+ cgData.markDropped(selected);
handler.sendEmptyMessage(MSG_DONE);
startGeoAndDir();
@@ -1591,7 +1628,7 @@ public class cgeocaches extends AbstractListActivity {
private class RemoveFromHistoryThread extends Thread {
final private Handler handler;
- final private List<cgCache> selected;
+ final private List<Geocache> selected;
public RemoveFromHistoryThread(Handler handlerIn) {
handler = handlerIn;
@@ -1600,7 +1637,7 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run() {
- app.clearVisitDate(selected);
+ cgData.clearVisitDate(selected);
handler.sendEmptyMessage(MSG_DONE);
}
}
@@ -1650,7 +1687,7 @@ public class cgeocaches extends AbstractListActivity {
return;
}
- StoredList list = app.getList(id);
+ StoredList list = cgData.getList(id);
if (list == null) {
return;
}
@@ -1692,33 +1729,12 @@ public class cgeocaches extends AbstractListActivity {
@Override
public void run() {
- final List<cgCache> caches = adapter.getCheckedCaches();
- app.moveToList(caches, listId);
+ final List<Geocache> caches = adapter.getCheckedCaches();
+ cgData.moveToList(caches, listId);
handler.sendEmptyMessage(listId);
}
}
- /**
- * Handler to refresh the current list of caches. This list is shared with the Adapter and therefore must be updated
- * in the UI-Thread
- */
-
- private Handler refreshCacheListHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- cacheList.clear();
- if (cachesFromSearchResult != null) {
- cacheList.addAll(cachesFromSearchResult);
- }
- if (adapter != null) {
- adapter.reFilter();
- }
- updateTitle();
- showFooterMoreCaches();
- }
- };
-
-
private void renameList() {
new StoredList.UserInterface(this).promptForListRename(listId, new Runnable() {
@@ -1730,7 +1746,7 @@ public class cgeocaches extends AbstractListActivity {
}
private void removeListInternal() {
- if (app.removeList(listId)) {
+ if (cgData.removeList(listId)) {
showToast(res.getString(R.string.list_dialog_remove_ok));
switchListById(StoredList.STANDARD_LIST_ID);
} else {
@@ -1783,18 +1799,14 @@ public class cgeocaches extends AbstractListActivity {
return;
}
- SearchResult searchToUse = search;
-
// apply filter settings (if there's a filter)
- if (adapter != null) {
- Set<String> geocodes = new HashSet<String>();
- for (cgCache cache : adapter.getFilteredList()) {
- geocodes.add(cache.getGeocode());
- }
- searchToUse = new SearchResult(geocodes);
+ Set<String> geocodes = new HashSet<String>();
+ for (Geocache cache : adapter.getFilteredList()) {
+ geocodes.add(cache.getGeocode());
}
- int count = searchToUse.getCount();
+ final SearchResult searchToUse = new SearchResult(geocodes);
+ final int count = searchToUse.getCount();
String mapTitle = title;
if (count > 0) {
mapTitle = title + " [" + count + "]";
@@ -1823,7 +1835,7 @@ public class cgeocaches extends AbstractListActivity {
public static void startActivityOffline(final Context context) {
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.OFFLINE);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.OFFLINE);
context.startActivity(cachesIntent);
}
@@ -1832,8 +1844,8 @@ public class cgeocaches extends AbstractListActivity {
return;
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.OWNER);
- cachesIntent.putExtra(EXTRAS_USERNAME, userName);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.OWNER);
+ cachesIntent.putExtra(Intents.EXTRA_USERNAME, userName);
context.startActivity(cachesIntent);
}
@@ -1850,8 +1862,8 @@ public class cgeocaches extends AbstractListActivity {
return;
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.USERNAME);
- cachesIntent.putExtra(EXTRAS_USERNAME, userName);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.USERNAME);
+ cachesIntent.putExtra(Intents.EXTRA_USERNAME, userName);
context.startActivity(cachesIntent);
}
@@ -1879,7 +1891,7 @@ public class cgeocaches extends AbstractListActivity {
private void setDateComparatorForEventList() {
if (CollectionUtils.isNotEmpty(cacheList)) {
boolean eventsOnly = true;
- for (cgCache cache : cacheList) {
+ for (Geocache cache : cacheList) {
if (!cache.isEventCache()) {
eventsOnly = false;
break;
@@ -1902,22 +1914,22 @@ public class cgeocaches extends AbstractListActivity {
return;
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.NEAREST);
- cachesIntent.putExtra(EXTRAS_COORDS, coordsNow);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.NEAREST);
+ cachesIntent.putExtra(Intents.EXTRAS_COORDS, coordsNow);
context.startActivity(cachesIntent);
}
public static void startActivityHistory(Context context) {
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.HISTORY);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.HISTORY);
context.startActivity(cachesIntent);
}
public static void startActivityAddress(final Context context, final Geopoint coords, final String address) {
final Intent addressIntent = new Intent(context, cgeocaches.class);
- addressIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.ADDRESS);
- addressIntent.putExtra(EXTRAS_COORDS, coords);
- addressIntent.putExtra(EXTRAS_ADDRESS, address);
+ addressIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.ADDRESS);
+ addressIntent.putExtra(Intents.EXTRAS_COORDS, coords);
+ addressIntent.putExtra(Intents.EXTRA_ADDRESS, address);
context.startActivity(addressIntent);
}
@@ -1926,8 +1938,8 @@ public class cgeocaches extends AbstractListActivity {
return;
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.COORDINATE);
- cachesIntent.putExtra(EXTRAS_COORDS, coords);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.COORDINATE);
+ cachesIntent.putExtra(Intents.EXTRAS_COORDS, coords);
context.startActivity(cachesIntent);
}
@@ -1945,15 +1957,15 @@ public class cgeocaches extends AbstractListActivity {
return;
}
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.KEYWORD);
- cachesIntent.putExtra(EXTRAS_KEYWORD, keyword);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.KEYWORD);
+ cachesIntent.putExtra(Intents.EXTRA_KEYWORD, keyword);
context.startActivity(cachesIntent);
}
public static void startActivityMap(final Context context, final SearchResult search) {
final Intent cachesIntent = new Intent(context, cgeocaches.class);
- cachesIntent.putExtra(EXTRAS_LIST_TYPE, CacheListType.MAP);
- cachesIntent.putExtra(EXTRAS_SEARCH, search);
+ cachesIntent.putExtra(Intents.EXTRA_LIST_TYPE, CacheListType.MAP);
+ cachesIntent.putExtra(Intents.EXTRA_SEARCH, search);
context.startActivity(cachesIntent);
}
}
diff --git a/main/src/cgeo/geocaching/cgeogpxes.java b/main/src/cgeo/geocaching/cgeogpxes.java
index 909263f..d512618 100644
--- a/main/src/cgeo/geocaching/cgeogpxes.java
+++ b/main/src/cgeo/geocaching/cgeogpxes.java
@@ -10,21 +10,17 @@ import org.apache.commons.lang3.StringUtils;
import android.app.Activity;
import android.content.Intent;
-import android.os.Bundle;
import java.io.File;
import java.util.Collections;
import java.util.List;
public class cgeogpxes extends FileList<GPXListAdapter> {
- private static final String EXTRAS_LIST_ID = "list";
public cgeogpxes() {
super(new String[] { "gpx", "loc", "zip" });
}
- private int listId = StoredList.STANDARD_LIST_ID;
-
@Override
protected GPXListAdapter getAdapter(List<File> files) {
return new GPXListAdapter(this, files);
@@ -36,26 +32,13 @@ public class cgeogpxes extends FileList<GPXListAdapter> {
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- final Bundle extras = getIntent().getExtras();
- if (extras != null) {
- listId = extras.getInt(EXTRAS_LIST_ID);
- }
- if (listId <= StoredList.TEMPORARY_LIST_ID) {
- listId = StoredList.STANDARD_LIST_ID;
- }
- }
-
- @Override
protected void setTitle() {
setTitle(res.getString(R.string.gpx_import_title));
}
public static void startSubActivity(Activity fromActivity, int listId) {
final Intent intent = new Intent(fromActivity, cgeogpxes.class);
- intent.putExtra(EXTRAS_LIST_ID, listId);
+ intent.putExtra(Intents.EXTRA_LIST_ID, listId);
fromActivity.startActivityForResult(intent, 0);
}
diff --git a/main/src/cgeo/geocaching/cgeonavigate.java b/main/src/cgeo/geocaching/cgeonavigate.java
index 64b7cd8..3c6bf73 100644
--- a/main/src/cgeo/geocaching/cgeonavigate.java
+++ b/main/src/cgeo/geocaching/cgeonavigate.java
@@ -61,8 +61,7 @@ public class cgeonavigate extends AbstractActivity {
// get parameters
Bundle extras = getIntent().getExtras();
if (extras != null) {
- final String geocode = extras.getString(EXTRAS_GEOCODE);
- title = geocode;
+ title = extras.getString(EXTRAS_GEOCODE);
final String name = extras.getString(EXTRAS_NAME);
dstCoords = (Geopoint) extras.getParcelable(EXTRAS_COORDS);
info = extras.getString(EXTRAS_CACHE_INFO);
@@ -293,7 +292,7 @@ public class cgeonavigate extends AbstractActivity {
final Intent navigateIntent = new Intent(context, cgeonavigate.class);
navigateIntent.putExtra(EXTRAS_COORDS, coords);
- navigateIntent.putExtra(EXTRAS_GEOCODE, geocode.toUpperCase());
+ navigateIntent.putExtra(EXTRAS_GEOCODE, geocode);
if (null != displayedName) {
navigateIntent.putExtra(EXTRAS_NAME, displayedName);
}
diff --git a/main/src/cgeo/geocaching/cgeopoint.java b/main/src/cgeo/geocaching/cgeopoint.java
index 025b96a..9fb1905 100644
--- a/main/src/cgeo/geocaching/cgeopoint.java
+++ b/main/src/cgeo/geocaching/cgeopoint.java
@@ -6,6 +6,7 @@ import cgeo.geocaching.geopoint.DistanceParser;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.ui.Formatter;
+import cgeo.geocaching.ui.dialog.CoordinatesInputDialog;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.Log;
@@ -207,7 +208,7 @@ public class cgeopoint extends AbstractActivity {
private List<Destination> getHistoryOfSearchedLocations() {
if (historyOfSearchedLocations == null) {
// Load from database
- historyOfSearchedLocations = app.getHistoryOfSearchedLocations();
+ historyOfSearchedLocations = cgData.loadHistoryOfSearchedLocations();
}
return historyOfSearchedLocations;
@@ -290,9 +291,9 @@ public class cgeopoint extends AbstractActivity {
if (latButton.getText().length() > 0 && lonButton.getText().length() > 0) {
gp = new Geopoint(latButton.getText().toString() + " " + lonButton.getText().toString());
}
- cgeocoords coordsDialog = new cgeocoords(cgeopoint.this, null, gp, app.currentGeo());
+ CoordinatesInputDialog coordsDialog = new CoordinatesInputDialog(cgeopoint.this, null, gp, app.currentGeo());
coordsDialog.setCancelable(true);
- coordsDialog.setOnCoordinateUpdate(new cgeocoords.CoordinateUpdate() {
+ coordsDialog.setOnCoordinateUpdate(new CoordinatesInputDialog.CoordinateUpdate() {
@Override
public void update(Geopoint gp) {
latButton.setText(gp.format(GeopointFormatter.Format.LAT_DECMINUTE));
@@ -304,7 +305,7 @@ public class cgeopoint extends AbstractActivity {
}
}
- private class changeDistanceUnit implements OnItemSelectedListener {
+ private static class changeDistanceUnit implements OnItemSelectedListener {
private changeDistanceUnit(cgeopoint unitView) {
this.unitView = unitView;
@@ -393,7 +394,7 @@ public class cgeopoint extends AbstractActivity {
getHistoryOfSearchedLocations().add(0, loc);
// Save location
- app.saveSearchedDestination(loc);
+ cgData.saveSearchedDestination(loc);
// Ensure to remove the footer
historyListView.removeFooterView(getEmptyHistoryFooter());
@@ -405,7 +406,7 @@ public class cgeopoint extends AbstractActivity {
getHistoryOfSearchedLocations().remove(destination);
// Save
- app.removeSearchedDestinations(destination);
+ cgData.removeSearchedDestination(destination);
if (getHistoryOfSearchedLocations().isEmpty()) {
if (historyListView.getFooterViewsCount() == 0) {
@@ -424,7 +425,7 @@ public class cgeopoint extends AbstractActivity {
getHistoryOfSearchedLocations().clear();
// Save
- app.clearSearchedDestinations();
+ cgData.clearSearchedDestinations();
if (historyListView.getFooterViewsCount() == 0) {
historyListView.addFooterView(getEmptyHistoryFooter());
@@ -487,8 +488,6 @@ public class cgeopoint extends AbstractActivity {
}
private Geopoint getDestination() {
- Geopoint result;
- Geopoint coords;
String bearingText = ((EditText) findViewById(R.id.bearing)).getText().toString();
// combine distance from EditText and distanceUnit saved from Spinner
@@ -502,6 +501,7 @@ public class cgeopoint extends AbstractActivity {
return null;
}
+ Geopoint coords;
if (StringUtils.isNotBlank(latText) && StringUtils.isNotBlank(lonText)) {
try {
coords = new Geopoint(latText, lonText);
@@ -518,6 +518,7 @@ public class cgeopoint extends AbstractActivity {
coords = app.currentGeo().getCoords();
}
+ Geopoint result;
if (StringUtils.isNotBlank(bearingText) && StringUtils.isNotBlank(distanceText)) {
// bearing & distance
double bearing;
diff --git a/main/src/cgeo/geocaching/cgeotrackable.java b/main/src/cgeo/geocaching/cgeotrackable.java
deleted file mode 100644
index 405581d..0000000
--- a/main/src/cgeo/geocaching/cgeotrackable.java
+++ /dev/null
@@ -1,575 +0,0 @@
-package cgeo.geocaching;
-
-import cgeo.geocaching.activity.AbstractActivity;
-import cgeo.geocaching.connector.gc.GCParser;
-import cgeo.geocaching.enumerations.LogType;
-import cgeo.geocaching.geopoint.Units;
-import cgeo.geocaching.network.HtmlImage;
-import cgeo.geocaching.ui.AnchorAwareLinkMovementMethod;
-import cgeo.geocaching.ui.CacheDetailsCreator;
-import cgeo.geocaching.ui.Formatter;
-import cgeo.geocaching.utils.BaseUtils;
-import cgeo.geocaching.utils.Log;
-import cgeo.geocaching.utils.UnknownTagsHandler;
-
-import org.apache.commons.lang3.StringUtils;
-
-import android.app.ProgressDialog;
-import android.content.Intent;
-import android.graphics.drawable.BitmapDrawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.text.Html;
-import android.text.method.LinkMovementMethod;
-import android.view.ContextMenu;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-public class cgeotrackable extends AbstractActivity {
- private static final int MENU_LOG_TOUCH = 1;
- private static final int MENU_BROWSER_TRACKABLE = 2;
- private cgTrackable trackable = null;
- private String geocode = null;
- private String name = null;
- private String guid = null;
- private String id = null;
- private String contextMenuUser = null;
- private LayoutInflater inflater = null;
- private ProgressDialog waitDialog = null;
- private Handler loadTrackableHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- if (trackable == null) {
- if (waitDialog != null) {
- waitDialog.dismiss();
- }
-
- if (StringUtils.isNotBlank(geocode)) {
- showToast(res.getString(R.string.err_tb_find) + " " + geocode + ".");
- } else {
- showToast(res.getString(R.string.err_tb_find_that));
- }
-
- finish();
- return;
- }
-
- try {
- inflater = getLayoutInflater();
- geocode = trackable.getGeocode().toUpperCase();
-
- if (StringUtils.isNotBlank(trackable.getName())) {
- setTitle(Html.fromHtml(trackable.getName()).toString());
- } else {
- setTitle(trackable.getName().toUpperCase());
- }
-
- findViewById(R.id.details_list_box).setVisibility(View.VISIBLE);
- final CacheDetailsCreator details = new CacheDetailsCreator(cgeotrackable.this, (LinearLayout) findViewById(R.id.details_list));
-
- // action bar icon
- if (StringUtils.isNotBlank(trackable.getIconUrl())) {
- final TrackableIconHandler iconHandler = new TrackableIconHandler(((TextView) findViewById(R.id.actionbar_title)));
- final TrackableIconThread iconThread = new TrackableIconThread(trackable.getIconUrl(), iconHandler);
- iconThread.start();
- }
-
- // trackable name
- details.add(R.string.trackable_name, StringUtils.isNotBlank(trackable.getName()) ? Html.fromHtml(trackable.getName()).toString() : res.getString(R.string.trackable_unknown));
-
- // trackable type
- String tbType;
- if (StringUtils.isNotBlank(trackable.getType())) {
- tbType = Html.fromHtml(trackable.getType()).toString();
- } else {
- tbType = res.getString(R.string.trackable_unknown);
- }
- details.add(R.string.trackable_type, tbType);
-
- // trackable geocode
- details.add(R.string.trackable_code, trackable.getGeocode().toUpperCase());
-
- // trackable owner
- TextView owner = details.add(R.string.trackable_owner, res.getString(R.string.trackable_unknown));
- if (StringUtils.isNotBlank(trackable.getOwner())) {
- owner.setText(Html.fromHtml(trackable.getOwner()), TextView.BufferType.SPANNABLE);
- owner.setOnClickListener(new UserActionsListener());
- }
-
- // trackable spotted
- if (StringUtils.isNotBlank(trackable.getSpottedName()) ||
- trackable.getSpottedType() == cgTrackable.SPOTTED_UNKNOWN ||
- trackable.getSpottedType() == cgTrackable.SPOTTED_OWNER
- ) {
- boolean showTimeSpan = true;
- StringBuilder text;
-
- if (trackable.getSpottedType() == cgTrackable.SPOTTED_CACHE) {
- text = new StringBuilder(res.getString(R.string.trackable_spotted_in_cache) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString());
- } else if (trackable.getSpottedType() == cgTrackable.SPOTTED_USER) {
- text = new StringBuilder(res.getString(R.string.trackable_spotted_at_user) + ' ' + Html.fromHtml(trackable.getSpottedName()).toString());
- } else if (trackable.getSpottedType() == cgTrackable.SPOTTED_UNKNOWN) {
- text = new StringBuilder(res.getString(R.string.trackable_spotted_unknown_location));
- } else if (trackable.getSpottedType() == cgTrackable.SPOTTED_OWNER) {
- text = new StringBuilder(res.getString(R.string.trackable_spotted_owner));
- } else {
- text = new StringBuilder("N/A");
- showTimeSpan = false;
- }
-
- // days since last spotting
- if (showTimeSpan && trackable.getLogs() != null) {
- for (LogEntry log : trackable.getLogs()) {
- if (log.type == LogType.RETRIEVED_IT || log.type == LogType.GRABBED_IT || log.type == LogType.DISCOVERED_IT || log.type == LogType.PLACED_IT) {
- final int days = log.daysSinceLog();
- text.append(" (").append(res.getQuantityString(R.plurals.days_ago, days, days)).append(')');
- break;
- }
- }
- }
-
- final TextView spotted = details.add(R.string.trackable_spotted, text.toString());
- spotted.setClickable(true);
- if (cgTrackable.SPOTTED_CACHE == trackable.getSpottedType()) {
- spotted.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- CacheDetailActivity.startActivityGuid(cgeotrackable.this, trackable.getSpottedGuid(), trackable.getSpottedName());
- }
- });
- } else if (cgTrackable.SPOTTED_USER == trackable.getSpottedType()) {
- spotted.setOnClickListener(new UserActionsListener());
- }
- }
-
- // trackable origin
- if (StringUtils.isNotBlank(trackable.getOrigin())) {
- TextView origin = details.add(R.string.trackable_origin, "");
- origin.setText(Html.fromHtml(trackable.getOrigin()), TextView.BufferType.SPANNABLE);
- }
-
- // trackable released
- if (trackable.getReleased() != null) {
- details.add(R.string.trackable_released, Formatter.formatDate(trackable.getReleased().getTime()));
- }
-
- // trackable distance
- if (trackable.getDistance() >= 0) {
- details.add(R.string.trackable_distance, Units.getDistanceFromKilometers(trackable.getDistance()));
- }
-
- // trackable goal
- if (StringUtils.isNotBlank(trackable.getGoal())) {
- findViewById(R.id.goal_box).setVisibility(View.VISIBLE);
- TextView descView = (TextView) findViewById(R.id.goal);
- descView.setVisibility(View.VISIBLE);
- descView.setText(Html.fromHtml(trackable.getGoal(), new HtmlImage(geocode, true, 0, false), null), TextView.BufferType.SPANNABLE);
- descView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- }
-
- // trackable details
- if (StringUtils.isNotBlank(trackable.getDetails())) {
- findViewById(R.id.details_box).setVisibility(View.VISIBLE);
- TextView descView = (TextView) findViewById(R.id.details);
- descView.setVisibility(View.VISIBLE);
- descView.setText(Html.fromHtml(trackable.getDetails(), new HtmlImage(geocode, true, 0, false), new UnknownTagsHandler()), TextView.BufferType.SPANNABLE);
- descView.setMovementMethod(AnchorAwareLinkMovementMethod.getInstance());
- }
-
- // trackable image
- if (StringUtils.isNotBlank(trackable.getImage())) {
- findViewById(R.id.image_box).setVisibility(View.VISIBLE);
- LinearLayout imgView = (LinearLayout) findViewById(R.id.image);
-
- final ImageView trackableImage = (ImageView) inflater.inflate(R.layout.trackable_image, null);
-
- trackableImage.setImageResource(R.drawable.image_not_loaded);
- trackableImage.setClickable(true);
- trackableImage.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View arg0) {
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getImage())));
- }
- });
-
- // try to load image
- final Handler handler = new Handler() {
-
- @Override
- public void handleMessage(Message message) {
- BitmapDrawable image = (BitmapDrawable) message.obj;
- if (image != null) {
- trackableImage.setImageDrawable((BitmapDrawable) message.obj);
- }
- }
- };
-
- new Thread() {
-
- @Override
- public void run() {
- BitmapDrawable image;
- try {
- HtmlImage imgGetter = new HtmlImage(geocode, true, 0, false);
-
- image = imgGetter.getDrawable(trackable.getImage());
- Message message = handler.obtainMessage(0, image);
- handler.sendMessage(message);
- } catch (Exception e) {
- Log.e("cgeospoilers.onCreate.onClick.run: " + e.toString());
- }
- }
- }.start();
-
- imgView.addView(trackableImage);
- }
- } catch (Exception e) {
- Log.e("cgeotrackable.loadTrackableHandler: " + e.toString() + Arrays.toString(e.getStackTrace()));
- }
-
- displayLogs();
-
- if (waitDialog != null) {
- waitDialog.dismiss();
- }
- }
- };
-
- public cgeotrackable() {
- super("c:geo-trackable-details");
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setTheme();
- setContentView(R.layout.trackable_detail);
- setTitle(res.getString(R.string.trackable));
-
- // get parameters
- Bundle extras = getIntent().getExtras();
- Uri uri = getIntent().getData();
-
- // try to get data from extras
- if (extras != null) {
- geocode = extras.getString("geocode");
- name = extras.getString("name");
- guid = extras.getString("guid");
- id = extras.getString("id");
- }
-
- // try to get data from URI
- if (geocode == null && guid == null && id == null && uri != null) {
- String uriHost = uri.getHost().toLowerCase();
- if (uriHost.contains("geocaching.com")) {
- geocode = uri.getQueryParameter("tracker");
- guid = uri.getQueryParameter("guid");
- id = uri.getQueryParameter("id");
-
- if (StringUtils.isNotBlank(geocode)) {
- geocode = geocode.toUpperCase();
- guid = null;
- id = null;
- } else if (StringUtils.isNotBlank(guid)) {
- geocode = null;
- guid = guid.toLowerCase();
- id = null;
- } else if (StringUtils.isNotBlank(id)) {
- geocode = null;
- guid = null;
- id = id.toLowerCase();
- } else {
- showToast(res.getString(R.string.err_tb_details_open));
- finish();
- return;
- }
- } else if (uriHost.contains("coord.info")) {
- String uriPath = uri.getPath().toLowerCase();
- if (uriPath != null && uriPath.startsWith("/tb")) {
- geocode = uriPath.substring(1).toUpperCase();
- guid = null;
- id = null;
- } else {
- showToast(res.getString(R.string.err_tb_details_open));
- finish();
- return;
- }
- }
- }
-
- // no given data
- if (geocode == null && guid == null && id == null) {
- showToast(res.getString(R.string.err_tb_display));
- finish();
- return;
- }
-
- String message;
- if (StringUtils.isNotBlank(name)) {
- message = Html.fromHtml(name).toString();
- } else if (StringUtils.isNotBlank(geocode)) {
- message = geocode.toUpperCase();
- } else {
- message = res.getString(R.string.trackable);
- }
- waitDialog = ProgressDialog.show(this, message, res.getString(R.string.trackable_details_loading), true, true);
-
- LoadTrackableThread thread = new LoadTrackableThread(loadTrackableHandler, geocode, guid, id);
- thread.start();
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo info) {
- super.onCreateContextMenu(menu, view, info);
- final int viewId = view.getId();
-
- if (viewId == R.id.author) { // Log item author
- contextMenuUser = ((TextView) view).getText().toString();
- } else { // Trackable owner, and user holding trackable now
- RelativeLayout itemLayout = (RelativeLayout) view.getParent();
- TextView itemName = (TextView) itemLayout.findViewById(R.id.name);
-
- String selectedName = itemName.getText().toString();
- if (selectedName.equals(res.getString(R.string.trackable_owner))) {
- contextMenuUser = trackable.getOwner();
- } else if (selectedName.equals(res.getString(R.string.trackable_spotted))) {
- contextMenuUser = trackable.getSpottedName();
- }
- }
-
- menu.setHeaderTitle(res.getString(R.string.user_menu_title) + " " + contextMenuUser);
- menu.add(viewId, 1, 0, res.getString(R.string.user_menu_view_hidden));
- menu.add(viewId, 2, 0, res.getString(R.string.user_menu_view_found));
- menu.add(viewId, 3, 0, res.getString(R.string.user_menu_open_browser));
- }
-
- @Override
- public boolean onContextItemSelected(final MenuItem item) {
- switch (item.getItemId()) {
- case 1:
- cgeocaches.startActivityOwner(this, contextMenuUser);
- return true;
- case 2:
- cgeocaches.startActivityUserName(this, contextMenuUser);
- return true;
- case 3:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.geocaching.com/profile/?u=" + URLEncoder.encode(contextMenuUser))));
- return true;
- default:
- return false;
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_LOG_TOUCH, 0, res.getString(R.string.trackable_log_touch)).setIcon(R.drawable.ic_menu_agenda); // log touch
- menu.add(0, MENU_BROWSER_TRACKABLE, 0, res.getString(R.string.trackable_browser_open)).setIcon(R.drawable.ic_menu_info_details); // browser
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case MENU_LOG_TOUCH:
- LogTrackableActivity.startActivity(this, trackable);
- return true;
- case MENU_BROWSER_TRACKABLE:
- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(trackable.getUrl())));
- return true;
- }
- return false;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- menu.findItem(MENU_LOG_TOUCH).setEnabled(StringUtils.isNotBlank(geocode) && trackable.isLoggable());
- menu.findItem(MENU_BROWSER_TRACKABLE).setEnabled(StringUtils.isNotBlank(trackable.getUrl()));
- return super.onPrepareOptionsMenu(menu);
- }
-
- private class LoadTrackableThread extends Thread {
- final private Handler handler;
- final private String geocode;
- final private String guid;
- final private String id;
-
- public LoadTrackableThread(Handler handlerIn, String geocodeIn, String guidIn, String idIn) {
- handler = handlerIn;
- geocode = geocodeIn;
- guid = guidIn;
- id = idIn;
- }
-
- @Override
- public void run() {
- // for non TB trackables, we should just use what we have in the database
- trackable = cgeoapplication.getInstance().getTrackableByGeocode(geocode);
-
- if ((trackable == null || trackable.isLoggable()) && !StringUtils.startsWithIgnoreCase(geocode, "GK")) {
- trackable = GCParser.searchTrackable(geocode, guid, id);
- }
- handler.sendMessage(Message.obtain());
- }
- }
-
- private void displayLogs() {
- // trackable logs
- LinearLayout listView = (LinearLayout) findViewById(R.id.log_list);
- listView.removeAllViews();
-
- RelativeLayout rowView;
-
- if (trackable != null && trackable.getLogs() != null) {
- for (LogEntry log : trackable.getLogs()) {
- rowView = (RelativeLayout) inflater.inflate(R.layout.trackable_logs_item, null);
-
- if (log.date > 0) {
- ((TextView) rowView.findViewById(R.id.added)).setText(Formatter.formatShortDate(log.date));
- }
-
- ((TextView) rowView.findViewById(R.id.type)).setText(log.type.getL10n());
- ((TextView) rowView.findViewById(R.id.author)).setText(Html.fromHtml(log.author), TextView.BufferType.SPANNABLE);
-
- if (StringUtils.isBlank(log.cacheName)) {
- rowView.findViewById(R.id.location).setVisibility(View.GONE);
- } else {
- ((TextView) rowView.findViewById(R.id.location)).setText(Html.fromHtml(log.cacheName));
- final String cacheGuid = log.cacheGuid;
- final String cacheName = log.cacheName;
- rowView.findViewById(R.id.location).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- CacheDetailActivity.startActivityGuid(cgeotrackable.this, cacheGuid, Html.fromHtml(cacheName).toString());
- }
- });
- }
-
- TextView logView = (TextView) rowView.findViewById(R.id.log);
- logView.setMovementMethod(LinkMovementMethod.getInstance());
-
- String logText = log.log;
- if (BaseUtils.containsHtml(logText)) {
- logText = log.getDisplayText();
- logView.setText(Html.fromHtml(logText, new HtmlImage(null, false, StoredList.TEMPORARY_LIST_ID, false), null), TextView.BufferType.SPANNABLE);
- }
- else {
- logView.setText(logText);
- }
-
- // add LogImages
- LinearLayout logLayout = (LinearLayout) rowView.findViewById(R.id.log_layout);
-
- if (log.hasLogImages()) {
-
- final ArrayList<cgImage> logImages = new ArrayList<cgImage>(log.getLogImages());
-
- final View.OnClickListener listener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- ImagesActivity.startActivityLogImages(cgeotrackable.this, trackable.getGeocode(), logImages);
- }
- };
-
- LinearLayout log_imgView = (LinearLayout) getLayoutInflater().inflate(R.layout.trackable_logs_img, null);
- TextView log_img_title = (TextView) log_imgView.findViewById(R.id.title);
- log_img_title.setText(log.getImageTitles());
- log_img_title.setOnClickListener(listener);
- logLayout.addView(log_imgView);
- }
-
- rowView.findViewById(R.id.author).setOnClickListener(new UserActionsListener());
- listView.addView(rowView);
- }
-
- if (trackable.getLogs().size() > 0) {
- findViewById(R.id.log_box).setVisibility(View.VISIBLE);
- }
- }
- }
-
- private class UserActionsListener implements View.OnClickListener {
-
- @Override
- public void onClick(View view) {
- if (view == null) {
- return;
- }
-
- try {
- registerForContextMenu(view);
- openContextMenu(view);
- } catch (Exception e) {
- Log.e("cgeotrackable.UserActionsListener.onClick ", e);
- }
- }
- }
-
- private class TrackableIconThread extends Thread {
- final private String url;
- final private Handler handler;
-
- public TrackableIconThread(String urlIn, Handler handlerIn) {
- url = urlIn;
- handler = handlerIn;
- }
-
- @Override
- public void run() {
- if (url == null || handler == null) {
- return;
- }
-
- BitmapDrawable image;
- try {
- HtmlImage imgGetter = new HtmlImage(trackable.getGeocode(), false, 0, false);
-
- image = imgGetter.getDrawable(url);
- Message message = handler.obtainMessage(0, image);
- handler.sendMessage(message);
- } catch (Exception e) {
- Log.e("cgeotrackable.TrackableIconThread.run: " + e.toString());
- }
- }
- }
-
- private static class TrackableIconHandler extends Handler {
- final private TextView view;
-
- public TrackableIconHandler(TextView viewIn) {
- view = viewIn;
- }
-
- @Override
- public void handleMessage(Message message) {
- final BitmapDrawable image = (BitmapDrawable) message.obj;
- if (image != null && view != null) {
- image.setBounds(0, 0, view.getHeight(), view.getHeight());
- view.setCompoundDrawables(image, null, null, null);
- }
- }
- }
-
- public static void startActivity(final AbstractActivity fromContext,
- final String guid, final String geocode, final String name) {
- final Intent trackableIntent = new Intent(fromContext, cgeotrackable.class);
- trackableIntent.putExtra("guid", guid);
- trackableIntent.putExtra("geocode", geocode);
- trackableIntent.putExtra("name", name);
- fromContext.startActivity(trackableIntent);
- }
-}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Dummy.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java
index 9c2bb8c..6a23ed5 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel11Dummy.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel11Emulation.java
@@ -3,9 +3,9 @@ package cgeo.geocaching.compatibility;
import android.app.Activity;
/**
- * dummy class which has no functionality in the level 11 API
+ * implement level 11 API using older methods
*/
-public class AndroidLevel11Dummy implements AndroidLevel11Interface {
+public class AndroidLevel11Emulation implements AndroidLevel11Interface {
@Override
public void invalidateOptionsMenu(final Activity activity) {
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java
new file mode 100644
index 0000000..4eac205
--- /dev/null
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13.java
@@ -0,0 +1,31 @@
+package cgeo.geocaching.compatibility;
+
+import cgeo.geocaching.cgeoapplication;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Point;
+import android.view.WindowManager;
+
+@TargetApi(value = 13)
+public class AndroidLevel13 implements AndroidLevel13Interface {
+
+ @Override
+ public int getDisplayWidth() {
+ return getDisplaySize().x;
+ }
+
+ @Override
+ public Point getDisplaySize() {
+ Point dimensions = new Point();
+ ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay().getSize(dimensions);
+ return dimensions;
+ }
+
+ @Override
+ public int getDisplayHeight() {
+ return getDisplaySize().y;
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java
new file mode 100644
index 0000000..2257d83
--- /dev/null
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Emulation.java
@@ -0,0 +1,33 @@
+package cgeo.geocaching.compatibility;
+
+import cgeo.geocaching.cgeoapplication;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.view.Display;
+import android.view.WindowManager;
+
+@SuppressWarnings("deprecation")
+public class AndroidLevel13Emulation implements AndroidLevel13Interface {
+
+ @Override
+ public int getDisplayWidth() {
+ return getDisplay().getWidth();
+ }
+
+ @Override
+ public int getDisplayHeight() {
+ return getDisplay().getHeight();
+ }
+
+ @Override
+ public Point getDisplaySize() {
+ final Display display = getDisplay();
+ return new Point(display.getWidth(), display.getHeight());
+ }
+
+ private static Display getDisplay() {
+ return ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE))
+ .getDefaultDisplay();
+ }
+}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java
new file mode 100644
index 0000000..f4e1975
--- /dev/null
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel13Interface.java
@@ -0,0 +1,11 @@
+package cgeo.geocaching.compatibility;
+
+import android.graphics.Point;
+
+public interface AndroidLevel13Interface {
+ int getDisplayWidth();
+
+ int getDisplayHeight();
+
+ Point getDisplaySize();
+}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java
index ea5a795..a388adb 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8.java
@@ -6,6 +6,7 @@ import android.annotation.TargetApi;
import android.app.Activity;
import android.app.backup.BackupManager;
import android.view.Display;
+import android.view.Surface;
@TargetApi(8)
public class AndroidLevel8 implements AndroidLevel8Interface {
@@ -21,4 +22,23 @@ public class AndroidLevel8 implements AndroidLevel8Interface {
Log.i("Requesting settings backup with settings manager");
BackupManager.dataChanged(name);
}
+
+ @Override
+ public int getRotationOffset(final Activity activity) {
+ try {
+ final int rotation = getRotation(activity);
+ if (rotation == Surface.ROTATION_90) {
+ return 90;
+ } else if (rotation == Surface.ROTATION_180) {
+ return 180;
+ } else if (rotation == Surface.ROTATION_270) {
+ return 270;
+ }
+ } catch (final Exception e) {
+ // This should never happen: IllegalArgumentException, IllegalAccessException or InvocationTargetException
+ Log.e("Cannot call getRotation()", e);
+ }
+
+ return 0;
+ }
}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java
deleted file mode 100644
index d0ab911..0000000
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Dummy.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package cgeo.geocaching.compatibility;
-
-import android.app.Activity;
-
-public class AndroidLevel8Dummy implements AndroidLevel8Interface {
-
- @Override
- public int getRotation(final Activity activity) {
- return 0;
- }
-
- @Override
- public void dataChanged(final String name) {
- // do nothing
- }
-}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java
new file mode 100644
index 0000000..197993d
--- /dev/null
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Emulation.java
@@ -0,0 +1,30 @@
+package cgeo.geocaching.compatibility;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.view.Display;
+
+@TargetApi(value = 7)
+public class AndroidLevel8Emulation implements AndroidLevel8Interface {
+
+ @Override
+ public int getRotation(final Activity activity) {
+ return 0;
+ }
+
+ @Override
+ public void dataChanged(final String name) {
+ // do nothing
+ }
+
+ @Override
+ public int getRotationOffset(Activity activity) {
+ final Display display = activity.getWindowManager().getDefaultDisplay();
+ final int rotation = display.getOrientation();
+ if (rotation == Configuration.ORIENTATION_LANDSCAPE) {
+ return 90;
+ }
+ return 0;
+ }
+}
diff --git a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java
index b1c4f81..761c23a 100644
--- a/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java
+++ b/main/src/cgeo/geocaching/compatibility/AndroidLevel8Interface.java
@@ -6,4 +6,5 @@ public interface AndroidLevel8Interface {
public int getRotation(final Activity activity);
public void dataChanged(final String name);
+ public int getRotationOffset(final Activity activity);
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/compatibility/Compatibility.java b/main/src/cgeo/geocaching/compatibility/Compatibility.java
index 0821655..05a3331 100644
--- a/main/src/cgeo/geocaching/compatibility/Compatibility.java
+++ b/main/src/cgeo/geocaching/compatibility/Compatibility.java
@@ -8,11 +8,9 @@ import org.apache.commons.lang3.reflect.MethodUtils;
import android.app.Activity;
import android.content.Intent;
-import android.content.res.Configuration;
+import android.graphics.Point;
import android.os.Build;
import android.text.InputType;
-import android.view.Display;
-import android.view.Surface;
import android.widget.EditText;
public final class Compatibility {
@@ -23,19 +21,26 @@ public final class Compatibility {
private final static AndroidLevel8Interface level8;
private final static AndroidLevel11Interface level11;
+ private final static AndroidLevel13Interface level13;
static {
if (isLevel8) {
level8 = new AndroidLevel8();
}
else {
- level8 = new AndroidLevel8Dummy();
+ level8 = new AndroidLevel8Emulation();
}
if (sdkVersion >= 11) {
level11 = new AndroidLevel11();
}
else {
- level11 = new AndroidLevel11Dummy();
+ level11 = new AndroidLevel11Emulation();
+ }
+ if (sdkVersion >= 13) {
+ level13 = new AndroidLevel13();
+ }
+ else {
+ level13 = new AndroidLevel13Emulation();
}
}
@@ -47,29 +52,7 @@ public final class Compatibility {
* @return the adjusted direction, in the [0, 360[ range
*/
public static float getDirectionNow(final float directionNowPre, final Activity activity) {
- float offset = 0;
- if (isLevel8) {
- try {
- final int rotation = level8.getRotation(activity);
- if (rotation == Surface.ROTATION_90) {
- offset = 90;
- } else if (rotation == Surface.ROTATION_180) {
- offset = 180;
- } else if (rotation == Surface.ROTATION_270) {
- offset = 270;
- }
- } catch (final Exception e) {
- // This should never happen: IllegalArgumentException, IllegalAccessException or InvocationTargetException
- Log.e("Cannot call getRotation()", e);
- }
- } else {
- final Display display = activity.getWindowManager().getDefaultDisplay();
- final int rotation = display.getOrientation();
- if (rotation == Configuration.ORIENTATION_LANDSCAPE) {
- offset = 90;
- }
- }
- return AngleUtils.normalize(directionNowPre + offset);
+ return AngleUtils.normalize(directionNowPre + level8.getRotationOffset(activity));
}
public static void dataChanged(final String name) {
@@ -113,4 +96,16 @@ public final class Compatibility {
level11.invalidateOptionsMenu(activity);
}
+ public static int getDisplayWidth() {
+ return level13.getDisplayWidth();
+ }
+
+ public static int getDisplayHeight() {
+ return level13.getDisplayHeight();
+ }
+
+ public static Point getDisplaySize() {
+ return level13.getDisplaySize();
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/AbstractConnector.java b/main/src/cgeo/geocaching/connector/AbstractConnector.java
index 112d6cf..1eb8fbb 100644
--- a/main/src/cgeo/geocaching/connector/AbstractConnector.java
+++ b/main/src/cgeo/geocaching/connector/AbstractConnector.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.connector;
-import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.enumerations.CacheRealm;
+import cgeo.geocaching.geopoint.Geopoint;
import org.apache.commons.lang3.StringUtils;
@@ -19,6 +19,31 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
+ public boolean supportsOwnCoordinates() {
+ return false;
+ }
+
+ /**
+ * Uploading modified coordinates to website
+ *
+ * @param cache
+ * @param wpt
+ * @return success
+ */
+ @Override
+ public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@link IConnector}
+ */
+ @Override
+ public boolean deleteModifiedCoordinates(Geocache cache) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public boolean supportsFavoritePoints() {
return false;
}
@@ -29,7 +54,7 @@ public abstract class AbstractConnector implements IConnector {
}
@Override
- public String getLicenseText(final cgCache cache) {
+ public String getLicenseText(final Geocache cache) {
return null;
}
@@ -38,11 +63,6 @@ public abstract class AbstractConnector implements IConnector {
return false;
}
- @Override
- public SearchResult searchByViewport(Viewport viewport, String tokens[]) {
- return null;
- }
-
protected static boolean isNumericId(final String string) {
try {
return Integer.parseInt(string) > 0;
@@ -81,4 +101,20 @@ public abstract class AbstractConnector implements IConnector {
}
abstract protected String getCacheUrlPrefix();
+
+ /**
+ * {@link IConnector}
+ */
+ @Override
+ public CacheRealm getCacheRealm() {
+ return CacheRealm.OTHER;
+ }
+
+ /**
+ * {@link IConnector}
+ */
+ @Override
+ public boolean isActivated() {
+ return false;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/ConnectorFactory.java b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
index bc4dcc0..561bae2 100644
--- a/main/src/cgeo/geocaching/connector/ConnectorFactory.java
+++ b/main/src/cgeo/geocaching/connector/ConnectorFactory.java
@@ -2,26 +2,32 @@ package cgeo.geocaching.connector;
import cgeo.geocaching.ICache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgTrackable;
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByViewPort;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.oc.OCApiConnector;
import cgeo.geocaching.connector.oc.OCConnector;
+import cgeo.geocaching.connector.oc.OCXMLApiConnector;
import cgeo.geocaching.connector.ox.OXConnector;
import cgeo.geocaching.geopoint.Viewport;
import org.apache.commons.lang3.StringUtils;
+import java.util.ArrayList;
+import java.util.List;
+
public final class ConnectorFactory {
private static final UnknownConnector UNKNOWN_CONNECTOR = new UnknownConnector();
private static final IConnector[] connectors = new IConnector[] {
GCConnector.getInstance(),
- new OCConnector("OpenCaching.DE", "www.opencaching.de", "OC"),
+ new OCXMLApiConnector("OpenCaching.DE", "www.opencaching.de", "OC"),
new OCConnector("OpenCaching.CZ", "www.opencaching.cz", "OZ"),
new OCApiConnector("OpenCaching.CO.UK", "www.opencaching.org.uk", "OK", "arU4okouc4GEjMniE2fq"),
new OCConnector("OpenCaching.ES", "www.opencachingspain.es", "OC"),
new OCConnector("OpenCaching.IT", "www.opencaching.it", "OC"),
new OCConnector("OpenCaching.JP", "www.opencaching.jp", "OJ"),
- new OCConnector("OpenCaching.NO/SE", "www.opencaching.no", "OS"),
+ new OCConnector("OpenCaching.NO/SE", "www.opencaching.se", "OS"),
new OCApiConnector("OpenCaching.NL", "www.opencaching.nl", "OB", "PdzU8jzIlcfMADXaYN8j"),
new OCApiConnector("OpenCaching.PL", "www.opencaching.pl", "OP", "GkxM47WkUkLQXXsZ9qSh"),
new OCApiConnector("OpenCaching.US", "www.opencaching.us", "OU", "pTsYAYSXFcfcRQnYE6uA"),
@@ -31,10 +37,37 @@ public final class ConnectorFactory {
UNKNOWN_CONNECTOR // the unknown connector MUST be the last one
};
+ private static final ISearchByViewPort[] searchByViewPortConns;
+
+ private static final ISearchByCenter[] searchByCenterConns;
+
+ static {
+ List<ISearchByViewPort> vpConns = new ArrayList<ISearchByViewPort>();
+ for (IConnector conn : connectors) {
+ if (conn instanceof ISearchByViewPort) {
+ vpConns.add((ISearchByViewPort) conn);
+ }
+ }
+ searchByViewPortConns = vpConns.toArray(new ISearchByViewPort[vpConns.size()]);
+
+ List<ISearchByCenter> centerConns = new ArrayList<ISearchByCenter>();
+ for (IConnector conn : connectors) {
+ // GCConnector is handled specially, omit it here!
+ if (conn instanceof ISearchByCenter && !(conn instanceof GCConnector)) {
+ centerConns.add((ISearchByCenter) conn);
+ }
+ }
+ searchByCenterConns = centerConns.toArray(new ISearchByCenter[centerConns.size()]);
+ }
+
public static IConnector[] getConnectors() {
return connectors;
}
+ public static ISearchByCenter[] getSearchByCenterConnectors() {
+ return searchByCenterConns;
+ }
+
public static boolean canHandle(final String geocode) {
if (isInvalidGeocode(geocode)) {
return false;
@@ -51,7 +84,7 @@ public final class ConnectorFactory {
return getConnector(cache.getGeocode());
}
- public static IConnector getConnector(cgTrackable trackable) {
+ public static IConnector getConnector(Trackable trackable) {
return getConnector(trackable.getGeocode());
}
@@ -74,11 +107,19 @@ public final class ConnectorFactory {
return StringUtils.isBlank(geocode) || !Character.isLetterOrDigit(geocode.charAt(0));
}
- /** @see IConnector#searchByViewport */
+ /** @see ISearchByViewPort#searchByViewport */
public static SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
- // We have only connector capable of doing a 'searchByViewport()'
- // If there is a second connector the information has to be collected from all collectors
- return GCConnector.getInstance().searchByViewport(viewport, tokens);
+
+ SearchResult result = new SearchResult();
+ for (ISearchByViewPort vpconn : searchByViewPortConns) {
+ if (vpconn.isActivated()) {
+ SearchResult temp = vpconn.searchByViewport(viewport, tokens);
+ if (temp != null) {
+ result.addGeocodes(temp.getGeocodes());
+ }
+ }
+ }
+ return result;
}
public static String getGeocodeFromURL(final String url) {
diff --git a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java
index 30d1a4b..ac2fb37 100644
--- a/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java
+++ b/main/src/cgeo/geocaching/connector/GeocachingAustraliaConnector.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
import org.apache.commons.lang3.StringUtils;
@@ -12,7 +13,7 @@ public class GeocachingAustraliaConnector extends AbstractConnector {
}
@Override
- public String getCacheUrl(final cgCache cache) {
+ public String getCacheUrl(final Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@@ -22,6 +23,11 @@ public class GeocachingAustraliaConnector extends AbstractConnector {
}
@Override
+ public boolean isOwner(final ICache cache) {
+ return false;
+ }
+
+ @Override
public boolean canHandle(final String geocode) {
return (StringUtils.startsWithIgnoreCase(geocode, "GA") || StringUtils.startsWithIgnoreCase(geocode, "TP")) && isNumericId(geocode.substring(2));
}
diff --git a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java
index 6ef91db..500f752 100644
--- a/main/src/cgeo/geocaching/connector/GeopeitusConnector.java
+++ b/main/src/cgeo/geocaching/connector/GeopeitusConnector.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
import org.apache.commons.lang3.StringUtils;
@@ -12,7 +13,7 @@ public class GeopeitusConnector extends AbstractConnector {
}
@Override
- public String getCacheUrl(final cgCache cache) {
+ public String getCacheUrl(final Geocache cache) {
return getCacheUrlPrefix() + StringUtils.stripStart(cache.getGeocode().substring(2), "0");
}
@@ -22,6 +23,11 @@ public class GeopeitusConnector extends AbstractConnector {
}
@Override
+ public boolean isOwner(final ICache cache) {
+ return false;
+ }
+
+ @Override
public boolean canHandle(String geocode) {
return StringUtils.startsWith(geocode, "GE") && isNumericId(geocode.substring(2));
}
diff --git a/main/src/cgeo/geocaching/connector/IConnector.java b/main/src/cgeo/geocaching/connector/IConnector.java
index d6ac2ff..da626f2 100644
--- a/main/src/cgeo/geocaching/connector/IConnector.java
+++ b/main/src/cgeo/geocaching/connector/IConnector.java
@@ -1,8 +1,9 @@
package cgeo.geocaching.connector;
-import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.ICache;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.enumerations.CacheRealm;
+import cgeo.geocaching.geopoint.Geopoint;
public interface IConnector {
/**
@@ -26,7 +27,7 @@ public interface IConnector {
* @param cache
* @return
*/
- public String getCacheUrl(final cgCache cache);
+ public String getCacheUrl(final Geocache cache);
/**
* enable/disable watchlist controls in cache details
@@ -62,7 +63,7 @@ public interface IConnector {
* @param cache
* @return
*/
- public String getLicenseText(final cgCache cache);
+ public String getLicenseText(final Geocache cache);
/**
* enable/disable user actions in cache details
@@ -72,15 +73,6 @@ public interface IConnector {
public boolean supportsUserActions();
/**
- * Search caches by viewport.
- *
- * @param viewport
- * @param tokens
- * @return
- */
- public SearchResult searchByViewport(final Viewport viewport, final String[] tokens);
-
- /**
* return true if this is a ZIP file containing a GPX file
*
* @param fileName
@@ -106,10 +98,57 @@ public interface IConnector {
/**
* extract a geocode from the given URL, if this connector can handle that URL somehow
- *
+ *
* @param url
* @return
*/
public String getGeocodeFromUrl(final String url);
+ /**
+ * enable/disable uploading modified coordinates to website
+ *
+ * @return true, when uploading is possible
+ */
+ public boolean supportsOwnCoordinates();
+
+ /**
+ * Uploading modified coordinates to website
+ *
+ * @param cache
+ * @param wpt
+ * @return success
+ */
+ public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt);
+
+ /**
+ * Reseting of modified coordinates on website to details
+ *
+ * @param cache
+ * @return success
+ */
+ public boolean deleteModifiedCoordinates(Geocache cache);
+
+ /**
+ * The CacheRealm this cache belongs to
+ *
+ * @return
+ */
+ public CacheRealm getCacheRealm();
+
+ /**
+ * Return true if this connector is activated for online
+ * interaction (download details, do searches, ...)
+ *
+ * @return
+ */
+
+ public boolean isActivated();
+
+ /**
+ * Check if the current user is the owner of the given cache.
+ *
+ * @param cache a cache that this connector must be able to handle
+ * @return <code>true</code> if the current user is the cache owner, <code>false</code> otherwise
+ */
+ public boolean isOwner(final ICache cache);
}
diff --git a/main/src/cgeo/geocaching/connector/UnknownConnector.java b/main/src/cgeo/geocaching/connector/UnknownConnector.java
index 991d31c..b6fc29a 100644
--- a/main/src/cgeo/geocaching/connector/UnknownConnector.java
+++ b/main/src/cgeo/geocaching/connector/UnknownConnector.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.ICache;
+import cgeo.geocaching.Geocache;
import org.apache.commons.lang3.StringUtils;
@@ -12,7 +13,7 @@ public class UnknownConnector extends AbstractConnector {
}
@Override
- public String getCacheUrl(cgCache cache) {
+ public String getCacheUrl(Geocache cache) {
return null; // we have no url for these caches
}
@@ -22,6 +23,11 @@ public class UnknownConnector extends AbstractConnector {
}
@Override
+ public boolean isOwner(final ICache cache) {
+ return false;
+ }
+
+ @Override
public boolean canHandle(final String geocode) {
return StringUtils.isNotBlank(geocode);
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
index 62645c2..3fdd61f 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByCenter.java
@@ -10,4 +10,5 @@ import cgeo.geocaching.geopoint.Geopoint;
public interface ISearchByCenter {
public SearchResult searchByCenter(final Geopoint center);
+ public boolean isActivated();
}
diff --git a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
index 316cf00..f1bd2ce 100644
--- a/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
+++ b/main/src/cgeo/geocaching/connector/capability/ISearchByViewPort.java
@@ -5,4 +5,6 @@ import cgeo.geocaching.geopoint.Viewport;
public interface ISearchByViewPort {
public SearchResult searchByViewport(final Viewport viewport, final String[] tokens);
+
+ public boolean isActivated();
}
diff --git a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java
index d0e45f6..f19064d 100644
--- a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java
+++ b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java
@@ -12,7 +12,7 @@ abstract public class AbstractSearchThread extends Thread {
private final Handler handler;
private static AbstractSearchThread currentInstance;
- public AbstractSearchThread(final Handler handler) {
+ protected AbstractSearchThread(final Handler handler) {
this.handler = handler;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConnector.java b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
index 197d4e6..2a38bd9 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConnector.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConnector.java
@@ -1,12 +1,16 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.connector.AbstractConnector;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
+import cgeo.geocaching.connector.capability.ISearchByViewPort;
+import cgeo.geocaching.enumerations.CacheRealm;
import cgeo.geocaching.enumerations.StatusCode;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
@@ -18,21 +22,24 @@ import org.apache.commons.lang3.StringUtils;
import java.util.regex.Pattern;
-public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter {
+public class GCConnector extends AbstractConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort {
private static final String HTTP_COORD_INFO = "http://coord.info/";
- private static GCConnector instance;
private static final Pattern gpxZipFilePattern = Pattern.compile("\\d{7,}(_.+)?\\.zip", Pattern.CASE_INSENSITIVE);
private GCConnector() {
// singleton
}
+ /**
+ * initialization on demand holder pattern
+ */
+ private static class Holder {
+ private static final GCConnector INSTANCE = new GCConnector();
+ }
+
public static GCConnector getInstance() {
- if (instance == null) {
- instance = new GCConnector();
- }
- return instance;
+ return Holder.INSTANCE;
}
@Override
@@ -44,12 +51,17 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
}
@Override
- public String getCacheUrl(cgCache cache) {
+ public String getCacheUrl(Geocache cache) {
// it would also be possible to use "http://www.geocaching.com/seek/cache_details.aspx?wp=" + cache.getGeocode();
return "http://www.geocaching.com//seek/cache_details.aspx?wp=" + cache.getGeocode();
}
@Override
+ public boolean supportsOwnCoordinates() {
+ return true;
+ }
+
+ @Override
public boolean supportsWatchList() {
return true;
}
@@ -83,11 +95,10 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
if (StringUtils.isEmpty(page)) {
final SearchResult search = new SearchResult();
- if (cgeoapplication.getInstance().isThere(geocode, guid, true, false)) {
+ if (cgData.isThere(geocode, guid, true, false)) {
if (StringUtils.isBlank(geocode) && StringUtils.isNotBlank(guid)) {
Log.i("Loading old cache from cache.");
-
- search.addGeocode(cgeoapplication.getInstance().getGeocode(guid));
+ search.addGeocode(cgData.getGeocodeForGuid(guid));
} else {
search.addGeocode(geocode);
}
@@ -103,7 +114,7 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
final SearchResult searchResult = GCParser.parseCache(page, handler);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
- Log.e("GCConnector.searchByGeocode: No cache parsed");
+ Log.w("GCConnector.searchByGeocode: No cache parsed");
return searchResult;
}
@@ -126,39 +137,81 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
return cacheHasReliableLatLon;
}
- public static boolean addToWatchlist(cgCache cache) {
+ @Override
+ public boolean isOwner(final ICache cache) {
+ return StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getUsername());
+
+ }
+
+ public static boolean addToWatchlist(Geocache cache) {
final boolean added = GCParser.addToWatchlist(cache);
if (added) {
- cgeoapplication.getInstance().updateCache(cache);
+ cgData.saveChangedCache(cache);
}
return added;
}
- public static boolean removeFromWatchlist(cgCache cache) {
+ public static boolean removeFromWatchlist(Geocache cache) {
final boolean removed = GCParser.removeFromWatchlist(cache);
if (removed) {
- cgeoapplication.getInstance().updateCache(cache);
+ cgData.saveChangedCache(cache);
}
return removed;
}
- public static boolean addToFavorites(cgCache cache) {
+ /**
+ * Add a cache to the favorites list.
+ *
+ * This must not be called from the UI thread.
+ *
+ * @param cache the cache to add
+ * @return <code>true</code> if the cache was sucessfully added, <code>false</code> otherwise
+ */
+
+ public static boolean addToFavorites(Geocache cache) {
final boolean added = GCParser.addToFavorites(cache);
if (added) {
- cgeoapplication.getInstance().updateCache(cache);
+ cgData.saveChangedCache(cache);
}
return added;
}
- public static boolean removeFromFavorites(cgCache cache) {
+ /**
+ * Remove a cache from the favorites list.
+ *
+ * This must not be called from the UI thread.
+ *
+ * @param cache the cache to add
+ * @return <code>true</code> if the cache was sucessfully added, <code>false</code> otherwise
+ */
+
+ public static boolean removeFromFavorites(Geocache cache) {
final boolean removed = GCParser.removeFromFavorites(cache);
if (removed) {
- cgeoapplication.getInstance().updateCache(cache);
+ cgData.saveChangedCache(cache);
}
return removed;
}
@Override
+ public boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ final boolean uploaded = GCParser.uploadModifiedCoordinates(cache, wpt);
+ if (uploaded) {
+ cgData.saveChangedCache(cache);
+ }
+ return uploaded;
+ }
+
+ @Override
+ public boolean deleteModifiedCoordinates(Geocache cache) {
+ final boolean deleted = GCParser.deleteModifiedCoordinates(cache);
+ if (deleted) {
+ cgData.saveChangedCache(cache);
+ }
+ return deleted;
+ }
+
+ @Override
public SearchResult searchByCenter(Geopoint center) {
// TODO make search by coordinate use this method. currently it is just a marker that this connector supports search by center
return null;
@@ -173,4 +226,14 @@ public class GCConnector extends AbstractConnector implements ISearchByGeocode,
protected String getCacheUrlPrefix() {
return HTTP_COORD_INFO;
}
+
+ @Override
+ public CacheRealm getCacheRealm() {
+ return CacheRealm.GC;
+ }
+
+ @Override
+ public boolean isActivated() {
+ return true;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCConstants.java b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
index 65f0bdb..8a4a741 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCConstants.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCConstants.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.connector.gc;
+import java.util.Locale;
import java.util.regex.Pattern;
/**
@@ -49,7 +50,7 @@ public final class GCConstants {
public final static Pattern PATTERN_FAVORITE = Pattern.compile("<div id=\"pnlFavoriteCache\">"); // without 'class="hideMe"' inside the tag !
public final static Pattern PATTERN_FAVORITECOUNT = Pattern.compile("<a id=\"uxFavContainerLink\"[^>]+>[^<]*<div[^<]*<span class=\"favorite-value\">\\D*([0-9]+?)</span>");
public final static Pattern PATTERN_COUNTLOGS = Pattern.compile("<span id=\"ctl00_ContentBody_lblFindCounts\"><p(.+?)</p></span>");
- public final static Pattern PATTERN_LOGBOOK = Pattern.compile("initalLogs = (\\{.+\\});");
+ public final static Pattern PATTERN_LOGBOOK = Pattern.compile("initalLogs = (\\{.+\\});"); // The "inital" typo really comes from gc.com site
/** Two groups ! */
public final static Pattern PATTERN_COUNTLOG = Pattern.compile("<img src=\"/images/logtypes/([0-9]+)\\.png\"[^>]+> (\\d*[,.]?\\d+)");
public static final Pattern PATTERN_PREMIUMMEMBERS = Pattern.compile("<p class=\"Warning NoBottomSpacing\">This is a Premium Member Only cache.</p>");
@@ -103,7 +104,7 @@ public final class GCConstants {
public final static Pattern PATTERN_TRACKABLE_ICON = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"([^\"]+)\"[^>]*>");
public final static Pattern PATTERN_TRACKABLE_TYPE = Pattern.compile("<img id=\"ctl00_ContentBody_BugTypeImage\" class=\"TravelBugHeaderIcon\" src=\"[^\"]+\" alt=\"([^\"]+)\"[^>]*>");
public final static Pattern PATTERN_TRACKABLE_DISTANCE = Pattern.compile("<h4[^>]*\\W*Tracking History \\(([0-9.,]+(km|mi))[^\\)]*\\)");
- public final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("<tr class=\"Data BorderTop .+?src=\"/images/logtypes/([^.]+)\\.png[^>]+>&nbsp;([^<]+)</td>.+?guid.+?>([^<]+)</a>.+?(?:guid=([^\"]+)\">(<span[^>]+>)?([^<]+)</.+?)?<td colspan=\"4\">(.+?)(?:<ul.+?ul>)?\\s*</td>\\s*</tr>");
+ public final static Pattern PATTERN_TRACKABLE_LOG = Pattern.compile("<tr class=\"Data BorderTop .+?src=\"/images/logtypes/([^.]+)\\.png[^>]+>&nbsp;([^<]+)</td>.+?guid.+?>([^<]+)</a>.+?(?:guid=([^\"]+)\">(<span[^>]+>)?([^<]+)</.+?)?<td colspan=\"4\">\\s*<div>(.*?)</div>\\s*(?:<ul.+?ul>)?\\s*</td>\\s*</tr>");
public final static Pattern PATTERN_TRACKABLE_LOG_IMAGES = Pattern.compile("<li><a href=\"([^\"]+)\".+?LogImgTitle.+?>([^<]+)</");
/**
@@ -164,8 +165,9 @@ public final class GCConstants {
public final static String STRING_PREMIUMONLY_2 = "Sorry, the owner of this listing has made it viewable to Premium Members only.";
public final static String STRING_PREMIUMONLY_1 = "has chosen to make this cache listing visible to Premium Members only.";
- public final static String STRING_UNPUBLISHED_OWNER = "Cache is Unpublished";
+ public final static String STRING_UNPUBLISHED_OWNER = "cache has not been published yet";
public final static String STRING_UNPUBLISHED_OTHER = "you cannot view this cache listing until it has been published";
+ public final static String STRING_UNPUBLISHED_FROM_SEARCH = "UnpublishedCacheSearchWidget";
public final static String STRING_UNKNOWN_ERROR = "An Error Has Occurred";
public final static String STRING_DISABLED = "<li>This cache is temporarily unavailable.";
public final static String STRING_ARCHIVED = "<li>This cache has been archived,";
@@ -185,14 +187,14 @@ public final class GCConstants {
* see http://support.groundspeak.com/index.php?pg=kb.printer.friendly&id=1#p221
*/
public static long gccodeToGCId(final String gccode) {
- long gcid = 0;
long base = GC_BASE31;
- String geocodeWO = gccode.substring(2).toUpperCase();
+ String geocodeWO = gccode.substring(2).toUpperCase(Locale.US);
if ((geocodeWO.length() < 4) || (geocodeWO.length() == 4 && SEQUENCE_GCID.indexOf(geocodeWO.charAt(0)) < 16)) {
base = GC_BASE16;
}
+ long gcid = 0;
for (int p = 0; p < geocodeWO.length(); p++) {
gcid = base * gcid + SEQUENCE_GCID.indexOf(geocodeWO.charAt(p));
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java
index 681a1d7..2e1dff0 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCMap.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java
@@ -2,7 +2,8 @@ package cgeo.geocaching.connector.gc;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -40,10 +41,10 @@ public class GCMap {
final SearchResult result = new SearchResult();
final String geocodeList = StringUtils.join(geocodes.toArray(), "|");
- final String referer = GCConstants.URL_LIVE_MAP_DETAILS;
try {
final Parameters params = new Parameters("i", geocodeList, "_", String.valueOf(System.currentTimeMillis()));
+ final String referer = GCConstants.URL_LIVE_MAP_DETAILS;
final String data = StringUtils.defaultString(Tile.requestMapInfo(referer, params, referer));
// Example JSON information
@@ -67,7 +68,7 @@ public class GCMap {
}
for (int j = 0; j < dataArray.length(); j++) {
- final cgCache cache = new cgCache();
+ final Geocache cache = new Geocache();
JSONObject dataObject = dataArray.getJSONObject(j);
cache.setName(dataObject.getString("name"));
@@ -166,6 +167,8 @@ public class GCMap {
// iterate over the data and construct all caches in this tile
Map<String, List<UTFGridPosition>> positions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key
+ Map<String, List<UTFGridPosition>> singlePositions = new HashMap<String, List<UTFGridPosition>>(); // JSON id as key
+
for (int i = 1; i < keys.length(); i++) { // index 0 is empty
String key = keys.getString(i);
if (StringUtils.isNotBlank(key)) {
@@ -177,12 +180,20 @@ public class GCMap {
nameCache.put(id, cacheInfo.getString("n"));
List<UTFGridPosition> listOfPositions = positions.get(id);
+ List<UTFGridPosition> singleListOfPositions = singlePositions.get(id);
+
if (listOfPositions == null) {
listOfPositions = new ArrayList<UTFGridPosition>();
positions.put(id, listOfPositions);
+ singleListOfPositions = new ArrayList<UTFGridPosition>();
+ singlePositions.put(id, singleListOfPositions);
}
listOfPositions.add(pos);
+ if (dataForKey.length() == 1) {
+ singleListOfPositions.add(pos);
+ }
+
}
}
}
@@ -191,27 +202,31 @@ public class GCMap {
String id = entry.getKey();
List<UTFGridPosition> pos = entry.getValue();
UTFGridPosition xy = UTFGrid.getPositionInGrid(pos);
- cgCache cache = new cgCache();
+ Geocache cache = new Geocache();
cache.setDetailed(false);
cache.setReliableLatLon(false);
cache.setGeocode(id);
cache.setName(nameCache.get(id));
cache.setZoomlevel(tile.getZoomlevel());
cache.setCoords(tile.getCoord(xy));
- if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && positions.size() < 64 && bitmap != null) {
- // don't parse if there are too many caches. The decoding would return too much wrong results
- IconDecoder.parseMapPNG(cache, bitmap, xy, tile.getZoomlevel());
+ if (strategy.flags.contains(StrategyFlag.PARSE_TILES) && bitmap != null) {
+ for (UTFGridPosition singlePos : singlePositions.get(id)) {
+ if (IconDecoder.parseMapPNG(cache, bitmap, singlePos, tile.getZoomlevel())) {
+ break; // cache parsed
+ }
+ }
} else {
cache.setType(CacheType.UNKNOWN);
}
+
boolean exclude = false;
- if (Settings.isExcludeMyCaches() && (cache.isFound() || cache.isOwn())) { // workaround for BM
+ if (Settings.isExcludeMyCaches() && (cache.isFound() || cache.isOwner())) { // workaround for BM
exclude = true;
}
if (Settings.isExcludeDisabledCaches() && cache.isDisabled()) {
exclude = true;
}
- if (Settings.getCacheType() != CacheType.ALL && Settings.getCacheType() != cache.getType() && cache.getType() != CacheType.UNKNOWN) { // workaround for BM
+ if (!Settings.getCacheType().contains(cache) && cache.getType() != CacheType.UNKNOWN) { // workaround for BM
exclude = true;
}
if (!exclude) {
@@ -313,7 +328,7 @@ public class GCMap {
String data = Tile.requestMapInfo(GCConstants.URL_MAP_INFO, params, GCConstants.URL_LIVE_MAP);
if (StringUtils.isEmpty(data)) {
- Log.e("GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")");
+ Log.w("GCBase.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")");
} else {
final SearchResult search = GCMap.parseMapJSON(data, tile, bitmap, strategy);
if (search == null || CollectionUtils.isEmpty(search.getGeocodes())) {
@@ -341,7 +356,7 @@ public class GCMap {
if (search != null && !search.isEmpty()) {
final Set<String> geocodes = search.getGeocodes();
if (Settings.isPremiumMember()) {
- lastSearchViewport = cgeoapplication.getInstance().getBounds(geocodes);
+ lastSearchViewport = cgData.getBounds(geocodes);
} else {
lastSearchViewport = new Viewport(center, center);
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java
index 158a201..2117053 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCParser.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java
@@ -1,14 +1,15 @@
package cgeo.geocaching.connector.gc;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
+import cgeo.geocaching.Trackable;
import cgeo.geocaching.TrackableLog;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgImage;
-import cgeo.geocaching.cgTrackable;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.Image;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
@@ -30,6 +31,7 @@ import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.LazyInitializedList;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -43,12 +45,7 @@ import org.json.JSONObject;
import android.net.Uri;
import android.text.Html;
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.StrikethroughSpan;
-import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -58,7 +55,6 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
-import java.util.regex.Matcher;
public abstract class GCParser {
private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009
@@ -71,8 +67,6 @@ public abstract class GCParser {
}
final List<String> cids = new ArrayList<String>();
- String recaptchaChallenge = null;
- String recaptchaText = null;
String page = pageContent;
final SearchResult searchResult = new SearchResult();
@@ -81,6 +75,7 @@ public abstract class GCParser {
// recaptcha
AbstractSearchThread thread = AbstractSearchThread.getCurrentInstance();
+ String recaptchaChallenge = null;
if (showCaptcha) {
String recaptchaJsParam = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null);
@@ -124,7 +119,7 @@ public abstract class GCParser {
final int rows_count = rows.length;
for (int z = 1; z < rows_count; z++) {
- final cgCache cache = new cgCache();
+ final Geocache cache = new Geocache();
String row = rows[z];
// check for cache type presence
@@ -133,7 +128,7 @@ public abstract class GCParser {
}
try {
- final Matcher matcherGuidAndDisabled = GCConstants.PATTERN_SEARCH_GUIDANDDISABLED.matcher(row);
+ final MatcherWrapper matcherGuidAndDisabled = new MatcherWrapper(GCConstants.PATTERN_SEARCH_GUIDANDDISABLED, row);
while (matcherGuidAndDisabled.find()) {
if (matcherGuidAndDisabled.groupCount() > 0) {
@@ -163,29 +158,32 @@ public abstract class GCParser {
continue;
}
- String inventoryPre = null;
-
- cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true).toUpperCase());
+ cache.setGeocode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_GEOCODE, true, 1, cache.getGeocode(), true));
// cache type
cache.setType(CacheType.getByPattern(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_TYPE, true, 1, null, true)));
// cache direction - image
if (Settings.getLoadDirImg()) {
- cache.setDirectionImg(URLDecoder.decode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION, true, 1, cache.getDirectionImg(), true)));
+ cache.setDirectionImg(Network.decode(BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_DIRECTION, true, 1, cache.getDirectionImg(), true)));
}
// cache inventory
- final Matcher matcherTbs = GCConstants.PATTERN_SEARCH_TRACKABLES.matcher(row);
+ final MatcherWrapper matcherTbs = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLES, row);
+ String inventoryPre = null;
while (matcherTbs.find()) {
if (matcherTbs.groupCount() > 0) {
- cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1)));
+ try {
+ cache.setInventoryItems(Integer.parseInt(matcherTbs.group(1)));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing trackables count", e);
+ }
inventoryPre = matcherTbs.group(2);
}
}
if (StringUtils.isNotBlank(inventoryPre)) {
- final Matcher matcherTbsInside = GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE.matcher(inventoryPre);
+ final MatcherWrapper matcherTbsInside = new MatcherWrapper(GCConstants.PATTERN_SEARCH_TRACKABLESINSIDE, inventoryPre);
while (matcherTbsInside.find()) {
if (matcherTbsInside.groupCount() == 2 &&
matcherTbsInside.group(2) != null &&
@@ -202,9 +200,6 @@ public abstract class GCParser {
// found it
cache.setFound(row.contains("/images/icons/16/found.png"));
- // own it
- cache.setOwn(row.contains("/images/icons/16/placed.png"));
-
// id
String result = BaseUtils.getMatch(row, GCConstants.PATTERN_SEARCH_ID, null);
if (null != result) {
@@ -222,16 +217,6 @@ public abstract class GCParser {
Log.w("GCParser.parseSearch: Failed to parse favourite count");
}
- if (cache.getNameSp() == null) {
- cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName()));
- if (cache.isDisabled() || cache.isArchived()) { // strike
- cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- if (cache.isArchived()) {
- cache.getNameSp().setSpan(new ForegroundColorSpan(cgeoapplication.getInstance().getResources().getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- }
-
searchResult.addCache(cache);
}
@@ -245,6 +230,7 @@ public abstract class GCParser {
Log.w("GCParser.parseSearch: Failed to parse cache count");
}
+ String recaptchaText = null;
if (thread != null && recaptchaChallenge != null) {
if (thread.getText() == null) {
thread.waitForUser();
@@ -253,7 +239,7 @@ public abstract class GCParser {
recaptchaText = thread.getText();
}
- if (cids.size() > 0 && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) {
+ if (!cids.isEmpty() && (Settings.isPremiumMember() || showCaptcha) && (recaptchaChallenge == null || StringUtils.isNotBlank(recaptchaText))) {
Log.i("Trying to get .loc for " + cids.size() + " caches");
try {
@@ -295,14 +281,14 @@ public abstract class GCParser {
LocParser.parseLoc(searchResult, coordinates);
} catch (Exception e) {
- Log.e("GCParser.parseSearch.CIDs: " + e.toString());
+ Log.e("GCParser.parseSearch.CIDs", e);
}
}
// get direction images
if (Settings.getLoadDirImg()) {
- final Set<cgCache> caches = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- for (cgCache cache : caches) {
+ final Set<Geocache> caches = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ for (Geocache cache : caches) {
if (cache.getCoords() == null && StringUtils.isNotEmpty(cache.getDirectionImg())) {
DirectionImage.getDrawable(cache.getGeocode(), cache.getDirectionImg());
}
@@ -315,18 +301,16 @@ public abstract class GCParser {
static SearchResult parseCache(final String page, final CancellableHandler handler) {
final SearchResult searchResult = parseCacheFromText(page, handler);
if (searchResult != null && !searchResult.getGeocodes().isEmpty()) {
- final cgCache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = searchResult.getFirstCacheFromResult(LoadFlags.LOAD_CACHE_OR_DB);
getExtraOnlineInfo(cache, page, handler);
- cache.setUpdated(System.currentTimeMillis());
- cache.setDetailedUpdate(cache.getUpdated());
- cache.setDetailed(true);
+ cache.setDetailedUpdatedNow();
if (CancellableHandler.isCancelled(handler)) {
return null;
}
// save full detailed caches
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_cache);
- cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
// update progress message so user knows we're still working. This is more of a place holder than
// actual indication of what the program is doing
@@ -345,7 +329,7 @@ public abstract class GCParser {
final SearchResult searchResult = new SearchResult();
- if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER)) {
+ if (page.contains(GCConstants.STRING_UNPUBLISHED_OTHER) || page.contains(GCConstants.STRING_UNPUBLISHED_OWNER) || page.contains(GCConstants.STRING_UNPUBLISHED_FROM_SEARCH)) {
searchResult.setError(StatusCode.UNPUBLISHED_CACHE);
return searchResult;
}
@@ -361,7 +345,7 @@ public abstract class GCParser {
return searchResult;
}
- final cgCache cache = new cgCache();
+ final Geocache cache = new Geocache();
cache.setDisabled(page.contains(GCConstants.STRING_DISABLED));
cache.setArchived(page.contains(GCConstants.STRING_ARCHIVED));
@@ -383,9 +367,9 @@ public abstract class GCParser {
cache.setName(cacheName);
// owner real name
- cache.setOwnerUserId(URLDecoder.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
+ cache.setOwnerUserId(Network.decode(BaseUtils.getMatch(page, GCConstants.PATTERN_OWNER_USERID, true, cache.getOwnerUserId())));
- cache.setOwn(StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getUsername()));
+ cache.setUserModifiedCoords(false);
String tableInside = page;
@@ -401,13 +385,21 @@ public abstract class GCParser {
// cache terrain
String result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_TERRAIN, true, null);
if (result != null) {
- cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ try {
+ cache.setTerrain(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing terrain value", e);
+ }
}
// cache difficulty
result = BaseUtils.getMatch(tableInside, GCConstants.PATTERN_DIFFICULTY, true, null);
if (result != null) {
- cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ try {
+ cache.setDifficulty(Float.parseFloat(StringUtils.replaceChars(result, '_', '.')));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing difficulty value", e);
+ }
}
// owner
@@ -432,10 +424,14 @@ public abstract class GCParser {
}
// favourite
- cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
+ try {
+ cache.setFavoritePoints(Integer.parseInt(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_FAVORITECOUNT, true, "0")));
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing favourite count", e);
+ }
// cache size
- cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id).toLowerCase()));
+ cache.setSize(CacheSize.getById(BaseUtils.getMatch(tableInside, GCConstants.PATTERN_SIZE, true, CacheSize.NOT_CHOSEN.id)));
}
// cache found
@@ -465,7 +461,7 @@ public abstract class GCParser {
cache.setCoords(new Geopoint(cache.getLatlon()));
cache.setReliableLatLon(true);
} catch (Geopoint.GeopointException e) {
- Log.w("GCParser.parseCache: Failed to parse cache coordinates: " + e.toString());
+ Log.w("GCParser.parseCache: Failed to parse cache coordinates", e);
}
}
@@ -497,21 +493,21 @@ public abstract class GCParser {
try {
final String attributesPre = BaseUtils.getMatch(page, GCConstants.PATTERN_ATTRIBUTES, true, null);
if (null != attributesPre) {
- final Matcher matcherAttributesInside = GCConstants.PATTERN_ATTRIBUTESINSIDE.matcher(attributesPre);
+ final MatcherWrapper matcherAttributesInside = new MatcherWrapper(GCConstants.PATTERN_ATTRIBUTESINSIDE, attributesPre);
final ArrayList<String> attributes = new ArrayList<String>();
while (matcherAttributesInside.find()) {
if (matcherAttributesInside.groupCount() > 1 && !matcherAttributesInside.group(2).equalsIgnoreCase("blank")) {
// by default, use the tooltip of the attribute
- String attribute = matcherAttributesInside.group(2).toLowerCase();
+ String attribute = matcherAttributesInside.group(2).toLowerCase(Locale.US);
// if the image name can be recognized, use the image name as attribute
- String imageName = matcherAttributesInside.group(1).trim();
- if (imageName.length() > 0) {
+ final String imageName = matcherAttributesInside.group(1).trim();
+ if (StringUtils.isNotEmpty(imageName)) {
int start = imageName.lastIndexOf('/');
int end = imageName.lastIndexOf('.');
if (start >= 0 && end >= 0) {
- attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase();
+ attribute = imageName.substring(start + 1, end).replace('-', '_').toLowerCase(Locale.US);
}
}
attributes.add(attribute);
@@ -531,26 +527,22 @@ public abstract class GCParser {
}
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_spoilers);
- final Matcher matcherSpoilersInside = GCConstants.PATTERN_SPOILER_IMAGE.matcher(page);
+ final MatcherWrapper matcherSpoilersInside = new MatcherWrapper(GCConstants.PATTERN_SPOILER_IMAGE, page);
while (matcherSpoilersInside.find()) {
// the original spoiler URL (include .../display/... contains a low-resolution image
// if we shorten the URL we get the original-resolution image
- //
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- String url = new String(matcherSpoilersInside.group(1).replace("/display", ""));
+ String url = matcherSpoilersInside.group(1).replace("/display", "");
String title = null;
if (matcherSpoilersInside.group(3) != null) {
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- title = new String(matcherSpoilersInside.group(3));
+ title = matcherSpoilersInside.group(3);
}
String description = null;
if (matcherSpoilersInside.group(4) != null) {
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- description = new String(matcherSpoilersInside.group(4));
+ description = matcherSpoilersInside.group(4);
}
- cache.addSpoiler(new cgImage(url, title, description));
+ cache.addSpoiler(new Image(url, title, description));
}
} catch (Exception e) {
// failed to parse cache spoilers
@@ -561,25 +553,23 @@ public abstract class GCParser {
try {
cache.setInventoryItems(0);
- final Matcher matcherInventory = GCConstants.PATTERN_INVENTORY.matcher(page);
+ final MatcherWrapper matcherInventory = new MatcherWrapper(GCConstants.PATTERN_INVENTORY, page);
if (matcherInventory.find()) {
if (cache.getInventory() == null) {
- cache.setInventory(new ArrayList<cgTrackable>());
+ cache.setInventory(new ArrayList<Trackable>());
}
if (matcherInventory.groupCount() > 1) {
final String inventoryPre = matcherInventory.group(2);
if (StringUtils.isNotBlank(inventoryPre)) {
- final Matcher matcherInventoryInside = GCConstants.PATTERN_INVENTORYINSIDE.matcher(inventoryPre);
+ final MatcherWrapper matcherInventoryInside = new MatcherWrapper(GCConstants.PATTERN_INVENTORYINSIDE, inventoryPre);
while (matcherInventoryInside.find()) {
if (matcherInventoryInside.groupCount() > 0) {
- final cgTrackable inventoryItem = new cgTrackable();
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- inventoryItem.setGuid(new String(matcherInventoryInside.group(1)));
- // Create a new string to avoid referencing the whole page though the matcher (@see BaseUtils.getMatch())
- inventoryItem.setName(new String(matcherInventoryInside.group(2)));
+ final Trackable inventoryItem = new Trackable();
+ inventoryItem.setGuid(matcherInventoryInside.group(1));
+ inventoryItem.setName(matcherInventoryInside.group(2));
cache.getInventory().add(inventoryItem);
cache.setInventoryItems(cache.getInventoryItems() + 1);
@@ -594,14 +584,12 @@ public abstract class GCParser {
}
// cache logs counts
- try
- {
+ try {
final String countlogs = BaseUtils.getMatch(page, GCConstants.PATTERN_COUNTLOGS, true, null);
if (null != countlogs) {
- final Matcher matcherLog = GCConstants.PATTERN_COUNTLOG.matcher(countlogs);
+ final MatcherWrapper matcherLog = new MatcherWrapper(GCConstants.PATTERN_COUNTLOG, countlogs);
- while (matcherLog.find())
- {
+ while (matcherLog.find()) {
String typeStr = matcherLog.group(1);
String countStr = matcherLog.group(2).replaceAll("[.,]", "");
@@ -612,21 +600,20 @@ public abstract class GCParser {
}
}
}
- } catch (Exception e)
- {
+ } catch (Exception e) {
// failed to parse logs
Log.w("GCParser.parseCache: Failed to parse cache log count");
}
// waypoints - reset collection
- cache.setWaypoints(Collections.<cgWaypoint> emptyList(), false);
+ cache.setWaypoints(Collections.<Waypoint> emptyList(), false);
// add waypoint for original coordinates in case of user-modified listing-coordinates
try {
final String originalCoords = BaseUtils.getMatch(page, GCConstants.PATTERN_LATLON_ORIG, false, null);
if (null != originalCoords) {
- final cgWaypoint waypoint = new cgWaypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.WAYPOINT, false);
+ final Waypoint waypoint = new Waypoint(cgeoapplication.getInstance().getString(R.string.cache_coordinates_original), WaypointType.ORIGINAL, false);
waypoint.setCoords(new Geopoint(originalCoords));
cache.addOrChangeWaypoint(waypoint, false);
cache.setUserModifiedCoords(true);
@@ -634,10 +621,7 @@ public abstract class GCParser {
} catch (Geopoint.GeopointException e) {
}
- int wpBegin;
- int wpEnd;
-
- wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
+ int wpBegin = page.indexOf("<table class=\"Table\" id=\"ctl00_ContentBody_Waypoints\">");
if (wpBegin != -1) { // parse waypoints
if (CancellableHandler.isCancelled(handler)) {
return null;
@@ -646,7 +630,7 @@ public abstract class GCParser {
String wpList = page.substring(wpBegin);
- wpEnd = wpList.indexOf("</p>");
+ int wpEnd = wpList.indexOf("</p>");
if (wpEnd > -1 && wpEnd <= wpList.length()) {
wpList = wpList.substring(0, wpEnd);
}
@@ -663,9 +647,8 @@ public abstract class GCParser {
final String[] wpItems = wpList.split("<tr");
- String[] wp;
for (int j = 1; j < wpItems.length; j++) {
- wp = wpItems[j].split("<td");
+ String[] wp = wpItems[j].split("<td");
// waypoint name
// res is null during the unit tests
@@ -674,7 +657,7 @@ public abstract class GCParser {
// waypoint type
final String resulttype = BaseUtils.getMatch(wp[3], GCConstants.PATTERN_WPTYPE, null);
- final cgWaypoint waypoint = new cgWaypoint(name, WaypointType.findById(resulttype), false);
+ final Waypoint waypoint = new Waypoint(name, WaypointType.findById(resulttype), false);
// waypoint prefix
waypoint.setPrefix(BaseUtils.getMatch(wp[4], GCConstants.PATTERN_WPPREFIXORLOOKUPORLATLON, true, 2, waypoint.getPrefix(), false));
@@ -756,12 +739,12 @@ public abstract class GCParser {
final SearchResult searchResult = parseSearch(url, page, showCaptcha);
if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) {
- Log.e("GCParser.searchByNextPage: No cache parsed");
+ Log.w("GCParser.searchByNextPage: No cache parsed");
return search;
}
// search results don't need to be filtered so load GCVote ratings here
- GCVote.loadRatings(new ArrayList<cgCache>(searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB)));
+ GCVote.loadRatings(new ArrayList<Geocache>(searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB)));
// save to application
search.setError(searchResult.getError());
@@ -896,13 +879,13 @@ public abstract class GCParser {
return null;
}
- public static cgTrackable searchTrackable(final String geocode, final String guid, final String id) {
+ public static Trackable searchTrackable(final String geocode, final String guid, final String id) {
if (StringUtils.isBlank(geocode) && StringUtils.isBlank(guid) && StringUtils.isBlank(id)) {
Log.w("GCParser.searchTrackable: No geocode nor guid nor id given");
return null;
}
- cgTrackable trackable = new cgTrackable();
+ Trackable trackable = new Trackable();
final Parameters params = new Parameters();
if (StringUtils.isNotBlank(geocode)) {
@@ -923,7 +906,7 @@ public abstract class GCParser {
trackable = parseTrackable(page, geocode);
if (trackable == null) {
- Log.e("GCParser.searchTrackable: No trackable parsed");
+ Log.w("GCParser.searchTrackable: No trackable parsed");
return null;
}
@@ -1004,7 +987,7 @@ public abstract class GCParser {
// maintenance, archived needs to be confirmed
- final Matcher matcher = GCConstants.PATTERN_MAINTENANCE.matcher(page);
+ final MatcherWrapper matcher = new MatcherWrapper(GCConstants.PATTERN_MAINTENANCE, page);
try {
if (matcher.find() && matcher.groupCount() > 0) {
@@ -1048,17 +1031,17 @@ public abstract class GCParser {
page = Network.getResponseData(Network.postRequest(uri, params));
}
} catch (Exception e) {
- Log.e("GCParser.postLog.confim: " + e.toString());
+ Log.e("GCParser.postLog.confim", e);
}
try {
- final Matcher matcherOk = GCConstants.PATTERN_OK1.matcher(page);
+ final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK1, page);
if (matcherOk.find()) {
Log.i("Log successfully posted to cache #" + cacheid);
if (geocode != null) {
- cgeoapplication.getInstance().saveVisitDate(geocode);
+ cgData.saveVisitDate(geocode);
}
Login.getLoginStatus(page);
@@ -1069,7 +1052,7 @@ public abstract class GCParser {
return StatusCode.NO_ERROR;
}
} catch (Exception e) {
- Log.e("GCParser.postLog.check: " + e.toString());
+ Log.e("GCParser.postLog.check", e);
}
Log.e("GCParser.postLog: Failed to post log because of unknown error");
@@ -1122,13 +1105,13 @@ public abstract class GCParser {
try {
- final Matcher matcherOk = GCConstants.PATTERN_OK2.matcher(page);
+ final MatcherWrapper matcherOk = new MatcherWrapper(GCConstants.PATTERN_OK2, page);
if (matcherOk.find()) {
Log.i("Log successfully posted to trackable #" + trackingCode);
return StatusCode.NO_ERROR;
}
} catch (Exception e) {
- Log.e("GCParser.postLogTrackable.check: " + e.toString());
+ Log.e("GCParser.postLogTrackable.check", e);
}
Log.e("GCParser.postLogTrackable: Failed to post log because of unknown error");
@@ -1142,7 +1125,7 @@ public abstract class GCParser {
* the cache to add
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean addToWatchlist(final cgCache cache) {
+ static boolean addToWatchlist(final Geocache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?w=" + cache.getCacheId();
String page = Login.postRequestLogged(uri, null);
@@ -1168,7 +1151,7 @@ public abstract class GCParser {
* the cache to remove
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean removeFromWatchlist(final cgCache cache) {
+ static boolean removeFromWatchlist(final Geocache cache) {
final String uri = "http://www.geocaching.com/my/watchlist.aspx?ds=1&action=rem&id=" + cache.getCacheId();
String page = Login.postRequestLogged(uri, null);
@@ -1211,15 +1194,17 @@ public abstract class GCParser {
/**
* Adds the cache to the favorites of the user.
*
+ * This must not be called from the UI thread.
+ *
* @param cache
* the cache to add
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean addToFavorites(final cgCache cache) {
+ static boolean addToFavorites(final Geocache cache) {
return changeFavorite(cache, true);
}
- private static boolean changeFavorite(final cgCache cache, final boolean add) {
+ private static boolean changeFavorite(final Geocache cache, final boolean add) {
final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
if (StringUtils.isEmpty(userToken)) {
@@ -1241,26 +1226,26 @@ public abstract class GCParser {
}
/**
- * Removes the cache from the Favorites
+ * Removes the cache from the favorites.
+ *
+ * This must not be called from the UI thread.
*
* @param cache
* the cache to remove
* @return <code>false</code> if an error occurred, <code>true</code> otherwise
*/
- static boolean removeFromFavorites(final cgCache cache) {
+ static boolean removeFromFavorites(final Geocache cache) {
return changeFavorite(cache, false);
}
/**
- * Parse a trackable HTML description into a cgTrackable object
+ * Parse a trackable HTML description into a Trackable object
*
* @param page
* the HTML page to parse, already processed through {@link BaseUtils#replaceWhitespace}
- * @param app
- * if not null, the application to use to save the trackable
* @return the parsed trackable, or null if none could be parsed
*/
- static cgTrackable parseTrackable(final String page, final String possibleTrackingcode) {
+ static Trackable parseTrackable(final String page, final String possibleTrackingcode) {
if (StringUtils.isBlank(page)) {
Log.e("GCParser.parseTrackable: No page given");
return null;
@@ -1270,10 +1255,10 @@ public abstract class GCParser {
return null;
}
- final cgTrackable trackable = new cgTrackable();
+ final Trackable trackable = new Trackable();
// trackable geocode
- trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()).toUpperCase());
+ trackable.setGeocode(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GEOCODE, true, trackable.getGeocode()));
// trackable id
trackable.setGuid(BaseUtils.getMatch(page, GCConstants.PATTERN_TRACKABLE_GUID, true, trackable.getGuid()));
@@ -1291,7 +1276,7 @@ public abstract class GCParser {
// trackable owner name
try {
- final Matcher matcherOwner = GCConstants.PATTERN_TRACKABLE_OWNER.matcher(page);
+ final MatcherWrapper matcherOwner = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_OWNER, page);
if (matcherOwner.find() && matcherOwner.groupCount() > 0) {
trackable.setOwnerGuid(matcherOwner.group(1));
trackable.setOwner(matcherOwner.group(2).trim());
@@ -1306,26 +1291,26 @@ public abstract class GCParser {
// trackable spotted
try {
- final Matcher matcherSpottedCache = GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE.matcher(page);
+ final MatcherWrapper matcherSpottedCache = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDCACHE, page);
if (matcherSpottedCache.find() && matcherSpottedCache.groupCount() > 0) {
trackable.setSpottedGuid(matcherSpottedCache.group(1));
trackable.setSpottedName(matcherSpottedCache.group(2).trim());
- trackable.setSpottedType(cgTrackable.SPOTTED_CACHE);
+ trackable.setSpottedType(Trackable.SPOTTED_CACHE);
}
- final Matcher matcherSpottedUser = GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER.matcher(page);
+ final MatcherWrapper matcherSpottedUser = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_SPOTTEDUSER, page);
if (matcherSpottedUser.find() && matcherSpottedUser.groupCount() > 0) {
trackable.setSpottedGuid(matcherSpottedUser.group(1));
trackable.setSpottedName(matcherSpottedUser.group(2).trim());
- trackable.setSpottedType(cgTrackable.SPOTTED_USER);
+ trackable.setSpottedType(Trackable.SPOTTED_USER);
}
if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDUNKNOWN)) {
- trackable.setSpottedType(cgTrackable.SPOTTED_UNKNOWN);
+ trackable.setSpottedType(Trackable.SPOTTED_UNKNOWN);
}
if (BaseUtils.matches(page, GCConstants.PATTERN_TRACKABLE_SPOTTEDOWNER)) {
- trackable.setSpottedType(cgTrackable.SPOTTED_OWNER);
+ trackable.setSpottedType(Trackable.SPOTTED_OWNER);
}
} catch (Exception e) {
// failed to parse trackable last known place
@@ -1356,7 +1341,7 @@ public abstract class GCParser {
// trackable details & image
try {
- final Matcher matcherDetailsImage = GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE.matcher(page);
+ final MatcherWrapper matcherDetailsImage = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_DETAILSIMAGE, page);
if (matcherDetailsImage.find() && matcherDetailsImage.groupCount() > 0) {
final String image = StringUtils.trim(matcherDetailsImage.group(3));
final String details = StringUtils.trim(matcherDetailsImage.group(4));
@@ -1375,7 +1360,7 @@ public abstract class GCParser {
// trackable logs
try {
- final Matcher matcherLogs = GCConstants.PATTERN_TRACKABLE_LOG.matcher(page);
+ final MatcherWrapper matcherLogs = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG, page);
/*
* 1. Type (image)
* 2. Date
@@ -1404,13 +1389,14 @@ public abstract class GCParser {
}
// Apply the pattern for images in a trackable log entry against each full log (group(0))
- final Matcher matcherLogImages = GCConstants.PATTERN_TRACKABLE_LOG_IMAGES.matcher(matcherLogs.group(0));
+ final String logEntry = matcherLogs.group(0);
+ final MatcherWrapper matcherLogImages = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE_LOG_IMAGES, logEntry);
/*
* 1. Image URL
* 2. Image title
*/
while (matcherLogImages.find()) {
- final cgImage logImage = new cgImage(matcherLogImages.group(1), matcherLogImages.group(2));
+ final Image logImage = new Image(matcherLogImages.group(1), matcherLogImages.group(2));
logDone.addLogImage(logImage);
}
@@ -1418,7 +1404,7 @@ public abstract class GCParser {
}
} catch (Exception e) {
// failed to parse logs
- Log.w("GCParser.parseCache: Failed to parse cache logs" + e.toString());
+ Log.w("GCParser.parseCache: Failed to parse cache logs", e);
}
// tracking code
@@ -1427,7 +1413,7 @@ public abstract class GCParser {
}
if (cgeoapplication.getInstance() != null) {
- cgeoapplication.getInstance().saveTrackable(trackable);
+ cgData.saveTrackable(trackable);
}
return trackable;
@@ -1450,11 +1436,11 @@ public abstract class GCParser {
* @param friends
* retrieve friend logs
*/
- private static List<LogEntry> loadLogsFromDetails(final String page, final cgCache cache, final boolean friends, final boolean getDataFromPage) {
+ private static List<LogEntry> loadLogsFromDetails(final String page, final Geocache cache, final boolean friends, final boolean getDataFromPage) {
String rawResponse;
if (!getDataFromPage) {
- final Matcher userTokenMatcher = GCConstants.PATTERN_USERTOKEN.matcher(page);
+ final MatcherWrapper userTokenMatcher = new MatcherWrapper(GCConstants.PATTERN_USERTOKEN, page);
if (!userTokenMatcher.find()) {
Log.e("GCParser.loadLogsFromDetails: unable to extract userToken");
return null;
@@ -1532,7 +1518,7 @@ public abstract class GCParser {
final JSONObject image = images.getJSONObject(i);
String url = "http://img.geocaching.com/cache/log/" + image.getString("FileName");
String title = image.getString("Name");
- final cgImage logImage = new cgImage(url, title);
+ final Image logImage = new Image(url, title);
logDone.addLogImage(logImage);
}
@@ -1553,7 +1539,7 @@ public abstract class GCParser {
final List<LogType> types = new ArrayList<LogType>();
- final Matcher typeBoxMatcher = GCConstants.PATTERN_TYPEBOX.matcher(page);
+ final MatcherWrapper typeBoxMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPEBOX, page);
String typesText = null;
if (typeBoxMatcher.find()) {
if (typeBoxMatcher.groupCount() > 0) {
@@ -1563,13 +1549,16 @@ public abstract class GCParser {
if (typesText != null) {
- final Matcher typeMatcher = GCConstants.PATTERN_TYPE2.matcher(typesText);
+ final MatcherWrapper typeMatcher = new MatcherWrapper(GCConstants.PATTERN_TYPE2, typesText);
while (typeMatcher.find()) {
if (typeMatcher.groupCount() > 1) {
- final int type = Integer.parseInt(typeMatcher.group(2));
-
- if (type > 0) {
- types.add(LogType.getById(type));
+ try {
+ int type = Integer.parseInt(typeMatcher.group(2));
+ if (type > 0) {
+ types.add(LogType.getById(type));
+ }
+ } catch (NumberFormatException e) {
+ Log.e("Error parsing log types", e);
}
}
}
@@ -1598,7 +1587,7 @@ public abstract class GCParser {
final List<TrackableLog> trackableLogs = new ArrayList<TrackableLog>();
- final Matcher trackableMatcher = GCConstants.PATTERN_TRACKABLE.matcher(page);
+ final MatcherWrapper trackableMatcher = new MatcherWrapper(GCConstants.PATTERN_TRACKABLE, page);
while (trackableMatcher.find()) {
if (trackableMatcher.groupCount() > 0) {
@@ -1634,7 +1623,7 @@ public abstract class GCParser {
params.put("tx", cacheType.guid);
}
- private static void getExtraOnlineInfo(final cgCache cache, final String page, final CancellableHandler handler) {
+ private static void getExtraOnlineInfo(final Geocache cache, final String page, final CancellableHandler handler) {
if (CancellableHandler.isCancelled(handler)) {
return;
}
@@ -1642,7 +1631,7 @@ public abstract class GCParser {
//cache.setLogs(loadLogsFromDetails(page, cache, false));
if (Settings.isFriendLogsWanted()) {
CancellableHandler.sendLoadProgressDetail(handler, R.string.cache_dialog_loading_details_status_logs);
- LazyInitializedList<LogEntry> allLogs = cache.getLogs();
+ List<LogEntry> allLogs = cache.getLogs();
List<LogEntry> friendLogs = loadLogsFromDetails(page, cache, true, false);
if (friendLogs != null) {
for (LogEntry log : friendLogs) {
@@ -1679,4 +1668,48 @@ public abstract class GCParser {
}
}
+ public static boolean uploadModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ return editModifiedCoordinates(cache, wpt);
+ }
+
+ public static boolean deleteModifiedCoordinates(Geocache cache) {
+ return editModifiedCoordinates(cache, null);
+ }
+
+ public static boolean editModifiedCoordinates(Geocache cache, Geopoint wpt) {
+ final String page = requestHtmlPage(cache.getGeocode(), null, "n", "0");
+ final String userToken = BaseUtils.getMatch(page, GCConstants.PATTERN_USERTOKEN, "");
+ if (StringUtils.isEmpty(userToken)) {
+ return false;
+ }
+
+ try {
+ JSONObject jo;
+ if (wpt != null) {
+ jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken)
+ .put("data", new JSONObject()
+ .put("lat", wpt.getLatitudeE6() / 1E6)
+ .put("lng", wpt.getLongitudeE6() / 1E6))));
+ } else {
+ jo = new JSONObject().put("dto", (new JSONObject().put("ut", userToken)));
+ }
+
+ final String uriSuffix = wpt != null ? "SetUserCoordinate" : "ResetUserCoordinate";
+
+ final String uriPrefix = "http://www.geocaching.com/seek/cache_details.aspx/";
+ HttpResponse response = Network.postJsonRequest(uriPrefix + uriSuffix, jo);
+ Log.i("Sending to " + uriPrefix + uriSuffix + " :" + jo.toString());
+
+ if (response != null && response.getStatusLine().getStatusCode() == 200) {
+ Log.i("GCParser.editModifiedCoordinates - edited on GC.com");
+ return true;
+ }
+
+ } catch (JSONException e) {
+ Log.e("Unknown exception with json wrap code", e);
+ }
+ Log.e("GCParser.deleteModifiedCoordinates - cannot delete modified coords");
+ return false;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java
index 1083a89..eba9301 100644
--- a/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java
+++ b/main/src/cgeo/geocaching/connector/gc/GCSmiliesProvider.java
@@ -26,7 +26,7 @@ public class GCSmiliesProvider {
public final String text;
- private Smiley(final String text) {
+ Smiley(final String text) {
this.text = text;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
index 50c0a6a..98bd28a 100644
--- a/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
+++ b/main/src/cgeo/geocaching/connector/gc/IconDecoder.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector.gc;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheType;
import android.graphics.Bitmap;
@@ -10,153 +11,496 @@ import android.graphics.Bitmap;
*
*/
public abstract class IconDecoder {
+ private static final int CT_TRADITIONAL = 0;
+ private static final int CT_MULTI = 1;
+ private static final int CT_MYSTERY = 2;
+ private static final int CT_EVENT = 3;
+ private static final int CT_EARTH = 4;
+ private static final int CT_FOUND = 5;
+ private static final int CT_OWN = 6;
+ private static final int CT_MEGAEVENT = 7;
+ private static final int CT_CITO = 8;
+ private static final int CT_WEBCAM = 9;
+ private static final int CT_WHEREIGO = 10;
+ private static final int CT_VIRTUAL = 11;
+ private static final int CT_LETTERBOX = 12;
- public static void parseMapPNG(final cgCache cache, Bitmap bitmap, UTFGridPosition xy, int zoomlevel) {
- if (zoomlevel >= 14) {
- parseMapPNG14(cache, bitmap, xy);
- } else {
- parseMapPNG13(cache, bitmap, xy);
+ public static boolean parseMapPNG(final Geocache cache, Bitmap bitmap, UTFGridPosition xy, int zoomlevel) {
+ final int topX = xy.getX() * 4;
+ final int topY = xy.getY() * 4;
+ final int bitmapWidth = bitmap.getWidth();
+ final int bitmapHeight = bitmap.getHeight();
+
+ if ((topX < 0) || (topY < 0) || (topX + 4 > bitmapWidth) || (topY + 4 > bitmapHeight)) {
+ return false; //out of image position
}
- }
- private static final int[] OFFSET_X = new int[] { 0, -1, -1, 0, 1, 1, 1, 0, -1, -2, -2, -2, -2, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2 };
- private static final int[] OFFSET_Y = new int[] { 0, 0, 1, 1, 1, 0, -1, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2 };
+ int numberOfDetections = 7; //for level 12 and 13;
+ if (zoomlevel < 12) {
+ numberOfDetections = 5;
+ }
+ if (zoomlevel > 13) {
+ numberOfDetections = 13;
+ }
- /**
- * The icon decoder walks a spiral around the center pixel position of the cache
- * and searches for characteristic colors.
- *
- * @param cache
- * @param bitmap
- * @param xy
- */
- private static void parseMapPNG13(final cgCache cache, Bitmap bitmap, UTFGridPosition xy) {
- final int xCenter = xy.getX() * 4 + 2;
- final int yCenter = xy.getY() * 4 + 2;
- final int bitmapWidth = bitmap.getWidth();
- final int bitmapHeight = bitmap.getHeight();
+ int[] pngType = new int[numberOfDetections];
+ for (int x = topX; x < topX + 4; x++) {
+ for (int y = topY; y < topY + 4; y++) {
+ int color = bitmap.getPixel(x, y);
- int countMulti = 0;
- int countFound = 0;
+ if ((color >>> 24) != 255) {
+ continue; //transparent pixels (or semi_transparent) are only shadows of border
+ }
- for (int i = 0; i < OFFSET_X.length; i++) {
+ int r = (color & 0xFF0000) >> 16;
+ int g = (color & 0xFF00) >> 8;
+ int b = color & 0xFF;
- // assert that we are still in the tile
- final int x = xCenter + OFFSET_X[i];
- if (x < 0 || x >= bitmapWidth) {
- continue;
- }
+ if (isPixelDuplicated(r, g, b, zoomlevel)) {
+ continue;
+ }
- final int y = yCenter + OFFSET_Y[i];
- if (y < 0 || y >= bitmapHeight) {
- continue;
+ int type;
+ if (zoomlevel < 12) {
+ type = getCacheTypeFromPixel11(r, g, b);
+ } else {
+ if (zoomlevel > 13) {
+ type = getCacheTypeFromPixel14(r, g, b);
+ } else {
+ type = getCacheTypeFromPixel13(r, g, b);
+ }
+ }
+ pngType[type]++;
}
+ }
- int color = bitmap.getPixel(x, y) & 0x00FFFFFF;
+ int type = -1;
+ int count = 0;
- // transparent pixels are not interesting
- if (color == 0) {
- continue;
+ for (int x = 0; x < pngType.length; x++)
+ {
+ if (pngType[x] > count) {
+ count = pngType[x];
+ type = x;
}
+ }
- int red = (color & 0xFF0000) >> 16;
- int green = (color & 0xFF00) >> 8;
- int blue = color & 0xFF;
+ if (count > 1) { // 2 pixels need to detect same type and we say good to go
+ switch (type) {
+ case CT_TRADITIONAL:
+ cache.setType(CacheType.TRADITIONAL);
+ return true;
+ case CT_MULTI:
+ cache.setType(CacheType.MULTI);
+ return true;
+ case CT_MYSTERY:
+ cache.setType(CacheType.MYSTERY);
+ return true;
+ case CT_EVENT:
+ cache.setType(CacheType.EVENT);
+ return true;
+ case CT_EARTH:
+ cache.setType(CacheType.EARTH);
+ return true;
+ case CT_FOUND:
+ cache.setFound(true);
+ return true;
+ case CT_OWN:
+ cache.setOwnerUserId(Settings.getUsername());
+ return true;
+ case CT_MEGAEVENT:
+ cache.setType(CacheType.MEGA_EVENT);
+ return true;
+ case CT_CITO:
+ cache.setType(CacheType.CITO);
+ return true;
+ case CT_WEBCAM:
+ cache.setType(CacheType.WEBCAM);
+ return true;
+ case CT_WHEREIGO:
+ cache.setType(CacheType.WHERIGO);
+ return true;
+ case CT_VIRTUAL:
+ cache.setType(CacheType.VIRTUAL);
+ return true;
+ case CT_LETTERBOX:
+ cache.setType(CacheType.LETTERBOX);
+ return true;
+ }
+ }
+ return false;
+ }
- // these are quite sure, so one pixel is enough for matching
- if (green > 0x80 && green > red && green > blue) {
- cache.setType(CacheType.TRADITIONAL);
- return;
+ /**
+ * A method that returns true if pixel color appears on more then one cache type and shall be excluded from parsing
+ *
+ * @param r
+ * red value
+ * @param g
+ * green value
+ * @param b
+ * blue value
+ * @param zoomlevel
+ * zoom level of map
+ * @return true if parsing should not be performed
+ */
+ private static boolean isPixelDuplicated(int r, int g, int b, int zoomlevel) {
+ if (zoomlevel < 12) {
+ if (((r == g) && (g == b)) || ((r == 233) && (g == 233) && (b == 234))) {
+ return true;
}
- if (blue > 0x80 && blue > red && blue > green) {
- cache.setType(CacheType.MYSTERY);
- return;
+ return false;
+ }
+ if (zoomlevel > 13) {
+ if ((r == g) && (g == b)) {
+ if ((r == 119) || (r == 231) || (r == 5) || (r == 230) || (r == 244) || (r == 93) || (r == 238) || (r == 73) || (r == 9) || (r == 225) || (r == 162) || (r == 153) || (r == 32) ||
+ (r == 50) || (r == 20) || (r == 232) || (r == 224) || (r == 192) || (r == 248) || (r == 152) || (r == 128) || (r == 176) || (r == 184) || (r == 200)) {
+ return false;
+ }
+ return true;
}
- if (red > 0x90 && blue < 0x10 && green < 0x10) {
- cache.setType(CacheType.EVENT);
- return;
+ if ((r == 44) && (b == 44) && (g == 17) ||
+ (r == 228) && (b == 228) && (g == 255) ||
+ (r == 236) && (b == 236) && (g == 255) ||
+ (r == 252) && (b == 225) && (g == 83) ||
+ (r == 252) && (b == 221) && (g == 81) ||
+ (r == 252) && (b == 216) && (g == 79) ||
+ (r == 252) && (b == 211) && (g == 77) ||
+ (r == 251) && (b == 206) && (g == 75) ||
+ (r == 251) && (b == 201) && (g == 73) ||
+ (r == 251) && (b == 196) && (g == 71) ||
+ (r == 251) && (b == 191) && (g == 69) ||
+ (r == 243) && (b == 153) && (g == 36)) {
+ return true;
}
+ return false;
+ }
+ //zoom level 12, 13
+ if ((r == 95) && (g == 95) && (b == 95)) {
+ return true;
+ }
+ return false;
+ }
- // next two are hard to distinguish, therefore we sample all pixels of the spiral
- if (red > 0xFA && green > 0xD0) {
- countMulti++;
+ /**
+ * This method returns detected type from specific pixel from geocaching.com live map.
+ * It was constructed based on classification tree made by Orange (http://orange.biolab.si/)
+ * Input file was made from every non-transparent pixel of every possible "middle" cache icon from GC map
+ *
+ * @param r
+ * Red component of pixel (from 0 - 255)
+ * @param g
+ * Green component of pixel (from 0 - 255)
+ * @param b
+ * Blue component of pixel (from 0 - 255)
+ * @return Value from 0 to 6 representing detected type or state of the cache.
+ */
+ private static int getCacheTypeFromPixel13(int r, int g, int b) {
+ if (b < 130) {
+ if (r < 41) {
+ return CT_MYSTERY;
+ }
+ if (g < 74) {
+ return CT_EVENT;
+ }
+ if (r < 130) {
+ return CT_TRADITIONAL;
}
- if (red < 0xF3 && red > 0xa0 && green > 0x20 && blue < 0x80) {
- countFound++;
+ if (b < 31) {
+ return CT_MULTI;
}
+ if (b < 101) {
+ if (g < 99) {
+ return r < 178 ? CT_FOUND : CT_EVENT;
+ }
+ if (b < 58) {
+ if (g < 174) {
+ return CT_FOUND;
+ }
+ if (r < 224) {
+ return CT_OWN;
+ }
+ if (b < 49) {
+ return g < 210 ? CT_FOUND : CT_OWN;
+ }
+ if (g < 205) {
+ return g < 202 ? CT_FOUND : CT_OWN;
+ }
+ return CT_FOUND;
+ }
+ if (r < 255) {
+ return CT_FOUND;
+ }
+ return g < 236 ? CT_MULTI : CT_FOUND;
+ }
+ return g < 182 ? CT_EVENT : CT_MULTI;
}
-
- // now check whether we are sure about found/multi
- if (countFound > countMulti && countFound >= 2) {
- cache.setFound(true);
+ if (r < 136) {
+ return CT_MYSTERY;
}
- if (countMulti > countFound && countMulti >= 5) {
- cache.setType(CacheType.MULTI);
+ if (b < 168) {
+ return g < 174 ? CT_EARTH : CT_TRADITIONAL;
}
+ return CT_EARTH;
}
- // Pixel colors in tile
- private final static int COLOR_BORDER_GRAY = 0x5F5F5F;
- private final static int COLOR_TRADITIONAL = 0x316013;
- private final static int COLOR_MYSTERY = 0x243C97;
- private final static int COLOR_MULTI = 0xFFDE19;
- private final static int COLOR_FOUND = 0xFF0000;
-
- // Offset inside cache icon
- private final static int POSX_TRADI = 7;
- private final static int POSY_TRADI = -12;
- private final static int POSX_MULTI = 5; // for orange 8
- private final static int POSY_MULTI = -9; // for orange 10
- private final static int POSX_MYSTERY = 5;
- private final static int POSY_MYSTERY = -13;
- private final static int POSX_FOUND = 9;
- private final static int POSY_FOUND = -6;
-
/**
- * For level 14 find the borders of the icons and then use a single pixel and color to match.
+ * This method returns detected type from specific pixel from geocaching.com live map level 14 or higher.
+ * It was constructed based on classification tree made by Orange (http://orange.biolab.si/)
+ * Input file was made from every non-transparent pixel of every possible "full" cache icon from GC map
*
- * @param cache
- * @param bitmap
- * @param xy
+ * @param r
+ * Red component of pixel (from 0 - 255)
+ * @param g
+ * Green component of pixel (from 0 - 255)
+ * @param b
+ * Blue component of pixel (from 0 - 255)
+ * @return Value from 0 to 6 representing detected type or state of the cache.
*/
- private static void parseMapPNG14(cgCache cache, Bitmap bitmap, UTFGridPosition xy) {
- int x = xy.getX() * 4 + 2;
- int y = xy.getY() * 4 + 2;
-
- // search for left border
- int countX = 0;
- while ((bitmap.getPixel(x, y) & 0x00FFFFFF) != COLOR_BORDER_GRAY) {
- if (--x < 0 || ++countX > 20) {
- return;
+ private static int getCacheTypeFromPixel14(int r, int g, int b) {
+ if (b < 128) {
+ if (r < 214) {
+ if (b < 37) {
+ if (g < 50) {
+ if (b < 19) {
+ if (g < 16) {
+ if (b < 4) {
+ return CT_FOUND;
+ }
+ return r < 8 ? CT_VIRTUAL : CT_WEBCAM;
+ }
+ return CT_FOUND;
+ }
+ return CT_WEBCAM;
+ }
+ if (b < 24) {
+ if (b < 18) {
+ return CT_EARTH;
+ }
+ return r < 127 ? CT_TRADITIONAL : CT_EARTH;
+ }
+ return CT_FOUND;
+ }
+ if (r < 142) {
+ if (r < 63) {
+ if (r < 26) {
+ return CT_CITO;
+ }
+ return r < 51 ? CT_WEBCAM : CT_CITO;
+ }
+ return g < 107 ? CT_WEBCAM : CT_MULTI;
+ }
+ if (g < 138) {
+ return r < 178 ? CT_MEGAEVENT : CT_EVENT;
+ }
+ return b < 71 ? CT_FOUND : CT_EARTH;
+ }
+ if (b < 77) {
+ if (g < 166) {
+ if (r < 238) {
+ return g < 120 ? CT_MULTI : CT_OWN;
+ }
+ if (b < 57) {
+ if (r < 254) {
+ if (b < 39) {
+ if (r < 239) {
+ return CT_OWN;
+ }
+ if (b < 36) {
+ if (g < 150) {
+ if (b < 24) {
+ return b < 22 ? CT_FOUND : CT_OWN;
+ }
+ if (g < 138) {
+ return b < 25 ? CT_FOUND : CT_OWN;
+ }
+ return CT_FOUND;
+ }
+ return CT_OWN;
+ }
+ if (b < 38) {
+ if (b < 37) {
+ if (g < 153) {
+ return r < 242 ? CT_OWN : CT_FOUND;
+ }
+ return CT_OWN;
+ }
+ return CT_FOUND;
+ }
+ return CT_OWN;
+ }
+ if (g < 148) {
+ return CT_OWN;
+ }
+ if (r < 244) {
+ return CT_FOUND;
+ }
+ if (b < 45) {
+ if (b < 42) {
+ return CT_FOUND;
+ }
+ if (g < 162) {
+ return r < 245 ? CT_OWN : CT_FOUND;
+ }
+ return CT_OWN;
+ }
+ return CT_FOUND;
+ }
+ return g < 3 ? CT_FOUND : CT_VIRTUAL;
+ }
+ return CT_OWN;
+ }
+ if (b < 51) {
+ if (r < 251) {
+ return CT_OWN;
+ }
+ return g < 208 ? CT_EARTH : CT_MULTI;
+ }
+ if (b < 63) {
+ if (r < 247) {
+ return CT_FOUND;
+ }
+ if (r < 250) {
+ if (g < 169) {
+ return CT_FOUND;
+ }
+ if (g < 192) {
+ if (b < 54) {
+ return CT_OWN;
+ }
+ if (r < 248) {
+ return g < 180 ? CT_FOUND : CT_OWN;
+ }
+ return CT_OWN;
+ }
+ return g < 193 ? CT_FOUND : CT_OWN;
+ }
+ return CT_FOUND;
+ }
+ return CT_FOUND;
+ }
+ if (g < 177) {
+ return CT_OWN;
}
+ if (r < 239) {
+ return CT_FOUND;
+ }
+ if (g < 207) {
+ return CT_OWN;
+ }
+ return r < 254 ? CT_FOUND : CT_EARTH;
}
- // search for bottom border
- int countY = 0;
- while ((bitmap.getPixel(x, y) & 0x00FFFFFF) != 0x000000) {
- if (++y >= Tile.TILE_SIZE || ++countY > 20) {
- return;
+ if (r < 203) {
+ if (b < 218) {
+ if (g < 158) {
+ if (g < 71) {
+ return CT_MYSTERY;
+ }
+ return r < 153 ? CT_WHEREIGO : CT_WEBCAM;
+ }
+ if (b < 167) {
+ return r < 157 ? CT_TRADITIONAL : CT_WEBCAM;
+ }
+ return CT_WHEREIGO;
+ }
+ if (g < 199) {
+ if (r < 142) {
+ return CT_LETTERBOX;
+ }
+ return r < 175 ? CT_CITO : CT_LETTERBOX;
}
+ if (g < 207) {
+ return r < 167 ? CT_MEGAEVENT : CT_CITO;
+ }
+ return CT_EARTH;
}
-
- try {
- if ((bitmap.getPixel(x + POSX_TRADI, y + POSY_TRADI) & 0x00FFFFFF) == COLOR_TRADITIONAL) {
- cache.setType(CacheType.TRADITIONAL);
- return;
+ if (b < 224) {
+ if (g < 235) {
+ if (b < 163) {
+ if (r < 249) {
+ return b < 133 ? CT_FOUND : CT_OWN;
+ }
+ return CT_FOUND;
+ }
+ if (r < 235) {
+ if (r < 213) {
+ if (r < 207) {
+ return CT_FOUND;
+ }
+ if (g < 206) {
+ return CT_OWN;
+ }
+ return g < 207 ? CT_FOUND : CT_OWN;
+ }
+ return g < 194 ? CT_OWN : CT_FOUND;
+ }
+ if (g < 230) {
+ return CT_OWN;
+ }
+ return b < 205 ? CT_FOUND : CT_OWN;
}
- if ((bitmap.getPixel(x + POSX_MYSTERY, y + POSY_MYSTERY) & 0x00FFFFFF) == COLOR_MYSTERY) {
- cache.setType(CacheType.MYSTERY);
- return;
+ if (r < 238) {
+ return CT_CITO;
}
- if ((bitmap.getPixel(x + POSX_MULTI, y + POSY_MULTI) & 0x00FFFFFF) == COLOR_MULTI) {
- cache.setType(CacheType.MULTI);
- return;
+ return b < 170 ? CT_EVENT : CT_FOUND;
+ }
+ if (r < 251) {
+ if (r < 210) {
+ return CT_MYSTERY;
}
- if ((bitmap.getPixel(x + POSX_FOUND, y + POSY_FOUND) & 0x00FFFFFF) == COLOR_FOUND) {
- cache.setFound(true);
+ if (b < 252) {
+ if (r < 243) {
+ if (r < 225) {
+ return CT_WHEREIGO;
+ }
+ if (b < 232) {
+ if (g < 228) {
+ return CT_WEBCAM;
+ }
+ return r < 231 ? CT_VIRTUAL : CT_TRADITIONAL;
+ }
+ if (r < 236) {
+ return CT_WHEREIGO;
+ }
+ return r < 240 ? CT_WEBCAM : CT_WHEREIGO;
+ }
+ if (g < 247) {
+ return r < 245 ? CT_WEBCAM : CT_FOUND;
+ }
+ return CT_WHEREIGO;
}
- } catch (IllegalArgumentException e) {
- // intentionally left blank
+ return CT_LETTERBOX;
}
+ if (r < 255) {
+ return CT_OWN;
+ }
+ return g < 254 ? CT_FOUND : CT_OWN;
+ }
+ /**
+ * This method returns detected type from specific pixel from geocaching.com live map level 11 or lower.
+ * It was constructed based on classification tree made by Orange (http://orange.biolab.si/)
+ * Input file was made from every non-transparent pixel of every possible "full" cache icon from GC map
+ *
+ * @param r
+ * Red component of pixel (from 0 - 255)
+ * @param g
+ * Green component of pixel (from 0 - 255)
+ * @param b
+ * Blue component of pixel (from 0 - 255)
+ * @return Value from 0 to 4 representing detected type or state of the cache.
+ */
+ private static int getCacheTypeFromPixel11(int r, int g, int b) {
+ if (g < 136) {
+ if (r < 90) {
+ return g < 111 ? CT_MYSTERY : CT_TRADITIONAL;
+ }
+ return b < 176 ? CT_EVENT : CT_MYSTERY;
+ }
+ if (r < 197) {
+ return CT_TRADITIONAL;
+ }
+ return b < 155 ? CT_MULTI : CT_EARTH;
}
+
}
diff --git a/main/src/cgeo/geocaching/connector/gc/Login.java b/main/src/cgeo/geocaching/connector/gc/Login.java
index 8bb9866..85b5272 100644
--- a/main/src/cgeo/geocaching/connector/gc/Login.java
+++ b/main/src/cgeo/geocaching/connector/gc/Login.java
@@ -10,6 +10,7 @@ import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import ch.boye.httpclientandroidlib.HttpResponse;
@@ -26,7 +27,6 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
-import java.util.regex.Matcher;
public abstract class Login {
@@ -133,7 +133,7 @@ public abstract class Login {
}
if (loginData.contains("You must validate your account before you can log in.")) {
- Log.i("Failued to log in Geocaching.com as " + login.left + " because account needs to be validated first");
+ Log.i("Failed to log in Geocaching.com as " + login.left + " because account needs to be validated first");
return StatusCode.UNVALIDATED_ACCOUNT;
}
@@ -354,7 +354,7 @@ public abstract class Login {
}
int count = 1;
- final Matcher matcherViewstateCount = GCConstants.PATTERN_VIEWSTATEFIELDCOUNT.matcher(page);
+ final MatcherWrapper matcherViewstateCount = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATEFIELDCOUNT, page);
if (matcherViewstateCount.find()) {
try {
count = Integer.parseInt(matcherViewstateCount.group(1));
@@ -366,14 +366,13 @@ public abstract class Login {
String[] viewstates = new String[count];
// Get the viewstates
- int no;
- final Matcher matcherViewstates = GCConstants.PATTERN_VIEWSTATES.matcher(page);
+ final MatcherWrapper matcherViewstates = new MatcherWrapper(GCConstants.PATTERN_VIEWSTATES, page);
while (matcherViewstates.find()) {
String sno = matcherViewstates.group(1); // number of viewstate
- if (sno.length() == 0) {
+ int no;
+ if (StringUtils.isEmpty(sno)) {
no = 0;
- }
- else {
+ } else {
try {
no = Integer.parseInt(sno);
} catch (NumberFormatException e) {
diff --git a/main/src/cgeo/geocaching/connector/gc/Tile.java b/main/src/cgeo/geocaching/connector/gc/Tile.java
index 5404446..0e5ffe7 100644
--- a/main/src/cgeo/geocaching/connector/gc/Tile.java
+++ b/main/src/cgeo/geocaching/connector/gc/Tile.java
@@ -17,6 +17,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
/**
@@ -52,11 +53,15 @@ public class Tile {
private final Viewport viewPort;
public Tile(Geopoint origin, int zoomlevel) {
+ this(calcX(origin, clippedZoomlevel(zoomlevel)), calcY(origin, clippedZoomlevel(zoomlevel)), clippedZoomlevel(zoomlevel));
+ }
+
+ private Tile(int tileX, int tileY, int zoomlevel) {
- this.zoomlevel = Math.max(Math.min(zoomlevel, ZOOMLEVEL_MAX), ZOOMLEVEL_MIN);
+ this.zoomlevel = clippedZoomlevel(zoomlevel);
- tileX = calcX(origin);
- tileY = calcY(origin);
+ this.tileX = tileX;
+ this.tileY = tileY;
viewPort = new Viewport(getCoord(new UTFGridPosition(0, 0)), getCoord(new UTFGridPosition(63, 63)));
}
@@ -65,28 +70,34 @@ public class Tile {
return zoomlevel;
}
+ private static int clippedZoomlevel(int zoomlevel) {
+ return Math.max(Math.min(zoomlevel, ZOOMLEVEL_MAX), ZOOMLEVEL_MIN);
+ }
+
/**
* Calculate the tile for a Geopoint based on the Spherical Mercator.
*
* @see <a
* href="http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers">Cloudmade</a>
*/
- private int calcX(final Geopoint origin) {
- return (int) ((origin.getLongitude() + 180.0) / 360.0 * NUMBER_OF_TILES[this.zoomlevel]);
+ private static int calcX(final Geopoint origin, final int zoomlevel) {
+ // The cut of the fractional part instead of rounding to the nearest integer is intentional and part of the algorithm
+ return (int) ((origin.getLongitude() + 180.0) / 360.0 * NUMBER_OF_TILES[zoomlevel]);
}
/**
* Calculate the tile for a Geopoint based on the Spherical Mercator.
*
*/
- private int calcY(final Geopoint origin) {
+ private static int calcY(final Geopoint origin, final int zoomlevel) {
// double latRad = Math.toRadians(origin.getLatitude());
// return (int) ((1 - (Math.log(Math.tan(latRad) + (1 / Math.cos(latRad))) / Math.PI)) / 2 * numberOfTiles);
// Optimization from Bing
double sinLatRad = Math.sin(Math.toRadians(origin.getLatitude()));
- return (int) ((0.5 - Math.log((1 + sinLatRad) / (1 - sinLatRad)) / (4 * Math.PI)) * NUMBER_OF_TILES[this.zoomlevel]);
+ // The cut of the fractional part instead of rounding to the nearest integer is intentional and part of the algorithm
+ return (int) ((0.5 - Math.log((1 + sinLatRad) / (1 - sinLatRad)) / (4 * Math.PI)) * NUMBER_OF_TILES[zoomlevel]);
}
public int getX() {
@@ -99,7 +110,7 @@ public class Tile {
/**
* Calculate latitude/longitude for a given x/y position in this tile.
- *
+ *
* @see <a
* href="http://developers.cloudmade.com/projects/tiles/examples/convert-coordinates-to-tile-numbers">Cloudmade</a>
*/
@@ -115,12 +126,17 @@ public class Tile {
@Override
public String toString() {
- return String.format("(%d/%d), zoom=%d", tileX, tileY, zoomlevel);
+ return String.format(Locale.US, "(%d/%d), zoom=%d", tileX, tileY, zoomlevel);
}
/**
* Calculates the maximum possible zoom level where the supplied points
- * are covered by adjacent tiles on the east/west axis.
+ * are covered by at least by the supplied number of
+ * adjacent tiles on the east/west axis.
+ * This criterion can be exactly met for even numbers of tiles
+ * while it may result in one more tile as requested for odd numbers
+ * of tiles.
+ *
* The order of the points (left/right) is irrelevant.
*
* @param left
@@ -129,17 +145,17 @@ public class Tile {
* Second point
* @return
*/
- public static int calcZoomLon(final Geopoint left, final Geopoint right) {
+ public static int calcZoomLon(final Geopoint left, final Geopoint right, final int numberOfTiles) {
int zoom = (int) Math.floor(
- Math.log(360.0 / Math.abs(left.getLongitude() - right.getLongitude()))
+ Math.log(360.0 * numberOfTiles / (2.0 * Math.abs(left.getLongitude() - right.getLongitude())))
/ Math.log(2)
);
Tile tileLeft = new Tile(left, zoom);
Tile tileRight = new Tile(right, zoom);
- if (tileLeft.tileX == tileRight.tileX) {
+ if (Math.abs(tileLeft.tileX - tileRight.tileX) < (numberOfTiles - 1)) {
zoom += 1;
}
@@ -148,7 +164,12 @@ public class Tile {
/**
* Calculates the maximum possible zoom level where the supplied points
- * are covered by adjacent tiles on the north/south axis.
+ * are covered by at least by the supplied number of
+ * adjacent tiles on the north/south axis.
+ * This criterion can be exactly met for even numbers of tiles
+ * while it may result in one more tile as requested for odd numbers
+ * of tiles.
+ *
* The order of the points (bottom/top) is irrelevant.
*
* @param bottom
@@ -157,21 +178,21 @@ public class Tile {
* Second point
* @return
*/
- public static int calcZoomLat(final Geopoint bottom, final Geopoint top) {
+ public static int calcZoomLat(final Geopoint bottom, final Geopoint top, final int numberOfTiles) {
int zoom = (int) Math.ceil(
- Math.log(2.0 * Math.PI /
+ Math.log(2.0 * Math.PI * numberOfTiles / (
Math.abs(
asinh(tanGrad(bottom.getLatitude()))
- asinh(tanGrad(top.getLatitude()))
- )
+ ) * 2.0)
) / Math.log(2)
);
Tile tileBottom = new Tile(bottom, zoom);
Tile tileTop = new Tile(top, zoom);
- if (Math.abs(tileBottom.tileY - tileTop.tileY) > 1) {
+ if (Math.abs(tileBottom.tileY - tileTop.tileY) > (numberOfTiles - 1)) {
zoom -= 1;
}
@@ -184,7 +205,7 @@ public class Tile {
/**
* Calculates the inverted hyperbolic sine
- * (after Bronstein, Semendjajew: Taschenbuch der Mathematik
+ * (after Bronstein, Semendjajew: Taschenbuch der Mathematik)
*
* @param x
* @return
@@ -232,19 +253,48 @@ public class Tile {
}
/**
- * Calculate needed tiles for the given viewport
+ * Calculate needed tiles for the given viewport to cover it with
+ * max 2x2 tiles
*
* @param viewport
* @return
*/
protected static Set<Tile> getTilesForViewport(final Viewport viewport) {
+ return getTilesForViewport(viewport, 2, Tile.ZOOMLEVEL_MIN);
+ }
+
+ /**
+ * Calculate needed tiles for the given viewport.
+ * You can define the minimum number of tiles on the longer axis
+ * and/or the minimum zoom level.
+ *
+ * @param viewport
+ * @param tilesOnAxis
+ * @param minZoom
+ * @return
+ */
+ protected static Set<Tile> getTilesForViewport(final Viewport viewport, final int tilesOnAxis, final int minZoom) {
Set<Tile> tiles = new HashSet<Tile>();
- int zoom = Math.min(Tile.calcZoomLon(viewport.bottomLeft, viewport.topRight),
- Tile.calcZoomLat(viewport.bottomLeft, viewport.topRight));
- tiles.add(new Tile(viewport.bottomLeft, zoom));
- tiles.add(new Tile(new Geopoint(viewport.getLatitudeMin(), viewport.getLongitudeMax()), zoom));
- tiles.add(new Tile(new Geopoint(viewport.getLatitudeMax(), viewport.getLongitudeMin()), zoom));
- tiles.add(new Tile(viewport.topRight, zoom));
+ int zoom = Math.max(
+ Math.min(Tile.calcZoomLon(viewport.bottomLeft, viewport.topRight, tilesOnAxis),
+ Tile.calcZoomLat(viewport.bottomLeft, viewport.topRight, tilesOnAxis)),
+ minZoom);
+
+ Tile tileBottomLeft = new Tile(viewport.bottomLeft, zoom);
+ Tile tileTopRight = new Tile(viewport.topRight, zoom);
+
+ int xLow = Math.min(tileBottomLeft.getX(), tileTopRight.getX());
+ int xHigh = Math.max(tileBottomLeft.getX(), tileTopRight.getX());
+
+ int yLow = Math.min(tileBottomLeft.getY(), tileTopRight.getY());
+ int yHigh = Math.max(tileBottomLeft.getY(), tileTopRight.getY());
+
+ for (int xNum = xLow; xNum <= xHigh; xNum++) {
+ for (int yNum = yLow; yNum <= yHigh; yNum++) {
+ tiles.add(new Tile(xNum, yNum, zoom));
+ }
+ }
+
return tiles;
}
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
index a4eeff5..6d20eb6 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGrid.java
@@ -29,7 +29,7 @@ public final class UTFGrid {
}
/** Calculate from a list of positions (x/y) the coords */
- protected static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) {
+ public static UTFGridPosition getPositionInGrid(List<UTFGridPosition> positions) {
int minX = GRID_MAXX;
int maxX = 0;
int minY = GRID_MAXY;
diff --git a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
index e34d277..5965fff 100644
--- a/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
+++ b/main/src/cgeo/geocaching/connector/gc/UTFGridPosition.java
@@ -1,6 +1,7 @@
package cgeo.geocaching.connector.gc;
-import java.util.regex.Matcher;
+import cgeo.geocaching.utils.MatcherWrapper;
+
import java.util.regex.Pattern;
@@ -35,7 +36,7 @@ public final class UTFGridPosition {
* @return
*/
static UTFGridPosition fromString(String key) {
- final Matcher matcher = UTFGridPosition.PATTERN_JSON_KEY.matcher(key);
+ final MatcherWrapper matcher = new MatcherWrapper(UTFGridPosition.PATTERN_JSON_KEY, key);
try {
if (matcher.matches()) {
final int x = Integer.parseInt(matcher.group(1));
diff --git a/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java
new file mode 100644
index 0000000..a9c041c
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OC11XMLParser.java
@@ -0,0 +1,716 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.Image;
+import cgeo.geocaching.LogEntry;
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.IConnector;
+import cgeo.geocaching.connector.gc.GCConnector;
+import cgeo.geocaching.enumerations.CacheAttribute;
+import cgeo.geocaching.enumerations.CacheSize;
+import cgeo.geocaching.enumerations.CacheType;
+import cgeo.geocaching.enumerations.LogType;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.utils.Log;
+
+import org.apache.commons.lang3.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import android.content.res.Resources;
+import android.sax.Element;
+import android.sax.EndElementListener;
+import android.sax.EndTextElementListener;
+import android.sax.RootElement;
+import android.sax.StartElementListener;
+import android.util.Xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class OC11XMLParser {
+
+ private static final String PARAGRAPH_END = "</p>";
+ private static final String PARAGRAPH_BEGIN = "<p>";
+ private static Pattern STRIP_DATE = Pattern.compile("\\+0([0-9]){1}\\:00");
+ 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 ImageHolder imageHolder = null;
+
+ private static class CacheHolder {
+ public Geocache cache;
+ public String latitude;
+ public String longitude;
+ }
+
+ private static class CacheLog {
+ public String id;
+ public String cacheId;
+ public LogEntry logEntry;
+ }
+
+ private static class CacheDescription {
+ public String cacheId;
+ public String shortDesc;
+ public String desc;
+ public String hint;
+ }
+
+ private static class ImageHolder {
+ public String url;
+ public String objectId;
+ protected String title;
+ protected boolean isSpoiler = false;
+ }
+
+ private static Date parseFullDate(final String date) {
+ final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
+ ISO8601DATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+ final String strippedDate = STRIP_DATE.matcher(date).replaceAll("+0$100");
+ try {
+ return ISO8601DATEFORMAT.parse(strippedDate);
+ } catch (ParseException e) {
+ Log.e("OC11XMLParser.parseFullDate", e);
+ }
+ return null;
+ }
+
+ private static Date parseDayDate(final String date) {
+ final SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
+ ISO8601DATEFORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+ final String strippedDate = STRIP_DATE.matcher(date).replaceAll("+0$100");
+ try {
+ return ISO8601DATEFORMAT.parse(strippedDate);
+ } catch (ParseException e) {
+ Log.e("OC11XMLParser.parseDayDate", e);
+ }
+ return null;
+ }
+
+ private static CacheSize getCacheSize(final String sizeId) {
+ try {
+ int size = Integer.parseInt(sizeId);
+
+ switch (size) {
+ case 1:
+ return CacheSize.OTHER;
+ case 2:
+ return CacheSize.MICRO;
+ case 3:
+ return CacheSize.SMALL;
+ case 4:
+ return CacheSize.REGULAR;
+ case 5:
+ case 6:
+ return CacheSize.LARGE;
+ case 8:
+ return CacheSize.VIRTUAL;
+ default:
+ break;
+ }
+ } catch (NumberFormatException e) {
+ Log.e("OC11XMLParser.getCacheSize", e);
+ }
+ return CacheSize.NOT_CHOSEN;
+ }
+
+ private static CacheType getCacheType(final String typeId) {
+ try {
+ int type = Integer.parseInt(typeId);
+ switch (type) {
+ case 1: // Other/unbekannter Cachetyp
+ return CacheType.UNKNOWN;
+ case 2: // Trad./normaler Cache
+ return CacheType.TRADITIONAL;
+ case 3: // Multi/Multicache
+ return CacheType.MULTI;
+ case 4: // Virt./virtueller Cache
+ return CacheType.VIRTUAL;
+ case 5: // ICam./Webcam-Cache
+ return CacheType.WEBCAM;
+ case 6: // Event/Event-Cache
+ return CacheType.EVENT;
+ case 7: // Quiz/Rätselcache
+ return CacheType.MYSTERY;
+ case 8: // Math/Mathe-/Physikcache
+ return CacheType.MYSTERY;
+ case 9: // Moving/beweglicher Cache
+ return CacheType.VIRTUAL;
+ case 10: // Driv./Drive-In
+ return CacheType.TRADITIONAL;
+ }
+ } catch (NumberFormatException e) {
+ Log.e("OC11XMLParser.getCacheType", e);
+ }
+ return CacheType.UNKNOWN;
+ }
+
+ private static LogType getLogType(final int typeId) {
+ switch (typeId) {
+ case 1:
+ return LogType.FOUND_IT;
+ case 2:
+ return LogType.DIDNT_FIND_IT;
+ case 3:
+ return LogType.NOTE;
+ case 7:
+ return LogType.ATTENDED;
+ case 8:
+ return LogType.WILL_ATTEND;
+ default:
+ return LogType.UNKNOWN;
+ }
+ }
+
+ private static void setCacheStatus(final int statusId, final Geocache cache) {
+ switch (statusId) {
+ case 1:
+ cache.setArchived(false);
+ cache.setDisabled(false);
+ break;
+ case 2:
+ cache.setArchived(false);
+ cache.setDisabled(true);
+ break;
+ default:
+ cache.setArchived(true);
+ cache.setDisabled(false);
+ break;
+ }
+ }
+
+ private static void resetCache(final CacheHolder cacheHolder) {
+ cacheHolder.cache = new Geocache(null);
+ cacheHolder.cache.setReliableLatLon(true);
+ cacheHolder.cache.setDescription(StringUtils.EMPTY);
+ cacheHolder.latitude = "0.0";
+ cacheHolder.longitude = "0.0";
+ }
+
+ private static void resetLog(final CacheLog log) {
+ log.cacheId = StringUtils.EMPTY;
+ log.logEntry = new LogEntry("", 0, LogType.UNKNOWN, "");
+ }
+
+ private static void resetDesc(final CacheDescription desc) {
+ desc.cacheId = StringUtils.EMPTY;
+ desc.shortDesc = StringUtils.EMPTY;
+ desc.desc = StringUtils.EMPTY;
+ desc.hint = StringUtils.EMPTY;
+ }
+
+ protected static int attributeId;
+
+ public static Collection<Geocache> parseCaches(final InputStream stream) throws IOException {
+
+ final Map<String, Geocache> caches = new HashMap<String, Geocache>();
+ final Map<String, LogEntry> logs = new HashMap<String, LogEntry>();
+
+ final CacheHolder cacheHolder = new CacheHolder();
+ final CacheLog logHolder = new CacheLog();
+ final CacheDescription descHolder = new CacheDescription();
+
+ final RootElement root = new RootElement("oc11xml");
+ final Element cacheNode = root.getChild("cache");
+
+ // cache
+ cacheNode.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attributes) {
+ resetCache(cacheHolder);
+ }
+
+ });
+
+ cacheNode.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ Geocache cache = cacheHolder.cache;
+ Geopoint coords = new Geopoint(cacheHolder.latitude, cacheHolder.longitude);
+ cache.setCoords(coords);
+ if (caches.size() < CACHE_PARSE_LIMIT && isValid(cache) && !isExcluded(cache)) {
+ cache.setDetailedUpdatedNow();
+ caches.put(cache.getCacheId(), cache);
+ }
+ }
+
+ private boolean isExcluded(Geocache cache) {
+ if (cache.isArchived() && Settings.isExcludeDisabledCaches()) {
+ return true;
+ }
+ if (cache.isFound() && Settings.isExcludeMyCaches()) {
+ return true;
+ }
+ return !Settings.getCacheType().contains(cache);
+ }
+
+ private boolean isValid(Geocache cache) {
+ return StringUtils.isNotBlank(cache.getGeocode()) && !cache.getCoords().equals(Geopoint.ZERO);
+ }
+ });
+
+ // cache.id
+ cacheNode.getChild("id").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ cacheHolder.cache.setCacheId(body);
+ }
+ });
+
+ // cache.longitude
+ cacheNode.getChild("longitude").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ String longitude = body.trim();
+ if (StringUtils.isNotBlank(longitude)) {
+ cacheHolder.longitude = longitude;
+ }
+ }
+ });
+
+ // cache.latitude
+ cacheNode.getChild("latitude").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ String latitude = body.trim();
+ if (StringUtils.isNotBlank(latitude)) {
+ cacheHolder.latitude = latitude;
+ }
+ }
+ });
+
+ // cache.name
+ cacheNode.getChild("name").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String content = body.trim();
+ cacheHolder.cache.setName(content);
+ }
+ });
+
+ // cache.waypoints[oc]
+ cacheNode.getChild("waypoints").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ if (attrs.getIndex("oc") > -1) {
+ cacheHolder.cache.setGeocode(attrs.getValue("oc"));
+ }
+ if (attrs.getIndex("gccom") > -1) {
+ String gccode = attrs.getValue("gccom");
+ if (!StringUtils.isBlank(gccode)) {
+ cacheHolder.cache.setDescription(res.getString(R.string.cache_listed_on, GCConnector.getInstance().getName()) + ": <a href=\"http://coord.info/" + gccode + "\">" + gccode + "</a><br /><br />");
+ }
+ }
+ }
+ });
+
+ // cache.type[id]
+ cacheNode.getChild("type").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ if (attrs.getIndex("id") > -1) {
+ final String typeId = attrs.getValue("id");
+ cacheHolder.cache.setType(getCacheType(typeId));
+ }
+ }
+ });
+
+ // cache.status[id]
+ cacheNode.getChild("status").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ if (attrs.getIndex("id") > -1) {
+ try {
+ final int statusId = Integer.parseInt(attrs.getValue("id"));
+ setCacheStatus(statusId, cacheHolder.cache);
+ } catch (NumberFormatException e) {
+ Log.w(String.format("Failed to parse status of cache '%s'.", cacheHolder.cache.getGeocode()));
+ }
+ }
+ }
+ });
+
+ // cache.size[id]
+ cacheNode.getChild("size").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ if (attrs.getIndex("id") > -1) {
+ final String typeId = attrs.getValue("id");
+ cacheHolder.cache.setSize(getCacheSize(typeId));
+ }
+ }
+ });
+
+ // cache.difficulty
+ cacheNode.getChild("difficulty").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String content = body.trim();
+ try {
+ cacheHolder.cache.setDifficulty(Float.valueOf(content));
+ } catch (NumberFormatException e) {
+ Log.e("OC11XMLParser: unknown difficulty " + content, e);
+ }
+ }
+ });
+
+ // cache.terrain
+ cacheNode.getChild("terrain").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String content = body.trim();
+ try {
+ cacheHolder.cache.setTerrain(Float.valueOf(content));
+ } catch (NumberFormatException e) {
+ Log.e("OC11XMLParser: unknown terrain " + content, e);
+ }
+ }
+ });
+
+ // cache.datehidden
+ cacheNode.getChild("datehidden").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String content = body.trim();
+ cacheHolder.cache.setHidden(parseFullDate(content));
+ }
+ });
+
+ // cache.userid
+ cacheNode.getChild("userid").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ cacheHolder.cache.setOwnerDisplayName(body);
+ cacheHolder.cache.setOwnerUserId(body);
+ }
+ });
+
+ // cache.attributes.attribute
+ final Element attributeNode = cacheNode.getChild("attributes").getChild("attribute");
+
+ attributeNode.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attributes) {
+ if (attributes.getIndex("id") > -1) {
+ try {
+ attributeId = Integer.parseInt(attributes.getValue("id"));
+ } catch (NumberFormatException e) {
+ Log.w(String.format("Failed to parse attribute id of cache '%s'.", cacheHolder.cache.getGeocode()));
+ }
+ }
+ }
+ });
+
+ attributeNode.setEndTextElementListener(new EndTextElementListener() {
+ @Override
+ public void end(String body) {
+ CacheAttribute attribute = CacheAttribute.getByOcId(attributeId);
+ if (attribute != null) {
+ // semantic of attributes on opencaching is always "yes"
+ cacheHolder.cache.getAttributes().add(attribute.getAttributeName(true));
+ }
+ else {
+ if (StringUtils.isNotBlank(body)) {
+ cacheHolder.cache.getAttributes().add(body.trim());
+ }
+ }
+ }
+ });
+
+ // cachedesc
+ final Element cacheDesc = root.getChild("cachedesc");
+
+ cacheDesc.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attributes) {
+ resetDesc(descHolder);
+ }
+ });
+
+ cacheDesc.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ final Geocache cache = caches.get(descHolder.cacheId);
+ if (cache != null) {
+ cache.setShortdesc(descHolder.shortDesc);
+ cache.setDescription(cache.getDescription() + descHolder.desc);
+ cache.setHint(descHolder.hint);
+ }
+ }
+ });
+
+ // cachedesc.cacheid
+ cacheDesc.getChild("cacheid").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ descHolder.cacheId = body;
+ }
+ });
+
+ // cachedesc.desc
+ cacheDesc.getChild("shortdesc").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String content = body.trim();
+ descHolder.shortDesc = linkify(content);
+ }
+ });
+
+ // cachedesc.desc
+ cacheDesc.getChild("desc").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ final String content = body.trim();
+ descHolder.desc = linkify(content);
+ }
+ });
+
+ // cachedesc.hint
+ cacheDesc.getChild("hint").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ descHolder.hint = body.trim();
+ }
+ });
+
+ // cachelog
+ final Element cacheLog = root.getChild("cachelog");
+
+ cacheLog.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ resetLog(logHolder);
+ }
+ });
+
+ cacheLog.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ final Geocache cache = caches.get(logHolder.cacheId);
+ if (cache != null && logHolder.logEntry.type != LogType.UNKNOWN) {
+ logs.put(logHolder.id, logHolder.logEntry);
+ cache.getLogs().add(0, logHolder.logEntry);
+ if ((logHolder.logEntry.type == LogType.FOUND_IT || logHolder.logEntry.type == LogType.ATTENDED)
+ && StringUtils.equalsIgnoreCase(logHolder.logEntry.author, Settings.getOCConnectorUserName())) {
+ cache.setFound(true);
+ cache.setVisitedDate(logHolder.logEntry.date);
+ }
+ }
+ }
+ });
+
+ // cachelog.id
+ cacheLog.getChild("id").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ logHolder.id = StringUtils.trim(body);
+ }
+ });
+
+ // cachelog.cacheid
+ cacheLog.getChild("cacheid").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ logHolder.cacheId = body;
+ }
+ });
+
+ // cachelog.date
+ cacheLog.getChild("date").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ try {
+ logHolder.logEntry.date = parseDayDate(body).getTime();
+ } catch (NullPointerException e) {
+ Log.w("Failed to parse log date", e);
+ }
+ }
+ });
+
+ // cachelog.logtype
+ cacheLog.getChild("logtype").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ if (attrs.getIndex("id") > -1) {
+ final String id = attrs.getValue("id");
+ try {
+ final int typeId = Integer.parseInt(id);
+ logHolder.logEntry.type = getLogType(typeId);
+ } catch (NumberFormatException e) {
+ Log.e("OC11XMLParser, unknown logtype " + id, e);
+ }
+ }
+ }
+ });
+
+ // cachelog.userid
+ cacheLog.getChild("userid").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String finderName) {
+ logHolder.logEntry.author = finderName;
+ }
+ });
+
+ // cachelog.text
+ cacheLog.getChild("text").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String logText) {
+ logHolder.logEntry.log = stripMarkup(logText);
+ }
+ });
+
+ // pictures
+ final Element picture = root.getChild("picture");
+
+ picture.setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attrs) {
+ imageHolder = new ImageHolder();
+ }
+ });
+
+ picture.setEndElementListener(new EndElementListener() {
+
+ @Override
+ public void end() {
+ if (imageHolder.isSpoiler) {
+ final Geocache cache = caches.get(imageHolder.objectId);
+ if (cache != null) {
+ Image spoiler = new Image(imageHolder.url, imageHolder.title);
+ cache.addSpoiler(spoiler);
+ }
+ }
+ else {
+ final LogEntry log = logs.get(imageHolder.objectId);
+ if (log != null) {
+ log.addLogImage(new Image(imageHolder.url, imageHolder.title));
+ }
+ }
+ }
+ });
+
+ // picture.object
+ picture.getChild("object").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ imageHolder.objectId = StringUtils.trim(body);
+ }
+ });
+
+ // picture.title
+ picture.getChild("title").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ imageHolder.title = StringUtils.trim(body);
+ }
+ });
+
+ // picture.url
+ picture.getChild("url").setEndTextElementListener(new EndTextElementListener() {
+
+ @Override
+ public void end(String body) {
+ imageHolder.url = StringUtils.trim(body);
+ }
+ });
+
+ // picture.attributes
+ picture.getChild("attributes").setStartElementListener(new StartElementListener() {
+
+ @Override
+ public void start(Attributes attributes) {
+ if (attributes.getIndex("spoiler") > -1) {
+ String spoiler = attributes.getValue("spoiler");
+ imageHolder.isSpoiler = ("1".equals(spoiler));
+ }
+ }
+ });
+
+ try {
+ Xml.parse(stream, Xml.Encoding.UTF_8, root.getContentHandler());
+ return caches.values();
+ } catch (SAXException e) {
+ Log.e("Cannot parse .gpx file as oc11xml: could not parse XML", e);
+ return null;
+ }
+ }
+
+ /**
+ * Converts local links to absolute links targeting the OC website.
+ */
+ private static String linkify(String input) {
+ String result = input;
+ Matcher matcher = LOCAL_URL.matcher(result);
+ while (matcher.find()) {
+ String url = matcher.group(1);
+ if (!url.contains(":/")) {
+ IConnector ocConnector = ConnectorFactory.getConnector("OCXXX");
+ String prefix = "http://" + ocConnector.getHost() + "/";
+ result = StringUtils.replace(result, url, prefix + url);
+ matcher = LOCAL_URL.matcher(result);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Removes unneeded markup. 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, PARAGRAPH_BEGIN) && StringUtils.endsWith(input, PARAGRAPH_END)) {
+ String inner = input.substring(PARAGRAPH_BEGIN.length(), input.length() - PARAGRAPH_END.length());
+ if (!inner.contains(PARAGRAPH_BEGIN)) {
+ return inner.trim();
+ }
+ }
+ return input;
+ }
+} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
index 17c961a..69cf8a4 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCApiConnector.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.CancellableHandler;
@@ -21,17 +21,23 @@ public class OCApiConnector extends OCConnector implements ISearchByGeocode {
}
@Override
- public String getLicenseText(final cgCache cache) {
+ public String getLicenseText(final Geocache cache) {
// NOT TO BE TRANSLATED
return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons BY-SA 3.0 License";
}
@Override
public SearchResult searchByGeocode(final String geocode, final String guid, final CancellableHandler handler) {
- final cgCache cache = OkapiClient.getCache(geocode);
+ final Geocache cache = OkapiClient.getCache(geocode);
if (cache == null) {
return null;
}
return new SearchResult(cache);
}
+
+ @Override
+ public boolean isActivated() {
+ // currently always active, but only for details download
+ return true;
+ }
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCConnector.java b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
index c098d12..62dfb4c 100644
--- a/main/src/cgeo/geocaching/connector/oc/OCConnector.java
+++ b/main/src/cgeo/geocaching/connector/oc/OCConnector.java
@@ -1,7 +1,9 @@
package cgeo.geocaching.connector.oc;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
import cgeo.geocaching.connector.AbstractConnector;
+import cgeo.geocaching.enumerations.CacheRealm;
import java.util.regex.Pattern;
@@ -32,7 +34,7 @@ public class OCConnector extends AbstractConnector {
}
@Override
- public String getCacheUrl(cgCache cache) {
+ public String getCacheUrl(Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@@ -47,8 +49,18 @@ public class OCConnector extends AbstractConnector {
}
@Override
+ public boolean isOwner(final ICache cache) {
+ return false;
+ }
+
+ @Override
protected String getCacheUrlPrefix() {
return "http://" + host + "/viewcache.php?wp=";
}
+ @Override
+ public CacheRealm getCacheRealm() {
+ return CacheRealm.OC;
+ }
+
}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java b/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java
new file mode 100644
index 0000000..d361a7e
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OCXMLApiConnector.java
@@ -0,0 +1,60 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
+import cgeo.geocaching.SearchResult;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.connector.capability.ISearchByCenter;
+import cgeo.geocaching.connector.capability.ISearchByGeocode;
+import cgeo.geocaching.connector.capability.ISearchByViewPort;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.utils.CancellableHandler;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class OCXMLApiConnector extends OCConnector implements ISearchByGeocode, ISearchByCenter, ISearchByViewPort {
+
+ private final static double SEARCH_DISTANCE_LIMIT = 15.0;
+ private final static double NEARBY_SEARCH_DISTANCE = 5.0;
+
+ public OCXMLApiConnector(String name, String host, String prefix) {
+ super(name, host, prefix);
+ }
+
+ @Override
+ public SearchResult searchByGeocode(final String geocode, final String guid, CancellableHandler handler) {
+ final Geocache cache = OCXMLClient.getCache(geocode);
+ if (cache == null) {
+ return null;
+ }
+ return new SearchResult(cache);
+ }
+
+ @Override
+ public SearchResult searchByCenter(final Geopoint center) {
+ return new SearchResult(OCXMLClient.getCachesAround(center, NEARBY_SEARCH_DISTANCE));
+ }
+
+ @Override
+ public SearchResult searchByViewport(final Viewport viewport, final String[] tokens) {
+ final Geopoint center = viewport.getCenter();
+ double distance = center.distanceTo(viewport.bottomLeft) * 1.15;
+ if (distance > SEARCH_DISTANCE_LIMIT) {
+ distance = SEARCH_DISTANCE_LIMIT;
+ }
+ return new SearchResult(OCXMLClient.getCachesAround(center, distance));
+ }
+
+ @Override
+ public boolean isActivated() {
+ // currently only tested and working with oc.de
+ return Settings.isOCConnectorActive();
+ }
+
+ @Override
+ public boolean isOwner(ICache cache) {
+ return StringUtils.equalsIgnoreCase(cache.getOwnerUserId(), Settings.getOCConnectorUserName());
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java b/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java
new file mode 100644
index 0000000..dee7bb9
--- /dev/null
+++ b/main/src/cgeo/geocaching/connector/oc/OCXMLClient.java
@@ -0,0 +1,115 @@
+package cgeo.geocaching.connector.oc;
+
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.cgData;
+import cgeo.geocaching.connector.ConnectorFactory;
+import cgeo.geocaching.connector.IConnector;
+import cgeo.geocaching.enumerations.LoadFlags;
+import cgeo.geocaching.geopoint.Geopoint;
+import cgeo.geocaching.geopoint.GeopointFormatter;
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.Log;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+import java.util.zip.GZIPInputStream;
+
+public class OCXMLClient {
+
+ private static final String SERVICE_CACHE = "/xml/ocxml11.php";
+
+ // Url for single cache requests
+ // http://www.opencaching.de/xml/ocxml11.php?modifiedsince=20060320000000&user=0&cache=1&cachedesc=1&cachelog=1&picture=1&removedobject=0&session=0&doctype=0&charset=utf-8&wp=OCC9BE
+
+ public static Geocache getCache(final String geoCode) {
+ try {
+ final Parameters params = getOCXmlQueryParameters(true, true, true);
+ params.put("wp", geoCode);
+ final InputStream data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params);
+
+ if (data == null) {
+ return null;
+ }
+
+ Collection<Geocache> caches = OC11XMLParser.parseCaches(new GZIPInputStream(data));
+ if (caches.iterator().hasNext()) {
+ Geocache cache = caches.iterator().next();
+ cgData.saveCache(cache, LoadFlags.SAVE_ALL);
+ return cache;
+ }
+ return null;
+ } catch (IOException e) {
+ Log.e("Error parsing cache '" + geoCode + "'", e);
+ return null;
+ }
+ }
+
+ public static Collection<Geocache> getCachesAround(final Geopoint center, final double distance) {
+ try {
+ final Parameters params = getOCXmlQueryParameters(false, false, false);
+ params.put("lat", GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center));
+ params.put("lon", GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center));
+ params.put("distance", String.format(Locale.US, "%f", distance));
+ final InputStream data = request(ConnectorFactory.getConnector("OCXXX"), SERVICE_CACHE, params);
+
+ if (data == null) {
+ return Collections.emptyList();
+ }
+
+ return OC11XMLParser.parseCaches(new GZIPInputStream(data));
+ } catch (IOException e) {
+ Log.e("Error parsing nearby search result", e);
+ return Collections.emptyList();
+ }
+ }
+
+ private static InputStream request(final IConnector connector, final String service, final Parameters params) {
+ if (connector == null) {
+ return null;
+ }
+ if (!(connector instanceof OCXMLApiConnector)) {
+ return null;
+ }
+
+ final String host = connector.getHost();
+ if (StringUtils.isBlank(host)) {
+ return null;
+ }
+
+ final String uri = "http://" + host + service;
+ HttpResponse resp = Network.getRequest(uri, params);
+ if (resp != null) {
+ try {
+ return resp.getEntity().getContent();
+ } catch (IllegalStateException e) {
+ // fall through and return null
+ } catch (IOException e) {
+ // fall through and return null
+ }
+ }
+ return null;
+ }
+
+ private static Parameters getOCXmlQueryParameters(final boolean withDescription, final boolean withLogs, final boolean withImages) {
+ return new Parameters("modifiedsince", "20000101000000",
+ "user", "0",
+ "cache", "1",
+ "cachedesc", withDescription ? "1" : "0",
+ "cachelog", withLogs ? "1" : "0",
+ "picture", withImages ? "1" : "0",
+ "removedobject", "0",
+ "session", "0",
+ "doctype", "0",
+ "charset", "utf-8",
+ "zip", "gzip",
+ "picturefromcachelog", withImages ? "1" : "0");
+ }
+}
diff --git a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
index 87cc3a1..dbcfea5 100644
--- a/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
+++ b/main/src/cgeo/geocaching/connector/oc/OkapiClient.java
@@ -1,9 +1,9 @@
package cgeo.geocaching.connector.oc;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.Image;
import cgeo.geocaching.LogEntry;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgImage;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.connector.IConnector;
import cgeo.geocaching.enumerations.CacheSize;
@@ -68,7 +68,7 @@ final public class OkapiClient {
private static final String SERVICE_NEAREST = "/okapi/services/caches/search/nearest";
- public static cgCache getCache(final String geoCode) {
+ public static Geocache getCache(final String geoCode) {
final Parameters params = new Parameters("cache_code", geoCode, "fields", SERVICE_CACHE_FIELDS);
final JSONObject data = request(ConnectorFactory.getConnector(geoCode), SERVICE_CACHE, params);
@@ -79,7 +79,7 @@ final public class OkapiClient {
return parseCache(data);
}
- public static List<cgCache> getCachesAround(final Geopoint center, IConnector connector) {
+ public static List<Geocache> getCachesAround(final Geopoint center, IConnector connector) {
String centerString = GeopointFormatter.format(GeopointFormatter.Format.LAT_DECDEGREE_RAW, center) + "|" + GeopointFormatter.format(GeopointFormatter.Format.LON_DECDEGREE_RAW, center);
final Parameters params = new Parameters("center", centerString);
final JSONObject data = request(connector, SERVICE_NEAREST, params);
@@ -91,7 +91,7 @@ final public class OkapiClient {
return parseCaches(data);
}
- private static List<cgCache> parseCaches(final JSONObject response) {
+ private static List<Geocache> parseCaches(final JSONObject response) {
try {
final JSONArray cachesResponse = response.getJSONArray("results");
if (cachesResponse != null) {
@@ -102,9 +102,9 @@ final public class OkapiClient {
geocodes.add(geocode);
}
}
- List<cgCache> caches = new ArrayList<cgCache>(geocodes.size());
+ List<Geocache> caches = new ArrayList<Geocache>(geocodes.size());
for (String geocode : geocodes) {
- cgCache cache = getCache(geocode);
+ Geocache cache = getCache(geocode);
if (cache != null) {
caches.add(cache);
}
@@ -117,8 +117,8 @@ final public class OkapiClient {
return null;
}
- private static cgCache parseCache(final JSONObject response) {
- final cgCache cache = new cgCache();
+ private static Geocache parseCache(final JSONObject response) {
+ final Geocache cache = new Geocache();
cache.setReliableLatLon(true);
try {
cache.setGeocode(response.getString(CACHE_CODE));
@@ -153,13 +153,12 @@ final public class OkapiClient {
final JSONArray images = response.getJSONArray(CACHE_IMAGES);
if (images != null) {
- JSONObject imageResponse;
for (int i = 0; i < images.length(); i++) {
- imageResponse = images.getJSONObject(i);
+ JSONObject imageResponse = images.getJSONObject(i);
if (imageResponse.getBoolean(CACHE_IMAGE_IS_SPOILER)) {
final String title = imageResponse.getString(CACHE_IMAGE_CAPTION);
final String url = absoluteUrl(imageResponse.getString(CACHE_IMAGE_URL), cache.getGeocode());
- cache.addSpoiler(new cgImage(url, title));
+ cache.addSpoiler(new Image(url, title));
}
}
}
@@ -168,12 +167,9 @@ final public class OkapiClient {
cache.setLogs(parseLogs(response.getJSONArray(CACHE_LATEST_LOGS)));
cache.setHidden(parseDate(response.getString(CACHE_HIDDEN)));
- cache.setUpdated(System.currentTimeMillis());
- cache.setDetailedUpdate(cache.getUpdated());
- cache.setDetailed(true);
-
+ cache.setDetailedUpdatedNow();
// save full detailed caches
- cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
} catch (JSONException e) {
Log.e("OkapiClient.parseCache", e);
}
@@ -239,7 +235,7 @@ final public class OkapiClient {
return null;
}
- private static void setLocation(final cgCache cache, final String location) {
+ private static void setLocation(final Geocache cache, final String location) {
final String latitude = StringUtils.substringBefore(location, "|");
final String longitude = StringUtils.substringAfter(location, "|");
cache.setCoords(new Geopoint(latitude, longitude));
diff --git a/main/src/cgeo/geocaching/connector/ox/OXConnector.java b/main/src/cgeo/geocaching/connector/ox/OXConnector.java
index 98b1656..eec07e3 100644
--- a/main/src/cgeo/geocaching/connector/ox/OXConnector.java
+++ b/main/src/cgeo/geocaching/connector/ox/OXConnector.java
@@ -1,8 +1,9 @@
package cgeo.geocaching.connector.ox;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.ICache;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.connector.AbstractConnector;
import cgeo.geocaching.connector.capability.ISearchByCenter;
import cgeo.geocaching.connector.capability.ISearchByGeocode;
@@ -26,7 +27,7 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I
}
@Override
- public String getCacheUrl(cgCache cache) {
+ public String getCacheUrl(Geocache cache) {
return getCacheUrlPrefix() + cache.getGeocode();
}
@@ -41,14 +42,19 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I
}
@Override
- public String getLicenseText(cgCache cache) {
+ public String getLicenseText(Geocache cache) {
// NOT TO BE TRANSLATED
return "<a href=\"" + getCacheUrl(cache) + "\">" + getName() + "</a> data licensed under the Creative Commons BY-SA 3.0 License";
}
@Override
+ public boolean isOwner(final ICache cache) {
+ return false;
+ }
+
+ @Override
public SearchResult searchByGeocode(String geocode, String guid, CancellableHandler handler) {
- final cgCache cache = OpenCachingApi.searchByGeoCode(geocode);
+ final Geocache cache = OpenCachingApi.searchByGeoCode(geocode);
if (cache == null) {
return null;
}
@@ -58,7 +64,7 @@ public class OXConnector extends AbstractConnector implements ISearchByCenter, I
@Override
public SearchResult searchByCenter(Geopoint center) {
- Collection<cgCache> caches = OpenCachingApi.searchByCenter(center);
+ Collection<Geocache> caches = OpenCachingApi.searchByCenter(center);
if (caches == null) {
return null;
}
diff --git a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java
index 377785a..f40a3e8 100644
--- a/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java
+++ b/main/src/cgeo/geocaching/connector/ox/OXGPXParser.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.connector.ox;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.files.GPX10Parser;
public class OXGPXParser extends GPX10Parser {
@@ -13,7 +13,7 @@ public class OXGPXParser extends GPX10Parser {
}
@Override
- protected void afterParsing(cgCache cache) {
+ protected void afterParsing(Geocache cache) {
cache.setUpdated(System.currentTimeMillis());
if (isDetailed) {
cache.setDetailedUpdate(cache.getUpdated());
diff --git a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
index 17be540..f25e289 100644
--- a/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
+++ b/main/src/cgeo/geocaching/connector/ox/OpenCachingApi.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.connector.ox;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.StoredList;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.GeopointFormatter;
import cgeo.geocaching.network.Network;
@@ -20,25 +20,25 @@ public class OpenCachingApi {
private static final String DEV_KEY = CryptUtils.rot13("PtqQnHo9RUTht3Np");
- public static cgCache searchByGeoCode(final String geocode) {
+ public static Geocache searchByGeoCode(final String geocode) {
final HttpResponse response = Network.getRequest("http://www.opencaching.com/api/geocache/" + geocode + ".gpx",
new Parameters(
"Authorization", DEV_KEY,
"log_limit", "30",
"hint", "true",
"description", "html"));
- final Collection<cgCache> caches = importCachesFromResponse(response, true);
+ final Collection<Geocache> caches = importCachesFromResponse(response, true);
if (CollectionUtils.isNotEmpty(caches)) {
return caches.iterator().next();
}
return null;
}
- private static Collection<cgCache> importCachesFromResponse(final HttpResponse response, final boolean isDetailed) {
+ private static Collection<Geocache> importCachesFromResponse(final HttpResponse response, final boolean isDetailed) {
if (response == null) {
return Collections.emptyList();
}
- Collection<cgCache> caches;
+ Collection<Geocache> caches;
try {
caches = new OXGPXParser(StoredList.STANDARD_LIST_ID, isDetailed).parse(response.getEntity().getContent(), null);
} catch (Exception e) {
@@ -48,7 +48,7 @@ public class OpenCachingApi {
return caches;
}
- public static Collection<cgCache> searchByCenter(final Geopoint center) {
+ public static Collection<Geocache> searchByCenter(final Geopoint center) {
final HttpResponse response = Network.getRequest("http://www.opencaching.com/api/geocache/.gpx",
new Parameters(
"Authorization", DEV_KEY,
diff --git a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
index a31b0cc..530869f 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheAttribute.java
@@ -5,133 +5,190 @@ import cgeo.geocaching.cgeoapplication;
import org.apache.commons.lang3.StringUtils;
+import android.util.SparseArray;
+
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-
public enum CacheAttribute {
- UNKNOWN(0, "unknown", R.drawable.attribute__strikethru, R.string.attribute_unknown_yes, R.string.attribute_unknown_no),
- DOGS(1, "dogs", R.drawable.attribute_dogs, R.string.attribute_dogs_yes, R.string.attribute_dogs_no),
- FEE(2, "fee", R.drawable.attribute_fee, R.string.attribute_fee_yes, R.string.attribute_fee_no),
- RAPPELLING(3, "rappelling", R.drawable.attribute_rappelling, R.string.attribute_rappelling_yes, R.string.attribute_rappelling_no),
- BOAT(4, "boat", R.drawable.attribute_boat, R.string.attribute_boat_yes, R.string.attribute_boat_no),
- SCUBA(5, "scuba", R.drawable.attribute_scuba, R.string.attribute_scuba_yes, R.string.attribute_scuba_no),
- KIDS(6, "kids", R.drawable.attribute_kids, R.string.attribute_kids_yes, R.string.attribute_kids_no),
- ONEHOUR(7, "onehour", R.drawable.attribute_onehour, R.string.attribute_onehour_yes, R.string.attribute_onehour_no),
- SCENIC(8, "scenic", R.drawable.attribute_scenic, R.string.attribute_scenic_yes, R.string.attribute_scenic_no),
- HIKING(9, "hiking", R.drawable.attribute_hiking, R.string.attribute_hiking_yes, R.string.attribute_hiking_no),
- CLIMBING(10, "climbing", R.drawable.attribute_climbing, R.string.attribute_climbing_yes, R.string.attribute_climbing_no),
- WADING(11, "wading", R.drawable.attribute_wading, R.string.attribute_wading_yes, R.string.attribute_wading_no),
- SWIMMING(12, "swimming", R.drawable.attribute_swimming, R.string.attribute_swimming_yes, R.string.attribute_swimming_no),
- AVAILABLE(13, "available", R.drawable.attribute_available, R.string.attribute_available_yes, R.string.attribute_available_no),
- NIGHT(14, "night", R.drawable.attribute_night, R.string.attribute_night_yes, R.string.attribute_night_no),
- WINTER(15, "winter", R.drawable.attribute_winter, R.string.attribute_winter_yes, R.string.attribute_winter_no),
- POISONOAK(17, "poisonoak", R.drawable.attribute_poisonoak, R.string.attribute_poisonoak_yes, R.string.attribute_poisonoak_no),
- DANGEROUSANIMALS(18, "dangerousanimals", R.drawable.attribute_dangerousanimals, R.string.attribute_dangerousanimals_yes, R.string.attribute_dangerousanimals_no),
- TICKS(19, "ticks", R.drawable.attribute_ticks, R.string.attribute_ticks_yes, R.string.attribute_ticks_no),
- MINE(29, "mine", R.drawable.attribute_mine, R.string.attribute_mine_yes, R.string.attribute_mine_no),
- CLIFF(21, "cliff", R.drawable.attribute_cliff, R.string.attribute_cliff_yes, R.string.attribute_cliff_no),
- HUNTING(22, "hunting", R.drawable.attribute_hunting, R.string.attribute_hunting_yes, R.string.attribute_hunting_no),
- DANGER(23, "danger", R.drawable.attribute_danger, R.string.attribute_danger_yes, R.string.attribute_danger_no),
- WHEELCHAIR(24, "wheelchair", R.drawable.attribute_wheelchair, R.string.attribute_wheelchair_yes, R.string.attribute_wheelchair_no),
- PARKING(25, "parking", R.drawable.attribute_parking, R.string.attribute_parking_yes, R.string.attribute_parking_no),
- PUBLIC(26, "public", R.drawable.attribute_public, R.string.attribute_public_yes, R.string.attribute_public_no),
- WATER(27, "water", R.drawable.attribute_water, R.string.attribute_water_yes, R.string.attribute_water_no),
- RESTROOMS(28, "restrooms", R.drawable.attribute_restrooms, R.string.attribute_restrooms_yes, R.string.attribute_restrooms_no),
- PHONE(29, "phone", R.drawable.attribute_phone, R.string.attribute_phone_yes, R.string.attribute_phone_no),
- PICNIC(30, "picnic", R.drawable.attribute_picnic, R.string.attribute_picnic_yes, R.string.attribute_picnic_no),
- CAMPING(31, "camping", R.drawable.attribute_camping, R.string.attribute_camping_yes, R.string.attribute_camping_no),
- BICYCLES(32, "bicycles", R.drawable.attribute_bicycles, R.string.attribute_bicycles_yes, R.string.attribute_bicycles_no),
- MOTORCYCLES(33, "motorcycles", R.drawable.attribute_motorcycles, R.string.attribute_motorcycles_yes, R.string.attribute_motorcycles_no),
- QUADS(34, "quads", R.drawable.attribute_quads, R.string.attribute_quads_yes, R.string.attribute_quads_no),
- JEEPS(35, "jeeps", R.drawable.attribute_jeeps, R.string.attribute_jeeps_yes, R.string.attribute_jeeps_no),
- SNOWMOBILES(36, "snowmobiles", R.drawable.attribute_snowmobiles, R.string.attribute_snowmobiles_yes, R.string.attribute_snowmobiles_no),
- HORSES(37, "horses", R.drawable.attribute_horses, R.string.attribute_horses_yes, R.string.attribute_horses_no),
- CAMPFIRES(38, "campfires", R.drawable.attribute_campfires, R.string.attribute_campfires_yes, R.string.attribute_campfires_no),
- THORN(39, "thorn", R.drawable.attribute_thorn, R.string.attribute_thorn_yes, R.string.attribute_thorn_no),
- STEALTH(40, "stealth", R.drawable.attribute_stealth, R.string.attribute_stealth_yes, R.string.attribute_stealth_no),
- STROLLER(41, "stroller", R.drawable.attribute_stroller, R.string.attribute_stroller_yes, R.string.attribute_stroller_no),
- FIRSTAID(42, "firstaid", R.drawable.attribute_firstaid, R.string.attribute_firstaid_yes, R.string.attribute_firstaid_no),
- COW(43, "cow", R.drawable.attribute_cow, R.string.attribute_cow_yes, R.string.attribute_cow_no),
- FLASHLIGHT(44, "flashlight", R.drawable.attribute_flashlight, R.string.attribute_flashlight_yes, R.string.attribute_flashlight_no),
- LANDF(45, "landf", R.drawable.attribute_landf, R.string.attribute_landf_yes, R.string.attribute_landf_no),
- RV(46, "rv", R.drawable.attribute_rv, R.string.attribute_rv_yes, R.string.attribute_rv_no),
- FIELD_PUZZLE(47, "field_puzzle", R.drawable.attribute_field_puzzle, R.string.attribute_field_puzzle_yes, R.string.attribute_field_puzzle_no),
- UV(48, "uv", R.drawable.attribute_uv, R.string.attribute_uv_yes, R.string.attribute_uv_no),
- SNOWSHOES(49, "snowshoes", R.drawable.attribute_snowshoes, R.string.attribute_snowshoes_yes, R.string.attribute_snowshoes_no),
- SKIIS(50, "skiis", R.drawable.attribute_skiis, R.string.attribute_skiis_yes, R.string.attribute_skiis_no),
- SPECIAL_TOOLS(51, "s_tool", R.drawable.attribute_s_tool, R.string.attribute_s_tool_yes, R.string.attribute_s_tool_no),
- NIGHTCACHE(52, "nightcache", R.drawable.attribute_nightcache, R.string.attribute_nightcache_yes, R.string.attribute_nightcache_no),
- PARKNGRAB(53, "parkngrab", R.drawable.attribute_parkngrab, R.string.attribute_parkngrab_yes, R.string.attribute_parkngrab_no),
- ABANDONED_BUILDING(54, "abandonedbuilding", R.drawable.attribute_abandonedbuilding, R.string.attribute_abandonedbuilding_yes, R.string.attribute_abandonedbuilding_no),
- HIKE_SHORT(55, "hike_short", R.drawable.attribute_hike_short, R.string.attribute_hike_short_yes, R.string.attribute_hike_short_no),
- HIKE_MED(56, "hike_med", R.drawable.attribute_hike_med, R.string.attribute_hike_med_yes, R.string.attribute_hike_med_no),
- HIKE_LONG(57, "hike_long", R.drawable.attribute_hike_long, R.string.attribute_hike_long_yes, R.string.attribute_hike_long_no),
- FUEL(58, "fuel", R.drawable.attribute_fuel, R.string.attribute_fuel_yes, R.string.attribute_fuel_no),
- FOOD(59, "food", R.drawable.attribute_food, R.string.attribute_food_yes, R.string.attribute_food_no),
- WIRELESS_BEACON(60, "wirelessbeacon", R.drawable.attribute_wirelessbeacon, R.string.attribute_wirelessbeacon_yes, R.string.attribute_wirelessbeacon_no),
- PARTNERSHIP(61, "partnership", R.drawable.attribute_partnership, R.string.attribute_partnership_yes, R.string.attribute_partnership_no),
- SEASONAL(62, "seasonal", R.drawable.attribute_seasonal, R.string.attribute_seasonal_yes, R.string.attribute_seasonal_no),
- TOURIST_OK(63, "touristok", R.drawable.attribute_touristok, R.string.attribute_touristok_yes, R.string.attribute_touristok_no),
- TREECLIMBING(64, "treeclimbing", R.drawable.attribute_treeclimbing, R.string.attribute_treeclimbing_yes, R.string.attribute_treeclimbing_no),
- FRONTYARD(65, "frontyard", R.drawable.attribute_frontyard, R.string.attribute_frontyard_yes, R.string.attribute_frontyard_no),
- TEAMWORK(66, "teamwork", R.drawable.attribute_teamwork, R.string.attribute_teamwork_yes, R.string.attribute_teamwork_no);
-
- private static final String INTERNAL_PRE = "attribute_";
+ // THIS LIST IS GENERATED: don't change anything here but in
+ // project/attributes/makeEnum.sh
+ DOGS(1, -1, "dogs", R.drawable.attribute_dogs, R.string.attribute_dogs_yes, R.string.attribute_dogs_no),
+ BICYCLES(32, -1, "bicycles", R.drawable.attribute_bicycles, R.string.attribute_bicycles_yes, R.string.attribute_bicycles_no),
+ MOTORCYCLES(33, -1, "motorcycles", R.drawable.attribute_motorcycles, R.string.attribute_motorcycles_yes, R.string.attribute_motorcycles_no),
+ QUADS(34, -1, "quads", R.drawable.attribute_quads, R.string.attribute_quads_yes, R.string.attribute_quads_no),
+ JEEPS(35, -1, "jeeps", R.drawable.attribute_jeeps, R.string.attribute_jeeps_yes, R.string.attribute_jeeps_no),
+ SNOWMOBILES(36, -1, "snowmobiles", R.drawable.attribute_snowmobiles, R.string.attribute_snowmobiles_yes, R.string.attribute_snowmobiles_no),
+ HORSES(37, -1, "horses", R.drawable.attribute_horses, R.string.attribute_horses_yes, R.string.attribute_horses_no),
+ CAMPFIRES(38, -1, "campfires", R.drawable.attribute_campfires, R.string.attribute_campfires_yes, R.string.attribute_campfires_no),
+ RV(46, -1, "rv", R.drawable.attribute_rv, R.string.attribute_rv_yes, R.string.attribute_rv_no),
+ KIDS(6, 59, "kids", R.drawable.attribute_kids, R.string.attribute_kids_yes, R.string.attribute_kids_no),
+ ONEHOUR(7, -1, "onehour", R.drawable.attribute_onehour, R.string.attribute_onehour_yes, R.string.attribute_onehour_no),
+ SCENIC(8, -1, "scenic", R.drawable.attribute_scenic, R.string.attribute_scenic_yes, R.string.attribute_scenic_no),
+ HIKING(9, 25, "hiking", R.drawable.attribute_hiking, R.string.attribute_hiking_yes, R.string.attribute_hiking_no),
+ CLIMBING(10, 28, "climbing", R.drawable.attribute_climbing, R.string.attribute_climbing_yes, R.string.attribute_climbing_no),
+ WADING(11, -1, "wading", R.drawable.attribute_wading, R.string.attribute_wading_yes, R.string.attribute_wading_no),
+ SWIMMING(12, 29, "swimming", R.drawable.attribute_swimming, R.string.attribute_swimming_yes, R.string.attribute_swimming_no),
+ AVAILABLE(13, 38, "available", R.drawable.attribute_available, R.string.attribute_available_yes, R.string.attribute_available_no),
+ NIGHT(14, -1, "night", R.drawable.attribute_night, R.string.attribute_night_yes, R.string.attribute_night_no),
+ WINTER(15, -1, "winter", R.drawable.attribute_winter, R.string.attribute_winter_yes, R.string.attribute_winter_no),
+ STEALTH(40, -1, "stealth", R.drawable.attribute_stealth, R.string.attribute_stealth_yes, R.string.attribute_stealth_no),
+ FIRSTAID(42, -1, "firstaid", R.drawable.attribute_firstaid, R.string.attribute_firstaid_yes, R.string.attribute_firstaid_no),
+ COW(43, -1, "cow", R.drawable.attribute_cow, R.string.attribute_cow_yes, R.string.attribute_cow_no),
+ FIELD_PUZZLE(47, -1, "field_puzzle", R.drawable.attribute_field_puzzle, R.string.attribute_field_puzzle_yes, R.string.attribute_field_puzzle_no),
+ NIGHTCACHE(52, 1, "nightcache", R.drawable.attribute_nightcache, R.string.attribute_nightcache_yes, R.string.attribute_nightcache_no),
+ PARKNGRAB(53, 24, "parkngrab", R.drawable.attribute_parkngrab, R.string.attribute_parkngrab_yes, R.string.attribute_parkngrab_no),
+ ABANDONEDBUILDING(54, -1, "abandonedbuilding", R.drawable.attribute_abandonedbuilding, R.string.attribute_abandonedbuilding_yes, R.string.attribute_abandonedbuilding_no),
+ HIKE_SHORT(55, -1, "hike_short", R.drawable.attribute_hike_short, R.string.attribute_hike_short_yes, R.string.attribute_hike_short_no),
+ HIKE_MED(56, -1, "hike_med", R.drawable.attribute_hike_med, R.string.attribute_hike_med_yes, R.string.attribute_hike_med_no),
+ HIKE_LONG(57, -1, "hike_long", R.drawable.attribute_hike_long, R.string.attribute_hike_long_yes, R.string.attribute_hike_long_no),
+ SEASONAL(62, 60, "seasonal", R.drawable.attribute_seasonal, R.string.attribute_seasonal_yes, R.string.attribute_seasonal_no),
+ TOURISTOK(63, -1, "touristok", R.drawable.attribute_touristok, R.string.attribute_touristok_yes, R.string.attribute_touristok_no),
+ FRONTYARD(65, -1, "frontyard", R.drawable.attribute_frontyard, R.string.attribute_frontyard_yes, R.string.attribute_frontyard_no),
+ TEAMWORK(66, -1, "teamwork", R.drawable.attribute_teamwork, R.string.attribute_teamwork_yes, R.string.attribute_teamwork_no),
+ LANDF(45, -1, "landf", R.drawable.attribute_landf, R.string.attribute_landf_yes, R.string.attribute_landf_no),
+ PARTNERSHIP(61, -1, "partnership", R.drawable.attribute_partnership, R.string.attribute_partnership_yes, R.string.attribute_partnership_no),
+ FEE(2, 36, "fee", R.drawable.attribute_fee, R.string.attribute_fee_yes, R.string.attribute_fee_no),
+ RAPPELLING(3, 49, "rappelling", R.drawable.attribute_rappelling, R.string.attribute_rappelling_yes, R.string.attribute_rappelling_no),
+ BOAT(4, 52, "boat", R.drawable.attribute_boat, R.string.attribute_boat_yes, R.string.attribute_boat_no),
+ SCUBA(5, 51, "scuba", R.drawable.attribute_scuba, R.string.attribute_scuba_yes, R.string.attribute_scuba_no),
+ FLASHLIGHT(44, 48, "flashlight", R.drawable.attribute_flashlight, R.string.attribute_flashlight_yes, R.string.attribute_flashlight_no),
+ UV(48, -1, "uv", R.drawable.attribute_uv, R.string.attribute_uv_yes, R.string.attribute_uv_no),
+ SNOWSHOES(49, -1, "snowshoes", R.drawable.attribute_snowshoes, R.string.attribute_snowshoes_yes, R.string.attribute_snowshoes_no),
+ SKIIS(50, -1, "skiis", R.drawable.attribute_skiis, R.string.attribute_skiis_yes, R.string.attribute_skiis_no),
+ S_TOOL(51, 46, "s_tool", R.drawable.attribute_s_tool, R.string.attribute_s_tool_yes, R.string.attribute_s_tool_no),
+ WIRELESSBEACON(60, -1, "wirelessbeacon", R.drawable.attribute_wirelessbeacon, R.string.attribute_wirelessbeacon_yes, R.string.attribute_wirelessbeacon_no),
+ TREECLIMBING(64, -1, "treeclimbing", R.drawable.attribute_treeclimbing, R.string.attribute_treeclimbing_yes, R.string.attribute_treeclimbing_no),
+ POISONOAK(17, 16, "poisonoak", R.drawable.attribute_poisonoak, R.string.attribute_poisonoak_yes, R.string.attribute_poisonoak_no),
+ DANGEROUSANIMALS(18, 17, "dangerousanimals", R.drawable.attribute_dangerousanimals, R.string.attribute_dangerousanimals_yes, R.string.attribute_dangerousanimals_no),
+ TICKS(19, 14, "ticks", R.drawable.attribute_ticks, R.string.attribute_ticks_yes, R.string.attribute_ticks_no),
+ MINE(20, 15, "mine", R.drawable.attribute_mine, R.string.attribute_mine_yes, R.string.attribute_mine_no),
+ CLIFF(21, 11, "cliff", R.drawable.attribute_cliff, R.string.attribute_cliff_yes, R.string.attribute_cliff_no),
+ HUNTING(22, 12, "hunting", R.drawable.attribute_hunting, R.string.attribute_hunting_yes, R.string.attribute_hunting_no),
+ DANGER(23, 9, "danger", R.drawable.attribute_danger, R.string.attribute_danger_yes, R.string.attribute_danger_no),
+ THORN(39, 13, "thorn", R.drawable.attribute_thorn, R.string.attribute_thorn_yes, R.string.attribute_thorn_no),
+ WHEELCHAIR(24, -1, "wheelchair", R.drawable.attribute_wheelchair, R.string.attribute_wheelchair_yes, R.string.attribute_wheelchair_no),
+ PARKING(25, 18, "parking", R.drawable.attribute_parking, R.string.attribute_parking_yes, R.string.attribute_parking_no),
+ PUBLIC(26, 19, "public", R.drawable.attribute_public, R.string.attribute_public_yes, R.string.attribute_public_no),
+ WATER(27, 20, "water", R.drawable.attribute_water, R.string.attribute_water_yes, R.string.attribute_water_no),
+ RESTROOMS(28, 21, "restrooms", R.drawable.attribute_restrooms, R.string.attribute_restrooms_yes, R.string.attribute_restrooms_no),
+ PHONE(29, 22, "phone", R.drawable.attribute_phone, R.string.attribute_phone_yes, R.string.attribute_phone_no),
+ PICNIC(30, -1, "picnic", R.drawable.attribute_picnic, R.string.attribute_picnic_yes, R.string.attribute_picnic_no),
+ CAMPING(31, -1, "camping", R.drawable.attribute_camping, R.string.attribute_camping_yes, R.string.attribute_camping_no),
+ STROLLER(41, -1, "stroller", R.drawable.attribute_stroller, R.string.attribute_stroller_yes, R.string.attribute_stroller_no),
+ FUEL(58, -1, "fuel", R.drawable.attribute_fuel, R.string.attribute_fuel_yes, R.string.attribute_fuel_no),
+ FOOD(59, -1, "food", R.drawable.attribute_food, R.string.attribute_food_yes, R.string.attribute_food_no),
+ OC_ONLY(-1, 6, "oc_only", R.drawable.attribute_oc_only, R.string.attribute_oc_only_yes, R.string.attribute_oc_only_no),
+ LINK_ONLY(-1, 7, "link_only", R.drawable.attribute_link_only, R.string.attribute_link_only_yes, R.string.attribute_link_only_no),
+ LETTERBOX(-1, 8, "letterbox", R.drawable.attribute_letterbox, R.string.attribute_letterbox_yes, R.string.attribute_letterbox_no),
+ RAILWAY(-1, 10, "railway", R.drawable.attribute_railway, R.string.attribute_railway_yes, R.string.attribute_railway_no),
+ SYRINGE(-1, 23, "syringe", R.drawable.attribute_syringe, R.string.attribute_syringe_yes, R.string.attribute_syringe_no),
+ SWAMP(-1, 26, "swamp", R.drawable.attribute_swamp, R.string.attribute_swamp_yes, R.string.attribute_swamp_no),
+ HILLS(-1, 27, "hills", R.drawable.attribute_hills, R.string.attribute_hills_yes, R.string.attribute_hills_no),
+ POI(-1, 30, "poi", R.drawable.attribute_poi, R.string.attribute_poi_yes, R.string.attribute_poi_no),
+ MOVING_TARGET(-1, 31, "moving_target", R.drawable.attribute_moving_target, R.string.attribute_moving_target_yes, R.string.attribute_moving_target_no),
+ WEBCAM(-1, 32, "webcam", R.drawable.attribute_webcam, R.string.attribute_webcam_yes, R.string.attribute_webcam_no),
+ INSIDE(-1, 33, "inside", R.drawable.attribute_inside, R.string.attribute_inside_yes, R.string.attribute_inside_no),
+ IN_WATER(-1, 34, "in_water", R.drawable.attribute_in_water, R.string.attribute_in_water_yes, R.string.attribute_in_water_no),
+ NO_GPS(-1, 35, "no_gps", R.drawable.attribute_no_gps, R.string.attribute_no_gps_yes, R.string.attribute_no_gps_no),
+ OVERNIGHT(-1, 37, "overnight", R.drawable.attribute_overnight, R.string.attribute_overnight_yes, R.string.attribute_overnight_no),
+ SPECIFIC_TIMES(-1, 39, "specific_times", R.drawable.attribute_specific_times, R.string.attribute_specific_times_yes, R.string.attribute_specific_times_no),
+ DAY(-1, 40, "day", R.drawable.attribute_day, R.string.attribute_day_yes, R.string.attribute_day_no),
+ TIDE(-1, 41, "tide", R.drawable.attribute_tide, R.string.attribute_tide_yes, R.string.attribute_tide_no),
+ ALL_SEASONS(-1, 42, "all_seasons", R.drawable.attribute_all_seasons, R.string.attribute_all_seasons_yes, R.string.attribute_all_seasons_no),
+ BREEDING(-1, 43, "breeding", R.drawable.attribute_breeding, R.string.attribute_breeding_yes, R.string.attribute_breeding_no),
+ SNOW_PROOF(-1, 44, "snow_proof", R.drawable.attribute_snow_proof, R.string.attribute_snow_proof_yes, R.string.attribute_snow_proof_no),
+ COMPASS(-1, 47, "compass", R.drawable.attribute_compass, R.string.attribute_compass_yes, R.string.attribute_compass_no),
+ CAVE(-1, 50, "cave", R.drawable.attribute_cave, R.string.attribute_cave_yes, R.string.attribute_cave_no),
+ AIRCRAFT(-1, 53, "aircraft", R.drawable.attribute_aircraft, R.string.attribute_aircraft_yes, R.string.attribute_aircraft_no),
+ INVESTIGATION(-1, 54, "investigation", R.drawable.attribute_investigation, R.string.attribute_investigation_yes, R.string.attribute_investigation_no),
+ PUZZLE(-1, 55, "puzzle", R.drawable.attribute_puzzle, R.string.attribute_puzzle_yes, R.string.attribute_puzzle_no),
+ ARITHMETIC(-1, 56, "arithmetic", R.drawable.attribute_arithmetic, R.string.attribute_arithmetic_yes, R.string.attribute_arithmetic_no),
+ OTHER_CACHE(-1, 57, "other_cache", R.drawable.attribute_other_cache, R.string.attribute_other_cache_yes, R.string.attribute_other_cache_no),
+ ASK_OWNER(-1, 58, "ask_owner", R.drawable.attribute_ask_owner, R.string.attribute_ask_owner_yes, R.string.attribute_ask_owner_no),
+ UNKNOWN(-1, -1, "unknown", R.drawable.attribute_unknown, R.string.attribute_unknown_yes, R.string.attribute_unknown_no);
+ // THIS LIST IS GENERATED: don't change anything here but in
+ // project/attributes/makeEnum.sh
+
private static final String INTERNAL_YES = "_yes";
private static final String INTERNAL_NO = "_no";
- public final int id;
- public final String gcRawName;
+ public static final int NO_ID = -1;
+
+ public final int gcid;
+ public final int ocid;
+ public final String rawName;
public final int drawableId;
public final int stringIdYes;
public final int stringIdNo;
- private CacheAttribute(final int id, final String gcRawName, final int drawableId, final int stringIdYes, final int stringIdNo) {
- this.id = id;
- this.gcRawName = gcRawName;
+ CacheAttribute(final int gcid, final int ocid, final String rawName,
+ final int drawableId, final int stringIdYes, final int stringIdNo) {
+ this.gcid = gcid;
+ this.ocid = ocid;
+ this.rawName = rawName;
this.drawableId = drawableId;
this.stringIdYes = stringIdYes;
this.stringIdNo = stringIdNo;
}
+ /**
+ * get localized text
+ *
+ * @param enabled
+ * true: for positive text, false: for negative text
+ * @return the localized text
+ */
public String getL10n(final boolean enabled) {
- return cgeoapplication.getInstance().getResources().getString(enabled ? stringIdYes : stringIdNo);
+ return cgeoapplication.getInstance().getResources().getString(
+ enabled ? stringIdYes : stringIdNo);
}
private final static Map<String, CacheAttribute> FIND_BY_GCRAWNAME;
-
static {
final HashMap<String, CacheAttribute> mapGcRawNames = new HashMap<String, CacheAttribute>();
for (CacheAttribute attr : values()) {
- mapGcRawNames.put(attr.gcRawName, attr);
+ mapGcRawNames.put(attr.rawName, attr);
}
FIND_BY_GCRAWNAME = Collections.unmodifiableMap(mapGcRawNames);
}
- public static CacheAttribute getById(final int id) {
+ private final static SparseArray<CacheAttribute> FIND_BY_GCID = new SparseArray<CacheAttribute>();
+ static {
for (CacheAttribute attr : values()) {
- if (attr.id == id) {
- return attr;
+ if (attr.gcid != NO_ID) {
+ FIND_BY_GCID.put(attr.gcid, attr);
}
}
- return UNKNOWN;
}
- public static CacheAttribute getByGcRawName(final String gcRawName) {
- final CacheAttribute result = gcRawName != null ? FIND_BY_GCRAWNAME.get(gcRawName) : null;
- if (result == null) {
- return UNKNOWN;
+ private final static SparseArray<CacheAttribute> FIND_BY_OCID = new SparseArray<CacheAttribute>();
+ static {
+ for (CacheAttribute attr : values()) {
+ if (attr.ocid != NO_ID) {
+ FIND_BY_OCID.put(attr.ocid, attr);
+ }
}
- return result;
+ }
+
+ public static CacheAttribute getByRawName(final String rawName) {
+ return rawName != null ? FIND_BY_GCRAWNAME.get(rawName) : null;
+ }
+
+ public static CacheAttribute getByGcId(final int gcid) {
+ return FIND_BY_GCID.get(gcid);
+ }
+
+ public static CacheAttribute getByOcId(final int ocid) {
+ return FIND_BY_OCID.get(ocid);
}
public static String trimAttributeName(String attributeName) {
if (null == attributeName) {
return "";
}
- return attributeName.replace(INTERNAL_PRE, "").replace(INTERNAL_YES, "").replace(INTERNAL_NO, "").trim();
+ return attributeName.replace(INTERNAL_YES, "").replace(INTERNAL_NO, "").trim();
}
public static boolean isEnabled(final String attributeName) {
@@ -139,6 +196,6 @@ public enum CacheAttribute {
}
public String getAttributeName(final boolean yes) {
- return gcRawName + (yes ? INTERNAL_YES : INTERNAL_NO);
+ return rawName + (yes ? INTERNAL_YES : INTERNAL_NO);
}
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheRealm.java b/main/src/cgeo/geocaching/enumerations/CacheRealm.java
new file mode 100644
index 0000000..5a203ab
--- /dev/null
+++ b/main/src/cgeo/geocaching/enumerations/CacheRealm.java
@@ -0,0 +1,22 @@
+package cgeo.geocaching.enumerations;
+
+import cgeo.geocaching.R;
+
+public enum CacheRealm {
+
+ GC("gc", "geocaching.com", R.drawable.marker, R.drawable.marker_disabled),
+ OC("oc", "OpenCaching Network", R.drawable.marker_oc, R.drawable.marker_disabled_oc),
+ OTHER("other", "Other", R.drawable.marker_other, R.drawable.marker_disabled_other);
+
+ public final String id;
+ public final String name;
+ public final int markerId;
+ public final int markerDisabledId;
+
+ CacheRealm(String id, String name, int markerId, int markerDisabledId) {
+ this.id = id;
+ this.name = name;
+ this.markerId = markerId;
+ this.markerDisabledId = markerDisabledId;
+ }
+}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheSize.java b/main/src/cgeo/geocaching/enumerations/CacheSize.java
index 155c9a5..726ebe2 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheSize.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheSize.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.cgeoapplication;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
/**
@@ -24,7 +25,7 @@ public enum CacheSize {
public final int comparable;
private final int stringId;
- private CacheSize(String id, int comparable, int stringId) {
+ CacheSize(String id, int comparable, int stringId) {
this.id = id;
this.comparable = comparable;
this.stringId = stringId;
@@ -34,7 +35,7 @@ public enum CacheSize {
static {
final HashMap<String, CacheSize> mapping = new HashMap<String, CacheSize>();
for (CacheSize cs : values()) {
- mapping.put(cs.id.toLowerCase(), cs);
+ mapping.put(cs.id.toLowerCase(Locale.US), cs);
}
// add medium as additional string for Regular
mapping.put("medium", CacheSize.REGULAR);
@@ -51,7 +52,7 @@ public enum CacheSize {
return result;
}
// only if String was not found, normalize it
- final CacheSize resultNormalized = CacheSize.FIND_BY_ID.get(id.toLowerCase().trim());
+ final CacheSize resultNormalized = CacheSize.FIND_BY_ID.get(id.toLowerCase(Locale.US).trim());
if (resultNormalized != null) {
return resultNormalized;
}
diff --git a/main/src/cgeo/geocaching/enumerations/CacheType.java b/main/src/cgeo/geocaching/enumerations/CacheType.java
index 730c989..528d3fa 100644
--- a/main/src/cgeo/geocaching/enumerations/CacheType.java
+++ b/main/src/cgeo/geocaching/enumerations/CacheType.java
@@ -1,10 +1,12 @@
package cgeo.geocaching.enumerations;
+import cgeo.geocaching.ICache;
import cgeo.geocaching.R;
import cgeo.geocaching.cgeoapplication;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
/**
@@ -44,7 +46,7 @@ public enum CacheType {
private final int stringId;
public final int markerId;
- private CacheType(String id, String pattern, String guid, int stringId, int markerId) {
+ CacheType(String id, String pattern, String guid, int stringId, int markerId) {
this.id = id;
this.pattern = pattern;
this.guid = guid;
@@ -59,14 +61,14 @@ public enum CacheType {
final HashMap<String, CacheType> mappingPattern = new HashMap<String, CacheType>();
for (CacheType ct : values()) {
mappingId.put(ct.id, ct);
- mappingPattern.put(ct.pattern.toLowerCase(), ct);
+ mappingPattern.put(ct.pattern.toLowerCase(Locale.US), ct);
}
FIND_BY_ID = Collections.unmodifiableMap(mappingId);
FIND_BY_PATTERN = Collections.unmodifiableMap(mappingPattern);
}
public static CacheType getById(final String id) {
- final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase().trim()) : null;
+ final CacheType result = (id != null) ? CacheType.FIND_BY_ID.get(id.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
return UNKNOWN;
}
@@ -74,7 +76,7 @@ public enum CacheType {
}
public static CacheType getByPattern(final String pattern) {
- final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase().trim()) : null;
+ final CacheType result = (pattern != null) ? CacheType.FIND_BY_PATTERN.get(pattern.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
return UNKNOWN;
}
@@ -88,4 +90,25 @@ public enum CacheType {
public boolean isEvent() {
return CacheType.EVENT == this || CacheType.MEGA_EVENT == this || CacheType.CITO == this || CacheType.LOSTANDFOUND == this;
}
+
+ @Override
+ public String toString() {
+ return getL10n();
+ }
+
+ /**
+ * Whether this type contains the given cache.
+ *
+ * @param cache
+ * @return true if this is the ALL type or if this type equals the type of the cache.
+ */
+ public boolean contains(ICache cache) {
+ if (cache == null) {
+ return false;
+ }
+ if (this == ALL) {
+ return true;
+ }
+ return cache.getType() == this;
+ }
}
diff --git a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
index e9dbc5d..5f5b2c9 100644
--- a/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
+++ b/main/src/cgeo/geocaching/enumerations/LiveMapStrategy.java
@@ -26,7 +26,7 @@ public interface LiveMapStrategy {
public final EnumSet<StrategyFlag> flags;
private final int stringId;
- private Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) {
+ Strategy(int id, EnumSet<StrategyFlag> flags, int stringId) {
this.id = id;
this.flags = flags;
this.stringId = stringId;
diff --git a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java
index 36a09bf..f2c79fe 100644
--- a/main/src/cgeo/geocaching/enumerations/LocationProviderType.java
+++ b/main/src/cgeo/geocaching/enumerations/LocationProviderType.java
@@ -9,7 +9,7 @@ public enum LocationProviderType {
public final int resourceId;
- private LocationProviderType(final int resourceId) {
+ LocationProviderType(final int resourceId) {
this.resourceId = resourceId;
}
}
diff --git a/main/src/cgeo/geocaching/enumerations/LogType.java b/main/src/cgeo/geocaching/enumerations/LogType.java
index 332ef03..71a5146 100644
--- a/main/src/cgeo/geocaching/enumerations/LogType.java
+++ b/main/src/cgeo/geocaching/enumerations/LogType.java
@@ -5,6 +5,7 @@ import cgeo.geocaching.cgeoapplication;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
@@ -14,43 +15,50 @@ import java.util.Map;
*/
public enum LogType {
- FOUND_IT(2, "2", "found it", R.string.log_found),
- DIDNT_FIND_IT(3, "3", "didn't find it", R.string.log_dnf),
+ FOUND_IT(2, "2", "found it", R.string.log_found, R.drawable.mark_green),
+ DIDNT_FIND_IT(3, "3", "didn't find it", R.string.log_dnf, R.drawable.mark_red),
NOTE(4, "4", "write note", R.string.log_note),
- PUBLISH_LISTING(1003, "24", "publish listing", R.string.log_published),
- ENABLE_LISTING(23, "23", "enable listing", R.string.log_enabled),
- ARCHIVE(5, "5", "archive", R.string.log_archived),
- UNARCHIVE(12, "12", "unarchive", R.string.log_unarchived),
- TEMP_DISABLE_LISTING(22, "22", "temporarily disable listing", R.string.log_disabled),
- NEEDS_ARCHIVE(7, "7", "needs archived", R.string.log_needs_archived),
+ PUBLISH_LISTING(1003, "24", "publish listing", R.string.log_published, R.drawable.mark_green_more),
+ ENABLE_LISTING(23, "23", "enable listing", R.string.log_enabled, R.drawable.mark_green_more),
+ ARCHIVE(5, "5", "archive", R.string.log_archived, R.drawable.mark_red_more),
+ UNARCHIVE(12, "12", "unarchive", R.string.log_unarchived, R.drawable.mark_green_more),
+ TEMP_DISABLE_LISTING(22, "22", "temporarily disable listing", R.string.log_disabled, R.drawable.mark_red_more),
+ NEEDS_ARCHIVE(7, "7", "needs archived", R.string.log_needs_archived, R.drawable.mark_red),
WILL_ATTEND(9, "9", "will attend", R.string.log_attend),
- ATTENDED(10, "10", "attended", R.string.log_attended),
- RETRIEVED_IT(13, "13", "retrieved it", R.string.log_retrieved),
- PLACED_IT(14, "14", "placed it", R.string.log_placed),
- GRABBED_IT(19, "19", "grabbed it", R.string.log_grabbed),
- NEEDS_MAINTENANCE(45, "45", "needs maintenance", R.string.log_maintenance_needed),
- OWNER_MAINTENANCE(46, "46", "owner maintenance", R.string.log_maintained),
+ ATTENDED(10, "10", "attended", R.string.log_attended, R.drawable.mark_green),
+ RETRIEVED_IT(13, "13", "retrieved it", R.string.log_retrieved, R.drawable.mark_green_more),
+ PLACED_IT(14, "14", "placed it", R.string.log_placed, R.drawable.mark_green_more),
+ GRABBED_IT(19, "19", "grabbed it", R.string.log_grabbed, R.drawable.mark_green_more),
+ NEEDS_MAINTENANCE(45, "45", "needs maintenance", R.string.log_maintenance_needed, R.drawable.mark_red),
+ OWNER_MAINTENANCE(46, "46", "owner maintenance", R.string.log_maintained, R.drawable.mark_green_more),
UPDATE_COORDINATES(47, "47", "update coordinates", R.string.log_update),
- DISCOVERED_IT(48, "48", "discovered it", R.string.log_discovered),
+ DISCOVERED_IT(48, "48", "discovered it", R.string.log_discovered, R.drawable.mark_green),
POST_REVIEWER_NOTE(18, "68", "post reviewer note", R.string.log_reviewer),
- VISIT(1001, "75", "visit", R.string.log_tb_visit),
- WEBCAM_PHOTO_TAKEN(11, "11", "webcam photo taken", R.string.log_webcam),
+ VISIT(1001, "75", "visit", R.string.log_tb_visit, R.drawable.mark_green),
+ WEBCAM_PHOTO_TAKEN(11, "11", "webcam photo taken", R.string.log_webcam, R.drawable.mark_green),
ANNOUNCEMENT(74, "74", "announcement", R.string.log_announcement),
MOVE_COLLECTION(69, "69", "unused_collection", R.string.log_movecollection),
MOVE_INVENTORY(70, "70", "unused_inventory", R.string.log_moveinventory),
RETRACT(25, "25", "retract listing", R.string.log_retractlisting),
- UNKNOWN(0, "unknown", "", R.string.err_unknown); // LogType not init. yet
+ MARKED_MISSING(16, "16", "marked missing", R.string.log_marked_missing, R.drawable.mark_red),
+ UNKNOWN(0, "unknown", "", R.string.err_unknown, R.drawable.mark_red); // LogType not init. yet
public final int id;
public final String iconName;
public final String type;
private final int stringId;
+ public final int markerId;
- private LogType(int id, String iconName, String type, int stringId) {
+ LogType(int id, String iconName, String type, int stringId, int markerId) {
this.id = id;
this.iconName = iconName;
this.type = type;
this.stringId = stringId;
+ this.markerId = markerId;
+ }
+
+ LogType(int id, String iconName, String type, int stringId) {
+ this(id, iconName, type, stringId, R.drawable.mark_gray);
}
private final static Map<String, LogType> FIND_BY_ICONNAME;
@@ -76,7 +84,7 @@ public enum LogType {
}
public static LogType getByIconName(final String imageType) {
- final LogType result = imageType != null ? LogType.FIND_BY_ICONNAME.get(imageType.toLowerCase().trim()) : null;
+ final LogType result = imageType != null ? LogType.FIND_BY_ICONNAME.get(imageType.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
return UNKNOWN;
}
@@ -84,7 +92,7 @@ public enum LogType {
}
public static LogType getByType(final String type) {
- final LogType result = type != null ? LogType.FIND_BY_TYPE.get(type.toLowerCase().trim()) : null;
+ final LogType result = type != null ? LogType.FIND_BY_TYPE.get(type.toLowerCase(Locale.US).trim()) : null;
if (result == null) {
return UNKNOWN;
}
diff --git a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
index 13b8d03..68a17a5 100644
--- a/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
+++ b/main/src/cgeo/geocaching/enumerations/LogTypeTrackable.java
@@ -11,7 +11,7 @@ public enum LogTypeTrackable {
final public String action;
final public int resourceId;
- private LogTypeTrackable(int id, String action, int resourceId) {
+ LogTypeTrackable(int id, String action, int resourceId) {
this.id = id;
this.action = action;
this.resourceId = resourceId;
diff --git a/main/src/cgeo/geocaching/enumerations/WaypointType.java b/main/src/cgeo/geocaching/enumerations/WaypointType.java
index 52eb318..748c432 100644
--- a/main/src/cgeo/geocaching/enumerations/WaypointType.java
+++ b/main/src/cgeo/geocaching/enumerations/WaypointType.java
@@ -19,13 +19,14 @@ public enum WaypointType {
PUZZLE("puzzle", R.string.wp_puzzle, R.drawable.waypoint_puzzle),
STAGE("stage", R.string.wp_stage, R.drawable.waypoint_stage),
TRAILHEAD("trailhead", R.string.wp_trailhead, R.drawable.waypoint_trailhead),
- WAYPOINT("waypoint", R.string.wp_waypoint, R.drawable.waypoint_waypoint);
+ WAYPOINT("waypoint", R.string.wp_waypoint, R.drawable.waypoint_waypoint),
+ ORIGINAL("original", R.string.wp_original, R.drawable.waypoint_waypoint);
public final String id;
public final int stringId;
public final int markerId;
- private WaypointType(String id, int stringId, int markerId) {
+ WaypointType(String id, int stringId, int markerId) {
this.id = id;
this.stringId = stringId;
this.markerId = markerId;
@@ -36,13 +37,13 @@ public enum WaypointType {
* non public so that <code>null</code> handling can be handled centrally in the enum type itself
*/
private static final Map<String, WaypointType> FIND_BY_ID;
- public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN = new HashSet<WaypointType>();
+ public static final Set<WaypointType> ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL = new HashSet<WaypointType>();
static {
final HashMap<String, WaypointType> mapping = new HashMap<String, WaypointType>();
for (WaypointType wt : values()) {
mapping.put(wt.id, wt);
- if (wt != WaypointType.OWN) {
- ALL_TYPES_EXCEPT_OWN.add(wt);
+ if (wt != WaypointType.OWN && wt != WaypointType.ORIGINAL) {
+ ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL.add(wt);
}
}
FIND_BY_ID = Collections.unmodifiableMap(mapping);
@@ -67,7 +68,6 @@ public enum WaypointType {
return cgeoapplication.getInstance().getBaseContext().getResources().getString(stringId);
}
-
@Override
public final String toString() {
return getL10n();
diff --git a/main/src/cgeo/geocaching/export/Export.java b/main/src/cgeo/geocaching/export/Export.java
index 7a2b075..a1a873f 100644
--- a/main/src/cgeo/geocaching/export/Export.java
+++ b/main/src/cgeo/geocaching/export/Export.java
@@ -1,24 +1,24 @@
package cgeo.geocaching.export;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import android.app.Activity;
import java.util.List;
/**
- * Represents an exporter to export a {@link List} of {@link cgCache} to various formats.
+ * Represents an exporter to export a {@link List} of {@link cgeo.geocaching.Geocache} to various formats.
*/
interface Export {
/**
- * Export a {@link List} of {@link cgCache} to various formats.
+ * Export a {@link List} of {@link cgeo.geocaching.Geocache} to various formats.
*
* @param caches
- * The {@link List} of {@link cgCache} to be exported
+ * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
* @param activity
* optional: Some exporters might have an UI which requires an {@link Activity}
*/
- public void export(List<cgCache> caches, Activity activity);
+ public void export(List<Geocache> caches, Activity activity);
/**
* Get the localized name of this exporter.
diff --git a/main/src/cgeo/geocaching/export/ExportFactory.java b/main/src/cgeo/geocaching/export/ExportFactory.java
index d32a751..a3ecb0c 100644
--- a/main/src/cgeo/geocaching/export/ExportFactory.java
+++ b/main/src/cgeo/geocaching/export/ExportFactory.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.utils.Log;
import android.app.Activity;
@@ -34,11 +34,11 @@ public abstract class ExportFactory {
* Creates a dialog so that the user can select an exporter.
*
* @param caches
- * The {@link List} of {@link cgCache} to be exported
+ * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
* @param activity
* The {@link Activity} in whose context the dialog should be shown
*/
- public static void showExportMenu(final List<cgCache> caches, final Activity activity) {
+ public static void showExportMenu(final List<Geocache> caches, final Activity activity) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(R.string.export).setIcon(R.drawable.ic_menu_share);
diff --git a/main/src/cgeo/geocaching/export/FieldnoteExport.java b/main/src/cgeo/geocaching/export/FieldnoteExport.java
index 028ad54..39eae0e 100644
--- a/main/src/cgeo/geocaching/export/FieldnoteExport.java
+++ b/main/src/cgeo/geocaching/export/FieldnoteExport.java
@@ -2,20 +2,24 @@ package cgeo.geocaching.export;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.Geocache;
+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.IOUtils;
import cgeo.geocaching.utils.Log;
+import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
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.View;
@@ -51,57 +55,53 @@ class FieldnoteExport extends AbstractExport {
super(getString(R.string.export_fieldnotes));
}
- /**
- * A dialog to allow the user to set options for the export.
- *
- * Currently available options are: upload field notes, only new logs since last export/upload
- */
- private class ExportOptionsDialog extends AlertDialog {
- public ExportOptionsDialog(final List<cgCache> caches, final Activity activity) {
- super(activity);
-
- View layout = activity.getLayoutInflater().inflate(R.layout.fieldnote_export_dialog, null);
- setView(layout);
-
- final CheckBox uploadOption = (CheckBox) layout.findViewById(R.id.upload);
- final CheckBox onlyNewOption = (CheckBox) layout.findViewById(R.id.onlynew);
-
- uploadOption.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onlyNewOption.setEnabled(uploadOption.isChecked());
- }
- });
-
- layout.findViewById(R.id.export).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dismiss();
- new ExportTask(
- caches,
- activity,
- uploadOption.isChecked(),
- onlyNewOption.isChecked())
- .execute((Void) null);
- }
- });
- }
- }
-
@Override
- public void export(final List<cgCache> caches, final Activity activity) {
+ public void export(final List<Geocache> caches, final Activity activity) {
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);
} else {
// Show configuration dialog
- new ExportOptionsDialog(caches, activity).show();
+ getExportOptionsDialog(caches, activity).show();
}
}
+ private Dialog getExportOptionsDialog(final List<Geocache> caches, final Activity activity) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+
+ View layout = activity.getLayoutInflater().inflate(R.layout.fieldnote_export_dialog, null);
+ builder.setView(layout);
+
+ final CheckBox uploadOption = (CheckBox) layout.findViewById(R.id.upload);
+ final CheckBox onlyNewOption = (CheckBox) layout.findViewById(R.id.onlynew);
+
+ uploadOption.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onlyNewOption.setEnabled(uploadOption.isChecked());
+ }
+ });
+
+ builder.setPositiveButton(R.string.export, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ new ExportTask(
+ caches,
+ activity,
+ uploadOption.isChecked(),
+ onlyNewOption.isChecked())
+ .execute((Void) null);
+ }
+ });
+
+ return builder.create();
+ }
+
private class ExportTask extends AsyncTask<Void, Integer, Boolean> {
- private final List<cgCache> caches;
+ private final List<Geocache> caches;
private final Activity activity;
private final boolean upload;
private final boolean onlyNew;
@@ -114,7 +114,7 @@ class FieldnoteExport extends AbstractExport {
* Instantiates and configurates the task for exporting field notes.
*
* @param caches
- * The {@link List} of {@link cgCache} to be exported
+ * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
* @param activity
* optional: Show a progress bar and toasts
* @param upload
@@ -122,7 +122,7 @@ class FieldnoteExport extends AbstractExport {
* @param onlyNew
* Upload/export only new logs since last export
*/
- public ExportTask(final List<cgCache> caches, final Activity activity, final boolean upload, final boolean onlyNew) {
+ public ExportTask(final List<Geocache> caches, final Activity activity, final boolean upload, final boolean onlyNew) {
this.caches = caches;
this.activity = activity;
this.upload = upload;
@@ -139,13 +139,11 @@ class FieldnoteExport extends AbstractExport {
@Override
protected Boolean doInBackground(Void... params) {
final StringBuilder fieldNoteBuffer = new StringBuilder();
- final cgeoapplication app = cgeoapplication.getInstance();
-
try {
int i = 0;
- for (cgCache cache : caches) {
+ for (Geocache cache : caches) {
if (cache.isLogOffline()) {
- appendFieldNote(fieldNoteBuffer, cache, app.loadLogOffline(cache.getGeocode()));
+ appendFieldNote(fieldNoteBuffer, cache, cgData.loadLogOffline(cache.getGeocode()));
publishProgress(++i);
}
}
@@ -156,40 +154,30 @@ class FieldnoteExport extends AbstractExport {
fieldNoteBuffer.append('\n');
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- exportLocation.mkdirs();
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ return false;
+ }
- SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
- exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt");
+ exportLocation.mkdirs();
- OutputStream os;
- Writer fw = null;
- try {
- os = new FileOutputStream(exportFile);
- fw = new OutputStreamWriter(os, "UTF-16");
- fw.write(fieldNoteBuffer.toString());
- } catch (IOException e) {
- Log.e("FieldnoteExport.ExportTask export", e);
- return false;
- } finally {
- if (fw != null) {
- try {
- fw.close();
- } catch (IOException e) {
- Log.e("FieldnoteExport.ExportTask export", e);
- return false;
- }
- }
- }
- } else {
+ SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
+ exportFile = new File(exportLocation.toString() + '/' + fileNameDateFormat.format(new Date()) + ".txt");
+
+ Writer fw = null;
+ try {
+ OutputStream os = new FileOutputStream(exportFile);
+ fw = new OutputStreamWriter(os, CharEncoding.UTF_16);
+ fw.write(fieldNoteBuffer.toString());
+ } catch (IOException e) {
+ Log.e("FieldnoteExport.ExportTask export", e);
return false;
+ } finally {
+ IOUtils.closeQuietly(fw);
}
if (upload) {
publishProgress(STATUS_UPLOAD);
- final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx";
-
if (!Login.isActualLoginStatus()) {
// no need to upload (possibly large file) if we're not logged in
final StatusCode loginState = Login.login();
@@ -198,6 +186,7 @@ class FieldnoteExport extends AbstractExport {
}
}
+ final String uri = "http://www.geocaching.com/my/uploadfieldnotes.aspx";
String page = Network.getResponseData(Network.getRequest(uri));
if (!Login.getLoginStatus(page)) {
@@ -268,7 +257,7 @@ class FieldnoteExport extends AbstractExport {
}
}
- static void appendFieldNote(final StringBuilder fieldNoteBuffer, final cgCache cache, final LogEntry log) {
+ static void appendFieldNote(final StringBuilder fieldNoteBuffer, final Geocache cache, final LogEntry log) {
fieldNoteBuffer.append(cache.getGeocode())
.append(',')
.append(fieldNoteDateFormat.format(new Date(log.date)))
diff --git a/main/src/cgeo/geocaching/export/GpxExport.java b/main/src/cgeo/geocaching/export/GpxExport.java
index 7573db9..d130e1f 100644
--- a/main/src/cgeo/geocaching/export/GpxExport.java
+++ b/main/src/cgeo/geocaching/export/GpxExport.java
@@ -1,11 +1,11 @@
package cgeo.geocaching.export;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.ActivityMixin;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.enumerations.CacheAttribute;
@@ -13,26 +13,28 @@ import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.BaseUtils;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.XmlUtils;
-import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
+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.View;
import android.widget.CheckBox;
import android.widget.TextView;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
@@ -41,76 +43,73 @@ import java.util.Locale;
class GpxExport extends AbstractExport {
private static final SimpleDateFormat dateFormatZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
+ public static final String PREFIX_XSI = "http://www.w3.org/2001/XMLSchema-instance";
+ 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";
protected GpxExport() {
super(getString(R.string.export_gpx));
}
@Override
- public void export(final List<cgCache> caches, final Activity activity) {
+ public void export(final List<Geocache> caches, final Activity activity) {
if (null == activity) {
// No activity given, so no user interaction possible.
// Start export with default parameters.
- new ExportTask(caches, activity).execute((Void) null);
+ new ExportTask(caches, null).execute((Void) null);
} else {
// Show configuration dialog
- new ExportOptionsDialog(caches, activity).show();
+ getExportDialog(caches, activity).show();
}
}
- /**
- * A dialog to allow the user to set options for the export.
- *
- * Currently available option is: opening of share menu after successful export
- */
- private class ExportOptionsDialog extends AlertDialog {
- public ExportOptionsDialog(final List<cgCache> caches, final Activity activity) {
- super(activity);
+ private Dialog getExportDialog(final List<Geocache> caches, final Activity activity) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- View layout = activity.getLayoutInflater().inflate(R.layout.gpx_export_dialog, null);
- setView(layout);
+ View layout = activity.getLayoutInflater().inflate(R.layout.gpx_export_dialog, null);
+ builder.setView(layout);
- final TextView text = (TextView) layout.findViewById(R.id.info);
- text.setText(getString(R.string.export_gpx_info, Settings.getGpxExportDir()));
+ final TextView text = (TextView) layout.findViewById(R.id.info);
+ text.setText(getString(R.string.export_gpx_info, Settings.getGpxExportDir()));
- final CheckBox shareOption = (CheckBox) layout.findViewById(R.id.share);
+ final CheckBox shareOption = (CheckBox) layout.findViewById(R.id.share);
- shareOption.setChecked(Settings.getShareAfterExport());
+ shareOption.setChecked(Settings.getShareAfterExport());
- shareOption.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Settings.setShareAfterExport(shareOption.isChecked());
- }
- });
+ shareOption.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Settings.setShareAfterExport(shareOption.isChecked());
+ }
+ });
- layout.findViewById(R.id.export).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- dismiss();
- new ExportTask(caches, activity).execute((Void) null);
- }
- });
- }
+ builder.setPositiveButton(R.string.export, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ new ExportTask(caches, activity).execute((Void) null);
+ }
+ });
+
+ return builder.create();
}
- private class ExportTask extends AsyncTask<Void, Integer, Boolean> {
- private final List<cgCache> caches;
+ private class ExportTask extends AsyncTask<Void, Integer, File> {
+ private final List<Geocache> caches;
private final Activity activity;
private final Progress progress = new Progress();
- private File exportFile;
- private Writer gpx;
/**
* Instantiates and configures the task for exporting field notes.
*
* @param caches
- * The {@link List} of {@link cgCache} to be exported
+ * The {@link List} of {@link cgeo.geocaching.Geocache} to be exported
* @param activity
* optional: Show a progress bar and toasts
*/
- public ExportTask(final List<cgCache> caches, final Activity activity) {
+ public ExportTask(final List<Geocache> caches, final Activity activity) {
this.caches = caches;
this.activity = activity;
}
@@ -124,169 +123,122 @@ class GpxExport extends AbstractExport {
}
@Override
- protected Boolean doInBackground(Void... params) {
+ protected File doInBackground(Void... params) {
// quick check for being able to write the GPX file
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- return false;
+ return null;
}
+ 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;
try {
final File exportLocation = new File(Settings.getGpxExportDir());
exportLocation.mkdirs();
- final SimpleDateFormat fileNameDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
- exportFile = new File(Settings.getGpxExportDir() + File.separatorChar + "export_" + fileNameDateFormat.format(new Date()) + ".gpx");
-
- gpx = new BufferedWriter(new FileWriter(exportFile));
-
- gpx.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
- gpx.write("<gpx version=\"1.0\" creator=\"c:geo - http://www.cgeo.org\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd\">");
+ final XmlSerializer gpx = Xml.newSerializer();
+ writer = new FileWriter(exportFile);
+ gpx.setOutput(writer);
+
+ gpx.startDocument("UTF-8", true);
+ gpx.setPrefix("", PREFIX_GPX);
+ gpx.setPrefix("xsi", PREFIX_XSI);
+ gpx.setPrefix("groundspeak", PREFIX_GROUNDSPEAK);
+ gpx.startTag(PREFIX_GPX, "gpx");
+ gpx.attribute("", "version", "1.0");
+ gpx.attribute("", "creator", "c:geo - http://www.cgeo.org/");
+ gpx.attribute(PREFIX_XSI, "schemaLocation",
+ 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++) {
- // reload the cache. otherwise logs, attributes and other detailed information is not available
- final cgCache cache = cgeoapplication.getInstance().loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY);
+ final Geocache cache = cgData.loadCache(caches.get(i).getGeocode(), LoadFlags.LOAD_ALL_DB_ONLY);
- gpx.write("<wpt ");
- gpx.write("lat=\"");
- gpx.write(Double.toString(cache.getCoords().getLatitude()));
- gpx.write("\" ");
- gpx.write("lon=\"");
- gpx.write(Double.toString(cache.getCoords().getLongitude()));
- gpx.write("\">");
+ 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) {
- gpx.write("<time>");
- gpx.write(StringEscapeUtils.escapeXml(dateFormatZ.format(hiddenDate)));
- gpx.write("</time>");
+ XmlUtils.simpleText(gpx, PREFIX_GPX, "time", dateFormatZ.format(hiddenDate));
}
- gpx.write("<name>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getGeocode()));
- gpx.write("</name>");
-
- gpx.write("<desc>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getName()));
- gpx.write("</desc>");
-
- gpx.write("<url>");
- gpx.write(cache.getUrl());
- gpx.write("</url>");
-
- gpx.write("<urlname>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getName()));
- gpx.write("</urlname>");
-
- gpx.write("<sym>");
- gpx.write(cache.isFound() ? "Geocache Found" : "Geocache");
- gpx.write("</sym>");
-
- gpx.write("<type>");
- gpx.write(StringEscapeUtils.escapeXml("Geocache|" + cache.getType().pattern));
- gpx.write("</type>");
-
- gpx.write("<groundspeak:cache ");
- gpx.write("id=\"");
- gpx.write(cache.getCacheId());
- gpx.write("\" available=\"");
- gpx.write(!cache.isDisabled() ? "True" : "False");
- gpx.write("\" archived=\"");
- gpx.write(cache.isArchived() ? "True" : "False");
- gpx.write("\" ");
- gpx.write("xmlns:groundspeak=\"http://www.groundspeak.com/cache/1/0/1\">");
-
- gpx.write("<groundspeak:name>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getName()));
- gpx.write("</groundspeak:name>");
-
- gpx.write("<groundspeak:placed_by>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getOwnerDisplayName()));
- gpx.write("</groundspeak:placed_by>");
-
- gpx.write("<groundspeak:owner>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getOwnerUserId()));
- gpx.write("</groundspeak:owner>");
+ 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.write("<groundspeak:type>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getType().pattern));
- gpx.write("</groundspeak:type>");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "cache");
+ gpx.attribute("", "id", cache.getCacheId());
+ gpx.attribute("", "available", !cache.isDisabled() ? "True" : "False");
+ gpx.attribute("", "archives", cache.isArchived() ? "True" : "False");
- gpx.write("<groundspeak:container>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getSize().id));
- gpx.write("</groundspeak:container>");
- writeAttributes(cache);
+ 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());
- gpx.write("<groundspeak:difficulty>");
- gpx.write(Float.toString(cache.getDifficulty()));
- gpx.write("</groundspeak:difficulty>");
+ writeAttributes(gpx, cache);
- gpx.write("<groundspeak:terrain>");
- gpx.write(Float.toString(cache.getTerrain()));
- gpx.write("</groundspeak:terrain>");
+ 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.write("<groundspeak:country>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getLocation()));
- gpx.write("</groundspeak:country>");
+ 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");
- gpx.write("<groundspeak:state></groundspeak:state>"); // c:geo cannot manage 2 separate fields, so we export as country
+ writeLogs(gpx, cache);
- gpx.write("<groundspeak:short_description html=\"");
- gpx.write(BaseUtils.containsHtml(cache.getShortDescription()) ? "True" : "False");
- gpx.write("\">");
- gpx.write(StringEscapeUtils.escapeXml(cache.getShortDescription()));
- gpx.write("</groundspeak:short_description>");
+ gpx.endTag(PREFIX_GROUNDSPEAK, "cache");
+ gpx.endTag(PREFIX_GPX, "wpt");
- gpx.write("<groundspeak:long_description html=\"");
- gpx.write(BaseUtils.containsHtml(cache.getDescription()) ? "True" : "False");
- gpx.write("\">");
- gpx.write(StringEscapeUtils.escapeXml(cache.getDescription()));
- gpx.write("</groundspeak:long_description>");
-
- gpx.write("<groundspeak:encoded_hints>");
- gpx.write(StringEscapeUtils.escapeXml(cache.getHint()));
- gpx.write("</groundspeak:encoded_hints>");
-
- writeLogs(cache);
-
- gpx.write("</groundspeak:cache>");
-
- gpx.write("</wpt>");
-
- writeWaypoints(cache);
+ writeWaypoints(gpx, cache);
publishProgress(i + 1);
}
- gpx.write("</gpx>");
-
- gpx.close();
- } catch (Exception e) {
+ gpx.endTag(PREFIX_GPX, "gpx");
+ gpx.endDocument();
+ } catch (final IOException e) {
Log.e("GpxExport.ExportTask export", e);
- if (gpx != null) {
+ if (writer != null) {
try {
- gpx.close();
- } catch (IOException ee) {
+ writer.close();
+ } catch (IOException e1) {
+ // Ignore double error
}
}
-
// delete partial gpx file on error
if (exportFile.exists()) {
exportFile.delete();
}
- return false;
+ return null;
}
- return true;
+ return exportFile;
}
- private void writeWaypoints(final cgCache cache) throws IOException {
- List<cgWaypoint> waypoints = cache.getWaypoints();
- List<cgWaypoint> ownWaypoints = new ArrayList<cgWaypoint>(waypoints.size());
- List<cgWaypoint> originWaypoints = new ArrayList<cgWaypoint>(waypoints.size());
- for (cgWaypoint wp : cache.getWaypoints()) {
+ private void writeWaypoints(final XmlSerializer gpx, final Geocache cache) throws IOException {
+ List<Waypoint> waypoints = cache.getWaypoints();
+ List<Waypoint> ownWaypoints = new ArrayList<Waypoint>(waypoints.size());
+ List<Waypoint> originWaypoints = new ArrayList<Waypoint>(waypoints.size());
+ for (Waypoint wp : cache.getWaypoints()) {
if (wp.isUserDefined()) {
ownWaypoints.add(wp);
} else {
@@ -294,19 +246,19 @@ class GpxExport extends AbstractExport {
}
}
int maxPrefix = 0;
- for (cgWaypoint wp : originWaypoints) {
+ for (Waypoint wp : originWaypoints) {
String prefix = wp.getPrefix();
try {
maxPrefix = Math.max(Integer.parseInt(prefix), maxPrefix);
} catch (NumberFormatException ex) {
Log.e("Unexpected origin waypoint prefix='" + prefix + "'", ex);
}
- writeCacheWaypoint(wp, prefix);
+ writeCacheWaypoint(gpx, wp, prefix);
}
- for (cgWaypoint wp : ownWaypoints) {
+ for (Waypoint wp : ownWaypoints) {
maxPrefix++;
String prefix = StringUtils.leftPad(String.valueOf(maxPrefix), 2, '0');
- writeCacheWaypoint(wp, prefix);
+ writeCacheWaypoint(gpx, wp, prefix);
}
}
@@ -319,103 +271,78 @@ class GpxExport extends AbstractExport {
* @param prefix
* @throws IOException
*/
- private void writeCacheWaypoint(final cgWaypoint wp, final String prefix) throws IOException {
- gpx.write("<wpt lat=\"");
+ private void writeCacheWaypoint(final XmlSerializer gpx, final Waypoint wp, final String prefix) throws IOException {
+ gpx.startTag(PREFIX_GPX, "wpt");
final Geopoint coords = wp.getCoords();
- gpx.write(coords != null ? Double.toString(coords.getLatitude()) : ""); // TODO: check whether is the best way to handle unknown waypoint coordinates
- gpx.write("\" lon=\"");
- gpx.write(coords != null ? Double.toString(coords.getLongitude()) : "");
- gpx.write("\">");
-
- gpx.write("<name>");
- gpx.write(StringEscapeUtils.escapeXml(prefix));
- gpx.write(StringEscapeUtils.escapeXml(wp.getGeocode().substring(2)));
- gpx.write("</name>");
-
- gpx.write("<cmt>");
- gpx.write(StringEscapeUtils.escapeXml(wp.getNote()));
- gpx.write("</cmt>");
-
- gpx.write("<desc>");
- gpx.write(StringEscapeUtils.escapeXml(wp.getName()));
- gpx.write("</desc>");
-
- gpx.write("<sym>");
- gpx.write(StringEscapeUtils.escapeXml(wp.getWaypointType().toString())); //TODO: Correct identifier string
- gpx.write("</sym>");
-
- gpx.write("<type>Waypoint|");
- gpx.write(StringEscapeUtils.escapeXml(wp.getWaypointType().toString())); //TODO: Correct identifier string
- gpx.write("</type>");
-
- gpx.write("</wpt>");
+ gpx.attribute("", "lat", coords != null ? Double.toString(coords.getLatitude()) : ""); // TODO: check whether is the best way to handle unknown waypoint coordinates
+ gpx.attribute("", "lon", coords != null ? Double.toString(coords.getLongitude()) : "");
+ XmlUtils.multipleTexts(gpx, PREFIX_GPX,
+ "name", prefix + wp.getGeocode().substring(2),
+ "cmt", wp.getNote(),
+ "desc", wp.getName(),
+ "sym", wp.getWaypointType().toString(), //TODO: Correct identifier string
+ "type", "Waypoint|" + wp.getWaypointType().toString()); //TODO: Correct identifier string
+ gpx.endTag(PREFIX_GPX, "wpt");
}
- private void writeLogs(final cgCache cache) throws IOException {
+ private void writeLogs(final XmlSerializer gpx, final Geocache cache) throws IOException {
if (cache.getLogs().isEmpty()) {
return;
}
- gpx.write("<groundspeak:logs>");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "logs");
for (LogEntry log : cache.getLogs()) {
- gpx.write("<groundspeak:log id=\"");
- gpx.write(Integer.toString(log.id));
- gpx.write("\">");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "log");
+ gpx.attribute("", "id", Integer.toString(log.id));
- gpx.write("<groundspeak:date>");
- gpx.write(StringEscapeUtils.escapeXml(dateFormatZ.format(new Date(log.date))));
- gpx.write("</groundspeak:date>");
+ XmlUtils.multipleTexts(gpx, PREFIX_GROUNDSPEAK,
+ "date", dateFormatZ.format(new Date(log.date)),
+ "type", log.type.type);
- gpx.write("<groundspeak:type>");
- gpx.write(StringEscapeUtils.escapeXml(log.type.type));
- gpx.write("</groundspeak:type>");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "finder");
+ gpx.attribute("", "id", log.author);
+ gpx.endTag(PREFIX_GROUNDSPEAK, "finder");
- gpx.write("<groundspeak:finder id=\"\">");
- gpx.write(StringEscapeUtils.escapeXml(log.author));
- gpx.write("</groundspeak:finder>");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "text");
+ gpx.attribute("", "encoded", "False");
+ gpx.text(log.log);
+ gpx.endTag(PREFIX_GROUNDSPEAK, "text");
- gpx.write("<groundspeak:text encoded=\"False\">");
- gpx.write(StringEscapeUtils.escapeXml(log.log));
- gpx.write("</groundspeak:text>");
-
- gpx.write("</groundspeak:log>");
+ gpx.endTag(PREFIX_GROUNDSPEAK, "log");
}
- gpx.write("</groundspeak:logs>");
+ gpx.endTag(PREFIX_GROUNDSPEAK, "logs");
}
- private void writeAttributes(final cgCache cache) throws IOException {
+ private void writeAttributes(final XmlSerializer gpx, final Geocache cache) throws IOException {
if (cache.getAttributes().isEmpty()) {
return;
}
//TODO: Attribute conversion required: English verbose name, gpx-id
- gpx.write("<groundspeak:attributes>");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "attributes");
for (String attribute : cache.getAttributes()) {
- final CacheAttribute attr = CacheAttribute.getByGcRawName(CacheAttribute.trimAttributeName(attribute));
+ final CacheAttribute attr = CacheAttribute.getByRawName(CacheAttribute.trimAttributeName(attribute));
+ if (attr == null) {
+ continue;
+ }
final boolean enabled = CacheAttribute.isEnabled(attribute);
- gpx.write("<groundspeak:attribute id=\"");
- gpx.write(Integer.toString(attr.id));
- gpx.write("\" inc=\"");
- if (enabled) {
- gpx.write('1');
- } else {
- gpx.write('0');
- }
- gpx.write("\">");
- gpx.write(StringEscapeUtils.escapeXml(attr.getL10n(enabled)));
- gpx.write("</groundspeak:attribute>");
+ gpx.startTag(PREFIX_GROUNDSPEAK, "attribute");
+ gpx.attribute("", "id", Integer.toString(attr.gcid));
+ gpx.attribute("", "inc", enabled ? "1" : "0");
+ gpx.text(attr.getL10n(enabled));
+ gpx.endTag(PREFIX_GROUNDSPEAK, "attribute");
}
- gpx.write("</groundspeak:attributes>");
+ gpx.endTag(PREFIX_GROUNDSPEAK, "attributes");
}
@Override
- protected void onPostExecute(Boolean result) {
+ protected void onPostExecute(final File exportFile) {
if (null != activity) {
progress.dismiss();
- if (result) {
+ if (exportFile != null) {
ActivityMixin.showToast(activity, getName() + ' ' + getString(R.string.export_exportedto) + ": " + exportFile.toString());
if (Settings.getShareAfterExport()) {
Intent shareIntent = new Intent();
diff --git a/main/src/cgeo/geocaching/files/FileList.java b/main/src/cgeo/geocaching/files/FileList.java
index df95085..31daeb4 100644
--- a/main/src/cgeo/geocaching/files/FileList.java
+++ b/main/src/cgeo/geocaching/files/FileList.java
@@ -1,9 +1,11 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.StoredList;
import cgeo.geocaching.activity.AbstractListActivity;
import cgeo.geocaching.utils.FileUtils;
+import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.collections.CollectionUtils;
@@ -33,7 +35,7 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
private T adapter = null;
private ProgressDialog waitDialog = null;
private SearchFilesThread searchingThread = null;
- private int listId = StoredList.STANDARD_LIST_ID;
+ protected int listId = StoredList.STANDARD_LIST_ID;
private String[] extensions;
final private Handler changeWaitDialogHandler = new Handler() {
@@ -91,7 +93,7 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
Bundle extras = getIntent().getExtras();
if (extras != null) {
- listId = extras.getInt("list");
+ listId = extras.getInt(Intents.EXTRA_LIST_ID);
}
if (listId <= StoredList.TEMPORARY_LIST_ID) {
listId = StoredList.STANDARD_LIST_ID;
@@ -182,7 +184,7 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
Log.w("No external media mounted.");
}
} catch (Exception e) {
- Log.e("cgFileList.loadFiles.run: " + e.toString());
+ Log.e("cgFileList.loadFiles.run", e);
}
changeWaitDialogHandler.sendMessage(Message.obtain(changeWaitDialogHandler, 0, "loaded directories"));
@@ -242,15 +244,8 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
Log.e("Could not get additional mount points for user content. " +
"Proceeding with external storage only (" + extStorage + ")");
} finally {
- try {
- if (fr != null) {
- fr.close();
- }
- if (br != null) {
- br.close();
- }
- } catch (IOException e) {
- }
+ IOUtils.closeQuietly(fr);
+ IOUtils.closeQuietly(br);
}
}
return storages;
@@ -283,8 +278,8 @@ public abstract class FileList<T extends ArrayAdapter<File>> extends AbstractLis
private void setExtensions(final String[] extensionsIn) {
extensions = extensionsIn;
for (int i = 0; i < extensions.length; i++) {
- String extension = extensions[i];
- if (extension.length() == 0 || extension.charAt(0) != '.') {
+ final String extension = extensions[i];
+ if (StringUtils.isEmpty(extension) || extension.charAt(0) != '.') {
extensions[i] = "." + extension;
}
}
diff --git a/main/src/cgeo/geocaching/files/FileParser.java b/main/src/cgeo/geocaching/files/FileParser.java
index 0308d81..50b65a1 100644
--- a/main/src/cgeo/geocaching/files/FileParser.java
+++ b/main/src/cgeo/geocaching/files/FileParser.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.files;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.CancellableHandler;
import java.io.BufferedReader;
@@ -26,7 +26,7 @@ public abstract class FileParser {
* @throws ParserException
* if the input stream contains data not matching the file format of the parser
*/
- public abstract Collection<cgCache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException;
+ public abstract Collection<Geocache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException;
/**
* Convenience method for parsing a file.
@@ -37,7 +37,7 @@ public abstract class FileParser {
* @throws IOException
* @throws ParserException
*/
- public Collection<cgCache> parse(final File file, final CancellableHandler progressHandler) throws IOException, ParserException {
+ public Collection<Geocache> parse(final File file, final CancellableHandler progressHandler) throws IOException, ParserException {
FileInputStream fis = new FileInputStream(file);
try {
return parse(fis, progressHandler);
@@ -72,7 +72,7 @@ public abstract class FileParser {
}
}
- protected static void fixCache(cgCache cache) {
+ protected static void fixCache(Geocache cache) {
if (cache.getInventory() != null) {
cache.setInventoryItems(cache.getInventory().size());
} else {
diff --git a/main/src/cgeo/geocaching/files/GPXImporter.java b/main/src/cgeo/geocaching/files/GPXImporter.java
index fb78360..b8dcbb3 100644
--- a/main/src/cgeo/geocaching/files/GPXImporter.java
+++ b/main/src/cgeo/geocaching/files/GPXImporter.java
@@ -1,11 +1,11 @@
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.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.enumerations.LoadFlags;
@@ -124,7 +124,7 @@ public class GPXImporter {
final Handler importStepHandler;
final CancellableHandler progressHandler;
- public ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ protected ImportThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
this.listId = listId;
this.importStepHandler = importStepHandler;
this.progressHandler = progressHandler;
@@ -132,14 +132,13 @@ public class GPXImporter {
@Override
public void run() {
- final Collection<cgCache> caches;
try {
importStepHandler.sendMessage(importStepHandler.obtainMessage(IMPORT_STEP_START));
- caches = doImport();
+ final Collection<Geocache> caches = doImport();
Log.i("Imported successfully " + caches.size() + " caches.");
final SearchResult search = new SearchResult();
- for (cgCache cache : caches) {
+ for (Geocache cache : caches) {
search.addCache(cache);
}
@@ -168,13 +167,12 @@ public class GPXImporter {
}
}
- protected abstract Collection<cgCache> doImport() throws IOException, ParserException;
+ protected abstract Collection<Geocache> doImport() throws IOException, ParserException;
private boolean importStaticMaps(final SearchResult importedCaches) {
- final cgeoapplication app = cgeoapplication.getInstance();
int storedCacheMaps = 0;
for (String geocode : importedCaches.getGeocodes()) {
- cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
Log.d("GPXImporter.ImportThread.importStaticMaps start downloadMaps for cache " + geocode);
StaticMapsProvider.downloadMaps(cache);
storedCacheMaps++;
@@ -196,7 +194,7 @@ public class GPXImporter {
}
@Override
- protected Collection<cgCache> doImport() throws IOException, ParserException {
+ protected Collection<Geocache> 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);
@@ -206,12 +204,12 @@ public class GPXImporter {
static abstract class ImportGpxThread extends ImportThread {
- public ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ protected ImportGpxThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
}
@Override
- protected Collection<cgCache> doImport() throws IOException, ParserException {
+ protected Collection<Geocache> doImport() throws IOException, ParserException {
try {
// try to parse cache file as GPX 10
return doImport(new GPX10Parser(listId));
@@ -221,7 +219,7 @@ public class GPXImporter {
}
}
- protected abstract Collection<cgCache> doImport(GPXParser parser) throws IOException, ParserException;
+ protected abstract Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException;
}
static class ImportGpxFileThread extends ImportGpxThread {
@@ -233,10 +231,10 @@ public class GPXImporter {
}
@Override
- protected Collection<cgCache> doImport(GPXParser parser) throws IOException, ParserException {
+ protected Collection<Geocache> 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<cgCache> caches = parser.parse(cacheFile, progressHandler);
+ Collection<Geocache> caches = parser.parse(cacheFile, progressHandler);
final String wptsFilename = getWaypointsFileNameForGpxFile(cacheFile);
if (wptsFilename != null) {
@@ -262,7 +260,7 @@ public class GPXImporter {
}
@Override
- protected Collection<cgCache> doImport(GPXParser parser) throws IOException, ParserException {
+ protected Collection<Geocache> 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);
@@ -276,13 +274,13 @@ public class GPXImporter {
static abstract class ImportGpxZipThread extends ImportGpxThread {
- public ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
+ protected ImportGpxZipThread(int listId, Handler importStepHandler, CancellableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
}
@Override
- protected Collection<cgCache> doImport(GPXParser parser) throws IOException, ParserException {
- Collection<cgCache> caches = Collections.emptySet();
+ protected Collection<Geocache> doImport(GPXParser parser) throws IOException, ParserException {
+ Collection<Geocache> 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());
diff --git a/main/src/cgeo/geocaching/files/GPXParser.java b/main/src/cgeo/geocaching/files/GPXParser.java
index b9d3f53..a691677 100644
--- a/main/src/cgeo/geocaching/files/GPXParser.java
+++ b/main/src/cgeo/geocaching/files/GPXParser.java
@@ -1,11 +1,12 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.StoredList;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgTrackable;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.enumerations.CacheSize;
@@ -18,6 +19,7 @@ import cgeo.geocaching.enumerations.WaypointType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.Attributes;
@@ -41,7 +43,6 @@ import java.util.EnumSet;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class GPXParser extends FileParser {
@@ -79,8 +80,8 @@ public abstract class GPXParser extends FileParser {
final protected String namespace;
final private String version;
- private cgCache cache;
- private cgTrackable trackable = new cgTrackable();
+ private Geocache cache;
+ private Trackable trackable = new Trackable();
private LogEntry log = null;
private String type = null;
@@ -208,7 +209,7 @@ public abstract class GPXParser extends FileParser {
return null;
}
// cut out baseName
- final Matcher m = BASENAME_PATTERN.matcher(stringName);
+ final MatcherWrapper m = new MatcherWrapper(BASENAME_PATTERN, stringName);
if (!m.matches()) {
return null;
}
@@ -234,7 +235,7 @@ public abstract class GPXParser extends FileParser {
static Date parseDate(String inputUntrimmed) throws ParseException {
String input = inputUntrimmed.trim();
// remove milliseconds to reduce number of needed patterns
- final Matcher matcher = PATTERN_MILLISECONDS.matcher(input);
+ final MatcherWrapper matcher = new MatcherWrapper(PATTERN_MILLISECONDS, input);
input = matcher.replaceFirst("");
if (input.contains("Z")) {
return formatSimpleZ.parse(input);
@@ -247,7 +248,7 @@ public abstract class GPXParser extends FileParser {
}
@Override
- public Collection<cgCache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException {
+ public Collection<Geocache> parse(final InputStream stream, final CancellableHandler progressHandler) throws IOException, ParserException {
resetCache();
final RootElement root = new RootElement(namespace, "gpx");
final Element waypoint = root.getChild(namespace, "wpt");
@@ -287,7 +288,7 @@ public abstract class GPXParser extends FileParser {
// take the name as code, if nothing else is available
if (StringUtils.isBlank(cache.getGeocode())) {
if (StringUtils.isNotBlank(name)) {
- cache.setGeocode(name.trim().toUpperCase());
+ cache.setGeocode(name.trim());
}
}
@@ -311,8 +312,8 @@ public abstract class GPXParser extends FileParser {
// finally store the cache in the database
result.add(geocode);
- cgeoapplication.getInstance().saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
- cgeoapplication.getInstance().removeAllFromCache();
+ cgData.saveCache(cache, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.removeAllFromCache();
showProgressMessage(progressHandler, progressStream.getProgress());
} else if (StringUtils.isNotBlank(cache.getName())
&& StringUtils.containsIgnoreCase(type, "waypoint")) {
@@ -326,12 +327,11 @@ public abstract class GPXParser extends FileParser {
fixCache(cache);
if (cache.getName().length() > 2) {
- final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase();
-
+ final String cacheGeocodeForWaypoint = "GC" + cache.getName().substring(2).toUpperCase(Locale.US);
// lookup cache for waypoint in already parsed caches
- final cgCache cacheForWaypoint = cgeoapplication.getInstance().loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cacheForWaypoint = cgData.loadCache(cacheGeocodeForWaypoint, LoadFlags.LOAD_CACHE_OR_DB);
if (cacheForWaypoint != null) {
- final cgWaypoint waypoint = new cgWaypoint(cache.getShortdesc(), convertWaypointSym2Type(sym), false);
+ final Waypoint waypoint = new Waypoint(cache.getShortdesc(), convertWaypointSym2Type(sym), false);
waypoint.setId(-1);
waypoint.setGeocode(cacheGeocodeForWaypoint);
waypoint.setPrefix(cache.getName().substring(0, 2));
@@ -340,14 +340,14 @@ public abstract class GPXParser extends FileParser {
waypoint.setCoords(cache.getCoords());
waypoint.setNote(cache.getDescription());
- final ArrayList<cgWaypoint> mergedWayPoints = new ArrayList<cgWaypoint>();
+ final ArrayList<Waypoint> mergedWayPoints = new ArrayList<Waypoint>();
mergedWayPoints.addAll(cacheForWaypoint.getWaypoints());
- final ArrayList<cgWaypoint> newPoints = new ArrayList<cgWaypoint>();
+ final ArrayList<Waypoint> newPoints = new ArrayList<Waypoint>();
newPoints.add(waypoint);
- cgWaypoint.mergeWayPoints(newPoints, mergedWayPoints, true);
+ Waypoint.mergeWayPoints(newPoints, mergedWayPoints, true);
cacheForWaypoint.setWaypoints(newPoints, false);
- cgeoapplication.getInstance().saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB));
+ cgData.saveCache(cacheForWaypoint, EnumSet.of(SaveFlag.SAVE_DB));
showProgressMessage(progressHandler, progressStream.getProgress());
}
}
@@ -362,7 +362,7 @@ public abstract class GPXParser extends FileParser {
try {
cache.setHidden(parseDate(body));
} catch (Exception e) {
- Log.w("Failed to parse cache date: " + e.toString());
+ Log.w("Failed to parse cache date", e);
}
}
});
@@ -410,7 +410,7 @@ public abstract class GPXParser extends FileParser {
public void end(String body) {
final String[] content = body.split("\\|");
if (content.length > 0) {
- type = content[0].toLowerCase().trim();
+ type = content[0].toLowerCase(Locale.US).trim();
}
}
});
@@ -420,7 +420,7 @@ public abstract class GPXParser extends FileParser {
@Override
public void end(final String body) {
- sym = body.toLowerCase();
+ sym = body.toLowerCase(Locale.US);
if (sym.contains("geocache") && sym.contains("found")) {
cache.setFound(true);
}
@@ -432,14 +432,14 @@ public abstract class GPXParser extends FileParser {
@Override
public void end(String url) {
- final Matcher matcher = patternGuid.matcher(url);
+ final MatcherWrapper matcher = new MatcherWrapper(patternGuid, url);
if (matcher.matches()) {
final String guid = matcher.group(1);
if (StringUtils.isNotBlank(guid)) {
cache.setGuid(guid);
}
}
- final Matcher matcherCode = patternUrlGeocode.matcher(url);
+ final MatcherWrapper matcherCode = new MatcherWrapper(patternUrlGeocode, url);
if (matcherCode.matches()) {
String geocode = matcherCode.group(1);
cache.setGeocode(geocode);
@@ -526,7 +526,7 @@ public abstract class GPXParser extends FileParser {
@Override
public void end(String body) {
- cache.setType(CacheType.getByPattern(validate(body.toLowerCase())));
+ cache.setType(CacheType.getByPattern(validate(body)));
}
});
@@ -535,7 +535,7 @@ public abstract class GPXParser extends FileParser {
@Override
public void end(String body) {
- cache.setSize(CacheSize.getById(validate(body.toLowerCase())));
+ cache.setSize(CacheSize.getById(validate(body)));
}
});
@@ -578,7 +578,7 @@ public abstract class GPXParser extends FileParser {
try {
cache.setDifficulty(Float.parseFloat(body));
} catch (NumberFormatException e) {
- Log.w("Failed to parse difficulty: " + e.toString());
+ Log.w("Failed to parse difficulty", e);
}
}
});
@@ -591,7 +591,7 @@ public abstract class GPXParser extends FileParser {
try {
cache.setTerrain(Float.parseFloat(body));
} catch (NumberFormatException e) {
- Log.w("Failed to parse terrain: " + e.toString());
+ Log.w("Failed to parse terrain", e);
}
}
});
@@ -661,11 +661,11 @@ public abstract class GPXParser extends FileParser {
@Override
public void start(Attributes attrs) {
- trackable = new cgTrackable();
+ trackable = new Trackable();
try {
if (attrs.getIndex("ref") > -1) {
- trackable.setGeocode(attrs.getValue("ref").toUpperCase());
+ trackable.setGeocode(attrs.getValue("ref"));
}
} catch (Exception e) {
// nothing
@@ -679,7 +679,7 @@ public abstract class GPXParser extends FileParser {
public void end() {
if (StringUtils.isNotBlank(trackable.getGeocode()) && StringUtils.isNotBlank(trackable.getName())) {
if (cache.getInventory() == null) {
- cache.setInventory(new ArrayList<cgTrackable>());
+ cache.setInventory(new ArrayList<Trackable>());
}
cache.getInventory().add(trackable);
}
@@ -735,7 +735,7 @@ public abstract class GPXParser extends FileParser {
try {
log.date = parseDate(body).getTime();
} catch (Exception e) {
- Log.w("Failed to parse log date: " + e.toString());
+ Log.w("Failed to parse log date", e);
}
}
});
@@ -745,7 +745,7 @@ public abstract class GPXParser extends FileParser {
@Override
public void end(String body) {
- final String logType = validate(body).toLowerCase();
+ final String logType = validate(body);
log.type = LogType.getByType(logType);
}
});
@@ -772,9 +772,9 @@ public abstract class GPXParser extends FileParser {
try {
progressStream = new ProgressInputStream(stream);
Xml.parse(progressStream, Xml.Encoding.UTF_8, root.getContentHandler());
- return cgeoapplication.getInstance().loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
+ return cgData.loadCaches(result, EnumSet.of(LoadFlag.LOAD_DB_MINIMAL));
} catch (SAXException e) {
- Log.e("Cannot parse .gpx file as GPX " + version + ": could not parse XML - " + e.toString());
+ Log.w("Cannot parse .gpx file as GPX " + version + ": could not parse XML - ", e);
throw new ParserException("Cannot parse .gpx file as GPX " + version + ": could not parse XML", e);
}
}
@@ -783,7 +783,7 @@ public abstract class GPXParser extends FileParser {
* @param cache
* currently imported cache
*/
- protected void afterParsing(cgCache cache) {
+ protected void afterParsing(Geocache cache) {
// can be overridden by sub classes
}
@@ -806,17 +806,21 @@ public abstract class GPXParser extends FileParser {
static WaypointType convertWaypointSym2Type(final String sym) {
if ("parking area".equalsIgnoreCase(sym)) {
return WaypointType.PARKING;
- } else if ("stages of a multicache".equalsIgnoreCase(sym)) {
+ }
+ if ("stages of a multicache".equalsIgnoreCase(sym)) {
return WaypointType.STAGE;
- } else if ("question to answer".equalsIgnoreCase(sym)) {
+ }
+ if ("question to answer".equalsIgnoreCase(sym)) {
return WaypointType.PUZZLE;
- } else if ("trailhead".equalsIgnoreCase(sym)) {
+ }
+ if ("trailhead".equalsIgnoreCase(sym)) {
return WaypointType.TRAILHEAD;
- } else if ("final location".equalsIgnoreCase(sym)) {
+ }
+ if ("final location".equalsIgnoreCase(sym)) {
return WaypointType.FINAL;
}
// this is not fully correct, but lets also look for localized waypoint types
- for (WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN) {
+ for (WaypointType waypointType : WaypointType.ALL_TYPES_EXCEPT_OWN_AND_ORIGINAL) {
final String localized = waypointType.getL10n();
if (StringUtils.isNotEmpty(localized)) {
if (localized.equalsIgnoreCase(sym)) {
@@ -832,7 +836,7 @@ public abstract class GPXParser extends FileParser {
return;
}
final String trimmed = input.trim();
- final Matcher matcherGeocode = patternGeocode.matcher(trimmed);
+ final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, trimmed);
if (matcherGeocode.find()) {
final String geocode = matcherGeocode.group(1);
// a geocode should not be part of a word
@@ -854,7 +858,7 @@ public abstract class GPXParser extends FileParser {
desc = null;
cmt = null;
- cache = new cgCache(this);
+ cache = new Geocache(this);
for (int i = 0; i < userData.length; i++) {
userData[i] = null;
}
diff --git a/main/src/cgeo/geocaching/files/LocParser.java b/main/src/cgeo/geocaching/files/LocParser.java
index b17b203..fe290c3 100644
--- a/main/src/cgeo/geocaching/files/LocParser.java
+++ b/main/src/cgeo/geocaching/files/LocParser.java
@@ -1,14 +1,15 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.SearchResult;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.CacheSize;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import org.apache.commons.lang3.StringUtils;
@@ -22,7 +23,6 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class LocParser extends FileParser {
@@ -56,7 +56,7 @@ public final class LocParser extends FileParser {
private int listId;
public static void parseLoc(final SearchResult searchResult, final String fileContent) {
- final Map<String, cgCache> cidCoords = parseCoordinates(fileContent);
+ final Map<String, Geocache> cidCoords = parseCoordinates(fileContent);
// save found cache coordinates
final HashSet<String> contained = new HashSet<String>();
@@ -65,27 +65,27 @@ public final class LocParser extends FileParser {
contained.add(geocode);
}
}
- Set<cgCache> caches = cgeoapplication.getInstance().loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB);
- for (cgCache cache : caches) {
- cgCache coord = cidCoords.get(cache.getGeocode());
+ Set<Geocache> caches = cgData.loadCaches(contained, LoadFlags.LOAD_CACHE_OR_DB);
+ for (Geocache cache : caches) {
+ Geocache coord = cidCoords.get(cache.getGeocode());
copyCoordToCache(coord, cache);
}
}
- private static void copyCoordToCache(final cgCache coord, final cgCache cache) {
+ private static void copyCoordToCache(final Geocache coord, final Geocache cache) {
cache.setCoords(coord.getCoords());
cache.setDifficulty(coord.getDifficulty());
cache.setTerrain(coord.getTerrain());
cache.setSize(coord.getSize());
- cache.setGeocode(coord.getGeocode().toUpperCase());
+ cache.setGeocode(coord.getGeocode());
cache.setReliableLatLon(true);
if (StringUtils.isBlank(cache.getName())) {
cache.setName(coord.getName());
}
}
- static Map<String, cgCache> parseCoordinates(final String fileContent) {
- final Map<String, cgCache> coords = new HashMap<String, cgCache>();
+ static Map<String, Geocache> parseCoordinates(final String fileContent) {
+ final Map<String, Geocache> coords = new HashMap<String, Geocache>();
if (StringUtils.isBlank(fileContent)) {
return coords;
}
@@ -95,7 +95,7 @@ public final class LocParser extends FileParser {
// parse coordinates
for (String pointString : points) {
- final cgCache pointCoord = parseCache(pointString);
+ final Geocache pointCoord = parseCache(pointString);
if (StringUtils.isNotBlank(pointCoord.getGeocode())) {
coords.put(pointCoord.getGeocode(), pointCoord);
}
@@ -121,17 +121,17 @@ public final class LocParser extends FileParser {
}
@Override
- public Collection<cgCache> parse(InputStream stream, CancellableHandler progressHandler) throws IOException, ParserException {
+ public Collection<Geocache> parse(InputStream stream, CancellableHandler progressHandler) throws IOException, ParserException {
// TODO: progress reporting happens during reading stream only, not during parsing
String streamContent = readStream(stream, progressHandler).toString();
- final Map<String, cgCache> coords = parseCoordinates(streamContent);
- final List<cgCache> caches = new ArrayList<cgCache>();
- for (Entry<String, cgCache> entry : coords.entrySet()) {
- cgCache coord = entry.getValue();
+ final Map<String, Geocache> coords = parseCoordinates(streamContent);
+ final List<Geocache> caches = new ArrayList<Geocache>();
+ for (Entry<String, Geocache> entry : coords.entrySet()) {
+ Geocache coord = entry.getValue();
if (StringUtils.isBlank(coord.getGeocode()) || StringUtils.isBlank(coord.getName())) {
continue;
}
- cgCache cache = new cgCache();
+ Geocache cache = new Geocache();
cache.setReliableLatLon(true);
copyCoordToCache(coord, cache);
caches.add(cache);
@@ -140,20 +140,20 @@ public final class LocParser extends FileParser {
cache.setType(CacheType.UNKNOWN); // type is not given in the LOC file
cache.setListId(listId);
cache.setDetailed(true);
+ cache.store(null);
}
Log.i("Caches found in .loc file: " + caches.size());
return caches;
}
- public static cgCache parseCache(final String pointString) {
- final cgCache cache = new cgCache();
- final Matcher matcherGeocode = patternGeocode.matcher(pointString);
+ public static Geocache parseCache(final String pointString) {
+ final Geocache cache = new Geocache();
+ final MatcherWrapper matcherGeocode = new MatcherWrapper(patternGeocode, pointString);
if (matcherGeocode.find()) {
- final String geocode = matcherGeocode.group(1).trim().toUpperCase();
- cache.setGeocode(geocode.toUpperCase());
+ cache.setGeocode(matcherGeocode.group(1).trim());
}
- final Matcher matcherName = patternName.matcher(pointString);
+ final MatcherWrapper matcherName = new MatcherWrapper(patternName, pointString);
if (matcherName.find()) {
final String name = matcherName.group(1).trim();
cache.setName(StringUtils.substringBeforeLast(name, " by ").trim());
@@ -161,28 +161,32 @@ public final class LocParser extends FileParser {
cache.setName(cache.getGeocode());
}
- final Matcher matcherLat = patternLat.matcher(pointString);
- final Matcher matcherLon = patternLon.matcher(pointString);
+ final MatcherWrapper matcherLat = new MatcherWrapper(patternLat, pointString);
+ final MatcherWrapper matcherLon = new MatcherWrapper(patternLon, pointString);
if (matcherLat.find() && matcherLon.find()) {
cache.setCoords(parsePoint(matcherLat.group(1).trim(), matcherLon.group(1).trim()));
}
- final Matcher matcherDifficulty = patternDifficulty.matcher(pointString);
- if (matcherDifficulty.find()) {
- cache.setDifficulty(Float.parseFloat(matcherDifficulty.group(1).trim()));
- }
+ final MatcherWrapper matcherDifficulty = new MatcherWrapper(patternDifficulty, pointString);
+ try {
+ if (matcherDifficulty.find()) {
+ cache.setDifficulty(Float.parseFloat(matcherDifficulty.group(1).trim()));
+ }
- final Matcher matcherTerrain = patternTerrain.matcher(pointString);
- if (matcherTerrain.find()) {
- cache.setTerrain(Float.parseFloat(matcherTerrain.group(1).trim()));
- }
+ final MatcherWrapper matcherTerrain = new MatcherWrapper(patternTerrain, pointString);
+ if (matcherTerrain.find()) {
+ cache.setTerrain(Float.parseFloat(matcherTerrain.group(1).trim()));
+ }
- final Matcher matcherContainer = patternContainer.matcher(pointString);
- if (matcherContainer.find()) {
- final int size = Integer.parseInt(matcherContainer.group(1).trim());
- if (size >= 1 && size <= 8) {
- cache.setSize(SIZES[size - 1]);
+ final MatcherWrapper matcherContainer = new MatcherWrapper(patternContainer, pointString);
+ if (matcherContainer.find()) {
+ final int size = Integer.parseInt(matcherContainer.group(1).trim());
+ if (size >= 1 && size <= 8) {
+ cache.setSize(SIZES[size - 1]);
+ }
}
+ } catch (NumberFormatException e) {
+ Log.e("LocParser.parseCache", e);
}
return cache;
diff --git a/main/src/cgeo/geocaching/files/LocalStorage.java b/main/src/cgeo/geocaching/files/LocalStorage.java
index c392564..f59f15c 100644
--- a/main/src/cgeo/geocaching/files/LocalStorage.java
+++ b/main/src/cgeo/geocaching/files/LocalStorage.java
@@ -305,9 +305,9 @@ public class LocalStorage {
}
private static boolean copy(final InputStream input, final OutputStream output) {
- final byte[] buffer = new byte[4096];
- int length;
try {
+ int length;
+ final byte[] buffer = new byte[4096];
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
@@ -363,7 +363,7 @@ public class LocalStorage {
Log.w("LocalStorage.deleteFilesPrefix: Can't delete file " + file.getName());
}
} catch (Exception e) {
- Log.e("LocalStorage.deleteFilesPrefix: " + e.toString());
+ Log.e("LocalStorage.deleteFilesPrefix", e);
}
}
}
diff --git a/main/src/cgeo/geocaching/files/ParserException.java b/main/src/cgeo/geocaching/files/ParserException.java
index 5aa152c..c0076cc 100644
--- a/main/src/cgeo/geocaching/files/ParserException.java
+++ b/main/src/cgeo/geocaching/files/ParserException.java
@@ -13,10 +13,6 @@ public class ParserException extends Exception {
super(detailMessage);
}
- public ParserException(Throwable throwable) {
- super(throwable);
- }
-
public ParserException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
diff --git a/main/src/cgeo/geocaching/files/SimpleDirChooser.java b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
index 404777a..7520e2e 100644
--- a/main/src/cgeo/geocaching/files/SimpleDirChooser.java
+++ b/main/src/cgeo/geocaching/files/SimpleDirChooser.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.files;
+import cgeo.geocaching.Intents;
import cgeo.geocaching.R;
import cgeo.geocaching.activity.ActivityMixin;
@@ -8,6 +9,7 @@ import org.apache.commons.lang3.StringUtils;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
@@ -18,7 +20,6 @@ import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
-import android.widget.ListView;
import android.widget.TextView;
import java.io.File;
@@ -31,8 +32,6 @@ import java.util.List;
* Dialog for choosing a file or directory.
*/
public class SimpleDirChooser extends ListActivity {
- public static final String EXTRA_CHOSEN_DIR = "chosenDir";
- public static final String START_DIR = "start_dir";
private static final String PARENT_DIR = ".. ";
private File currentDir;
private FileArrayAdapter adapter;
@@ -43,7 +42,7 @@ public class SimpleDirChooser extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle extras = getIntent().getExtras();
- currentDir = dirContaining(extras.getString(START_DIR));
+ currentDir = dirContaining(extras.getString(Intents.EXTRA_START_DIR));
ActivityMixin.setTheme(this);
setContentView(R.layout.simple_dir_chooser);
@@ -57,10 +56,8 @@ public class SimpleDirChooser extends ListActivity {
okButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- Intent intent = new Intent();
- String chosenDirName = File.separator + adapter.getItem(lastPosition).getName();
- intent.putExtra(EXTRA_CHOSEN_DIR, currentDir.getAbsolutePath() + chosenDirName);
- setResult(RESULT_OK, intent);
+ setResult(RESULT_OK, new Intent()
+ .setData(Uri.fromFile(new File(currentDir, adapter.getItem(lastPosition).getName()))));
finish();
}
});
@@ -107,11 +104,6 @@ public class SimpleDirChooser extends ListActivity {
this.setListAdapter(adapter);
}
- @Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
- super.onListItemClick(l, v, position, id);
- }
-
public class FileArrayAdapter extends ArrayAdapter<Option> {
private Context content;
@@ -206,7 +198,7 @@ public class SimpleDirChooser extends ListActivity {
}
}
- public class Option implements Comparable<Option> {
+ public static class Option implements Comparable<Option> {
private final String name;
private final String path;
private boolean checked = false;
diff --git a/main/src/cgeo/geocaching/filter/AbstractFilter.java b/main/src/cgeo/geocaching/filter/AbstractFilter.java
index 44d6d3f..bc99959 100644
--- a/main/src/cgeo/geocaching/filter/AbstractFilter.java
+++ b/main/src/cgeo/geocaching/filter/AbstractFilter.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import java.util.ArrayList;
import java.util.List;
@@ -8,14 +8,14 @@ import java.util.List;
abstract class AbstractFilter implements IFilter {
private final String name;
- public AbstractFilter(String name) {
+ protected AbstractFilter(String name) {
this.name = name;
}
@Override
- public void filter(List<cgCache> list) {
- final List<cgCache> itemsToRemove = new ArrayList<cgCache>();
- for (cgCache item : list) {
+ public void filter(List<Geocache> list) {
+ final List<Geocache> itemsToRemove = new ArrayList<Geocache>();
+ for (Geocache item : list) {
if (!accepts(item)) {
itemsToRemove.add(item);
}
diff --git a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java
index ff3fce5..e84174a 100644
--- a/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AbstractRangeFilter.java
@@ -8,8 +8,8 @@ abstract class AbstractRangeFilter extends AbstractFilter {
protected final float rangeMin;
protected final float rangeMax;
- public AbstractRangeFilter(int ressourceId, int range) {
- super(cgeoapplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : String.valueOf(range) + " + " + String.format("%.1f", range + 0.5)));
+ protected AbstractRangeFilter(int ressourceId, int range) {
+ super(cgeoapplication.getInstance().getResources().getString(ressourceId) + ' ' + (range == 5 ? '5' : range + " + " + String.format("%.1f", range + 0.5)));
this.rangeMin = range;
rangeMax = rangeMin + 1f;
}
diff --git a/main/src/cgeo/geocaching/filter/AttributeFilter.java b/main/src/cgeo/geocaching/filter/AttributeFilter.java
index 2565178..4b6f382 100644
--- a/main/src/cgeo/geocaching/filter/AttributeFilter.java
+++ b/main/src/cgeo/geocaching/filter/AttributeFilter.java
@@ -1,7 +1,8 @@
package cgeo.geocaching.filter;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.LoadFlags.LoadFlag;
@@ -33,8 +34,8 @@ class AttributeFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final cgCache cache) {
- cgCache fullCache = cgeoapplication.getInstance().loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
+ public boolean accepts(final Geocache cache) {
+ Geocache fullCache = cgData.loadCache(cache.getGeocode(), EnumSet.of(LoadFlag.LOAD_ATTRIBUTES));
if (fullCache == null) {
fullCache = cache;
}
diff --git a/main/src/cgeo/geocaching/filter/DifficultyFilter.java b/main/src/cgeo/geocaching/filter/DifficultyFilter.java
index 368c20f..c0ec61a 100644
--- a/main/src/cgeo/geocaching/filter/DifficultyFilter.java
+++ b/main/src/cgeo/geocaching/filter/DifficultyFilter.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
import java.util.ArrayList;
@@ -12,7 +12,7 @@ class DifficultyFilter extends AbstractRangeFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return rangeMin <= cache.getDifficulty() && cache.getDifficulty() < rangeMax;
}
diff --git a/main/src/cgeo/geocaching/filter/FilterUserInterface.java b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
index 230bc91..e2472fd 100644
--- a/main/src/cgeo/geocaching/filter/FilterUserInterface.java
+++ b/main/src/cgeo/geocaching/filter/FilterUserInterface.java
@@ -73,7 +73,7 @@ public final class FilterUserInterface {
public void selectFilter(final RunnableWithArgument<IFilter> runAfterwards) {
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(R.string.caches_filter);
+ builder.setTitle(R.string.caches_filter_title);
final ArrayAdapter<FactoryEntry> adapter = new ArrayAdapter<FactoryEntry>(activity, android.R.layout.select_dialog_item, registry);
diff --git a/main/src/cgeo/geocaching/filter/IFilter.java b/main/src/cgeo/geocaching/filter/IFilter.java
index abc2d50..4a428f8 100644
--- a/main/src/cgeo/geocaching/filter/IFilter.java
+++ b/main/src/cgeo/geocaching/filter/IFilter.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import java.util.List;
@@ -12,7 +12,7 @@ public interface IFilter {
* @param cache
* @return true if the filter accepts the cache, false otherwise
*/
- public abstract boolean accepts(final cgCache cache);
+ public abstract boolean accepts(final Geocache cache);
- public void filter(final List<cgCache> list);
+ public void filter(final List<Geocache> list);
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/filter/ModifiedFilter.java b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
index f74bb4d..f3e57de 100644
--- a/main/src/cgeo/geocaching/filter/ModifiedFilter.java
+++ b/main/src/cgeo/geocaching/filter/ModifiedFilter.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
class ModifiedFilter extends AbstractFilter implements IFilterFactory {
@@ -11,7 +11,7 @@ class ModifiedFilter extends AbstractFilter implements IFilterFactory {
}
@Override
- public boolean accepts(final cgCache cache) {
+ public boolean accepts(final Geocache cache) {
// modified on GC
return cache.hasUserModifiedCoords() || cache.hasFinalDefined();
}
diff --git a/main/src/cgeo/geocaching/filter/SizeFilter.java b/main/src/cgeo/geocaching/filter/SizeFilter.java
index b08c2ae..7a34c83 100644
--- a/main/src/cgeo/geocaching/filter/SizeFilter.java
+++ b/main/src/cgeo/geocaching/filter/SizeFilter.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheSize;
import java.util.ArrayList;
@@ -14,7 +14,7 @@ class SizeFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cacheSize == cache.getSize();
}
diff --git a/main/src/cgeo/geocaching/filter/StateFilter.java b/main/src/cgeo/geocaching/filter/StateFilter.java
index f51329a..0df47c1 100644
--- a/main/src/cgeo/geocaching/filter/StateFilter.java
+++ b/main/src/cgeo/geocaching/filter/StateFilter.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.filter;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import android.content.res.Resources;
@@ -25,7 +25,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cache.isFound();
}
@@ -37,7 +37,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cache.isArchived();
}
}
@@ -48,7 +48,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cache.isDisabled();
}
}
@@ -59,7 +59,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cache.isPremiumMembersOnly();
}
}
@@ -70,7 +70,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return !cache.isPremiumMembersOnly();
}
}
@@ -81,7 +81,7 @@ abstract class StateFilter extends AbstractFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cache.isLogOffline();
}
}
diff --git a/main/src/cgeo/geocaching/filter/TerrainFilter.java b/main/src/cgeo/geocaching/filter/TerrainFilter.java
index 5cee87e..f7703d5 100644
--- a/main/src/cgeo/geocaching/filter/TerrainFilter.java
+++ b/main/src/cgeo/geocaching/filter/TerrainFilter.java
@@ -2,7 +2,7 @@ package cgeo.geocaching.filter;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import java.util.ArrayList;
@@ -13,7 +13,7 @@ class TerrainFilter extends AbstractRangeFilter {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return rangeMin <= cache.getTerrain() && cache.getTerrain() < rangeMax;
}
diff --git a/main/src/cgeo/geocaching/filter/TrackablesFilter.java b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
index 90def5b..3225daa 100644
--- a/main/src/cgeo/geocaching/filter/TrackablesFilter.java
+++ b/main/src/cgeo/geocaching/filter/TrackablesFilter.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.filter;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.cgeoapplication;
class TrackablesFilter extends AbstractFilter implements IFilterFactory {
@@ -10,7 +10,7 @@ class TrackablesFilter extends AbstractFilter implements IFilterFactory {
}
@Override
- public boolean accepts(cgCache cache) {
+ public boolean accepts(Geocache cache) {
return cache.hasTrackables();
}
diff --git a/main/src/cgeo/geocaching/filter/TypeFilter.java b/main/src/cgeo/geocaching/filter/TypeFilter.java
index 05b97e0..eeab552 100644
--- a/main/src/cgeo/geocaching/filter/TypeFilter.java
+++ b/main/src/cgeo/geocaching/filter/TypeFilter.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.filter;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.enumerations.CacheType;
import java.util.ArrayList;
@@ -14,7 +14,7 @@ class TypeFilter extends AbstractFilter {
}
@Override
- public boolean accepts(final cgCache cache) {
+ public boolean accepts(final Geocache cache) {
return cacheType == cache.getType();
}
diff --git a/main/src/cgeo/geocaching/gcvote/GCVote.java b/main/src/cgeo/geocaching/gcvote/GCVote.java
index 5a00009..a053f31 100644
--- a/main/src/cgeo/geocaching/gcvote/GCVote.java
+++ b/main/src/cgeo/geocaching/gcvote/GCVote.java
@@ -1,21 +1,22 @@
package cgeo.geocaching.gcvote;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.LeastRecentlyUsedMap;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class GCVote {
@@ -38,31 +39,16 @@ public final class GCVote {
* @return
*/
public static GCVoteRating getRating(String guid, String geocode) {
- List<String> guids = null;
- List<String> geocodes = null;
-
- if (StringUtils.isNotBlank(guid)) {
-
- GCVoteRating rating = ratingsCache.get(guid);
- if (rating != null) {
- return rating;
- }
- guids = new ArrayList<String>();
- guids.add(guid);
- } else if (StringUtils.isNotBlank(geocode)) {
- geocodes = new ArrayList<String>();
- geocodes.add(geocode);
- } else {
- return null;
+ if (StringUtils.isNotBlank(guid) && ratingsCache.containsKey(guid)) {
+ return ratingsCache.get(guid);
}
- final Map<String, GCVoteRating> ratings = getRating(guids, geocodes);
-
- if (MapUtils.isEmpty(ratings)) {
- return null;
- }
+ final Map<String, GCVoteRating> ratings = getRating(singletonOrNull(guid), singletonOrNull(geocode));
+ return MapUtils.isNotEmpty(ratings) ? ratings.values().iterator().next() : null;
+ }
- return ratings.values().iterator().next();
+ private static List<String> singletonOrNull(final String item) {
+ return StringUtils.isNotBlank(item) ? Collections.singletonList(item) : null;
}
/**
@@ -98,17 +84,16 @@ public final class GCVote {
return null;
}
- String voteData;
- final Matcher matcherVoteElement = patternVoteElement.matcher(page);
+ final MatcherWrapper matcherVoteElement = new MatcherWrapper(patternVoteElement, page);
while (matcherVoteElement.find()) {
- voteData = matcherVoteElement.group(1);
+ String voteData = matcherVoteElement.group(1);
if (voteData == null) {
continue;
}
String guid = null;
try {
- final Matcher matcherGuid = patternGuid.matcher(voteData);
+ final MatcherWrapper matcherGuid = new MatcherWrapper(patternGuid, voteData);
if (matcherGuid.find()) {
if (matcherGuid.groupCount() > 0) {
guid = matcherGuid.group(1);
@@ -123,7 +108,7 @@ public final class GCVote {
boolean loggedIn = false;
try {
- final Matcher matcherLoggedIn = patternLogIn.matcher(page);
+ final MatcherWrapper matcherLoggedIn = new MatcherWrapper(patternLogIn, page);
if (matcherLoggedIn.find()) {
if (matcherLoggedIn.groupCount() > 0) {
if (matcherLoggedIn.group(1).equalsIgnoreCase("true")) {
@@ -137,7 +122,7 @@ public final class GCVote {
float rating = 0;
try {
- final Matcher matcherRating = patternRating.matcher(voteData);
+ final MatcherWrapper matcherRating = new MatcherWrapper(patternRating, voteData);
if (matcherRating.find()) {
rating = Float.parseFloat(matcherRating.group(1));
}
@@ -150,7 +135,7 @@ public final class GCVote {
int votes = -1;
try {
- final Matcher matcherVotes = patternVotes.matcher(voteData);
+ final MatcherWrapper matcherVotes = new MatcherWrapper(patternVotes, voteData);
if (matcherVotes.find()) {
votes = Integer.parseInt(matcherVotes.group(1));
}
@@ -164,7 +149,7 @@ public final class GCVote {
float myVote = 0;
if (loggedIn) {
try {
- final Matcher matcherVote = patternVote.matcher(voteData);
+ final MatcherWrapper matcherVote = new MatcherWrapper(patternVote, voteData);
if (matcherVote.find()) {
myVote = Float.parseFloat(matcherVote.group(1));
}
@@ -180,7 +165,7 @@ public final class GCVote {
}
}
} catch (Exception e) {
- Log.e("GCVote.getRating: " + e.toString());
+ Log.e("GCVote.getRating", e);
}
return ratings;
@@ -193,7 +178,7 @@ public final class GCVote {
* @param vote
* @return
*/
- public static boolean setRating(cgCache cache, double vote) {
+ public static boolean setRating(Geocache cache, double vote) {
if (!cache.supportsGCVote()) {
return false;
}
@@ -222,13 +207,13 @@ public final class GCVote {
return result.trim().equalsIgnoreCase("ok");
}
- public static void loadRatings(ArrayList<cgCache> caches) {
+ public static void loadRatings(ArrayList<Geocache> caches) {
if (!Settings.isRatingWanted()) {
return;
}
final ArrayList<String> guids = new ArrayList<String>(caches.size());
- for (final cgCache cache : caches) {
+ for (final Geocache cache : caches) {
String guid = cache.getGuid();
if (StringUtils.isNotBlank(guid)) {
guids.add(guid);
@@ -244,7 +229,7 @@ public final class GCVote {
if (MapUtils.isNotEmpty(ratings)) {
// save found cache coordinates
- for (cgCache cache : caches) {
+ for (Geocache cache : caches) {
if (ratings.containsKey(cache.getGuid())) {
GCVoteRating rating = ratings.get(cache.getGuid());
@@ -255,7 +240,7 @@ public final class GCVote {
}
}
} catch (Exception e) {
- Log.e("GCvote.loadRatings: " + e.toString());
+ Log.e("GCvote.loadRatings", e);
}
}
}
diff --git a/main/src/cgeo/geocaching/geopoint/DistanceParser.java b/main/src/cgeo/geocaching/geopoint/DistanceParser.java
index 5f02895..e1692f4 100644
--- a/main/src/cgeo/geocaching/geopoint/DistanceParser.java
+++ b/main/src/cgeo/geocaching/geopoint/DistanceParser.java
@@ -1,6 +1,10 @@
package cgeo.geocaching.geopoint;
-import java.util.regex.Matcher;
+import cgeo.geocaching.utils.MatcherWrapper;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Locale;
import java.util.regex.Pattern;
public final class DistanceParser {
@@ -19,16 +23,16 @@ public final class DistanceParser {
* if the given number is invalid
*/
public static float parseDistance(String distanceText, final boolean metricUnit) {
- final Matcher matcher = pattern.matcher(distanceText);
+ final MatcherWrapper matcher = new MatcherWrapper(pattern, distanceText);
if (!matcher.find()) {
throw new NumberFormatException(distanceText);
}
final float value = Float.parseFloat(matcher.group(1).replace(',', '.'));
- final String unit = matcher.group(2).toLowerCase();
+ final String unit = matcher.group(2).toLowerCase(Locale.US);
- if (unit.equals("m") || (unit.length() == 0 && metricUnit)) {
+ if (unit.equals("m") || (StringUtils.isEmpty(unit) && metricUnit)) {
return value / 1000;
}
if (unit.equals("km")) {
diff --git a/main/src/cgeo/geocaching/geopoint/Geopoint.java b/main/src/cgeo/geocaching/geopoint/Geopoint.java
index 00dec7f..a4821b9 100644
--- a/main/src/cgeo/geocaching/geopoint/Geopoint.java
+++ b/main/src/cgeo/geocaching/geopoint/Geopoint.java
@@ -23,6 +23,8 @@ public final class Geopoint implements ICoordinates, Parcelable {
public static final double rad2deg = 180 / Math.PI;
public static final float erad = 6371.0f;
+ public static final Geopoint ZERO = new Geopoint(0.0, 0.0);
+
private final double latitude;
private final double longitude;
@@ -140,7 +142,7 @@ public final class Geopoint implements ICoordinates, Parcelable {
* @param lonSecFrac
*/
public Geopoint(final String latDir, final String latDeg, final String latMin, final String latSec, final String latSecFrac,
- final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) {
+ final String lonDir, final String lonDeg, final String lonMin, final String lonSec, final String lonSecFrac) {
this(latDir + " " + latDeg + " " + latMin + " " + latSec + "." + addZeros(latSecFrac, 3),
lonDir + " " + lonDeg + " " + lonMin + " " + lonSec + "." + addZeros(lonSecFrac, 3));
}
@@ -253,7 +255,7 @@ public final class Geopoint implements ICoordinates, Parcelable {
if (this == obj) {
return true;
}
- if (obj == null || !(obj instanceof Geopoint)) {
+ if (!(obj instanceof Geopoint)) {
return false;
}
final Geopoint gp = (Geopoint) obj;
@@ -274,8 +276,7 @@ public final class Geopoint implements ICoordinates, Parcelable {
* tolerance in km
* @return true if similar, false otherwise
*/
- public boolean isEqualTo(Geopoint gp, double tolerance)
- {
+ public boolean isEqualTo(Geopoint gp, double tolerance) {
return null != gp && distanceTo(gp) <= tolerance;
}
@@ -287,42 +288,35 @@ public final class Geopoint implements ICoordinates, Parcelable {
* @see GeopointFormatter
* @return formatted coordinates
*/
- public String format(GeopointFormatter.Format format)
- {
+ public String format(GeopointFormatter.Format format) {
return GeopointFormatter.format(format, this);
}
/**
* Returns formatted coordinates with default format.
* Default format is decimalminutes, e.g. N 52° 36.123 E 010° 03.456
- *
+ *
* @return formatted coordinates
*/
@Override
- public String toString()
- {
+ public String toString() {
return format(GeopointFormatter.Format.LAT_LON_DECMINUTE);
}
- abstract public static class GeopointException
- extends RuntimeException
- {
+ abstract public static class GeopointException extends NumberFormatException {
private static final long serialVersionUID = 1L;
- public GeopointException(String msg)
+ protected GeopointException(String msg)
{
super(msg);
}
}
- public static class ParseException
- extends GeopointException
- {
+ public static class ParseException extends GeopointException {
private static final long serialVersionUID = 1L;
public final int resource;
- public ParseException(final String msg, final GeopointParser.LatLon faulty)
- {
+ public ParseException(final String msg, final GeopointParser.LatLon faulty) {
super(msg);
resource = faulty == GeopointParser.LatLon.LAT ? R.string.err_parse_lat : R.string.err_parse_lon;
}
@@ -350,7 +344,7 @@ public final class Geopoint implements ICoordinates, Parcelable {
return result.getDouble("elevation");
}
} catch (Exception e) {
- Log.w("cgBase.getElevation: " + e.toString());
+ Log.w("cgBase.getElevation", e);
}
return null;
diff --git a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java b/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java
index c706e77..0e676ce 100644
--- a/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java
+++ b/main/src/cgeo/geocaching/geopoint/GeopointFormatter.java
@@ -10,7 +10,7 @@ public class GeopointFormatter
/**
* Predefined formats.
*/
- public static enum Format {
+ public enum Format {
/** Example: "10,123456 -0,123456" */
LAT_LON_DECDEGREE,
@@ -61,13 +61,13 @@ public class GeopointFormatter
switch (format) {
case LAT_LON_DECDEGREE:
- return String.format("%.6f %.6f", latSigned, lonSigned);
+ return String.format(Locale.getDefault(), "%.6f %.6f", latSigned, lonSigned);
case LAT_LON_DECDEGREE_COMMA:
return String.format((Locale) null, "%.6f,%.6f", latSigned, lonSigned);
case LAT_LON_DECMINUTE:
- return String.format("%c %02d° %06.3f · %c %03d° %06.3f",
+ return String.format(Locale.getDefault(), "%c %02d° %06.3f · %c %03d° %06.3f",
gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw(), gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw());
case LAT_LON_DECMINUTE_RAW:
@@ -75,7 +75,7 @@ public class GeopointFormatter
gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw(), gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw());
case LAT_LON_DECSECOND:
- return String.format("%c %02d° %02d' %06.3f\" · %c %03d° %02d' %06.3f\"",
+ return String.format(Locale.getDefault(), "%c %02d° %02d' %06.3f\" · %c %03d° %02d' %06.3f\"",
gp.getLatDir(), gp.getLatDeg(), gp.getLatMin(), gp.getLatSecRaw(),
gp.getLonDir(), gp.getLonDeg(), gp.getLonMin(), gp.getLonSecRaw());
@@ -83,23 +83,22 @@ public class GeopointFormatter
return String.format((Locale) null, "%.6f", latSigned);
case LAT_DECMINUTE:
- return String.format("%c %02d° %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw());
+ return String.format(Locale.getDefault(), "%c %02d° %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw());
case LAT_DECMINUTE_RAW:
- return String.format("%c %02d %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw());
+ return String.format(Locale.getDefault(), "%c %02d %06.3f", gp.getLatDir(), gp.getLatDeg(), gp.getLatMinRaw());
case LON_DECDEGREE_RAW:
return String.format((Locale) null, "%.6f", lonSigned);
case LON_DECMINUTE:
- return String.format("%c %03d° %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw());
+ return String.format(Locale.getDefault(), "%c %03d° %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw());
case LON_DECMINUTE_RAW:
- return String.format("%c %03d %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw());
+ return String.format(Locale.getDefault(), "%c %03d %06.3f", gp.getLonDir(), gp.getLonDeg(), gp.getLonMinRaw());
+ default:
+ throw new IllegalArgumentException();
}
-
- // Keep the compiler happy even though it cannot happen
- return null;
}
}
diff --git a/main/src/cgeo/geocaching/geopoint/GeopointParser.java b/main/src/cgeo/geocaching/geopoint/GeopointParser.java
index 7604b9d..ba86e70 100644
--- a/main/src/cgeo/geocaching/geopoint/GeopointParser.java
+++ b/main/src/cgeo/geocaching/geopoint/GeopointParser.java
@@ -1,15 +1,17 @@
package cgeo.geocaching.geopoint;
+import cgeo.geocaching.utils.MatcherWrapper;
+
import org.apache.commons.lang3.StringUtils;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Parse coordinates.
*/
class GeopointParser {
+
private static class ResultWrapper {
final double result;
final int matcherPos;
@@ -22,12 +24,13 @@ class GeopointParser {
}
}
- // ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 )
- private static final Pattern patternLat = Pattern.compile("\\b([NS])\\s*(\\d+)°?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
- private static final Pattern patternLon = Pattern.compile("\\b([WE])\\s*(\\d+)°?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
+ // ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 )
+ private static final Pattern PATTERN_LAT = Pattern.compile("\\b([NS])\\s*(\\d+)°?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
+ private static final Pattern PATTERN_LON = Pattern.compile("\\b([WE])\\s*(\\d+)°?(?:\\s*(\\d+)(?:[.,](\\d+)|'?\\s*(\\d+(?:[.,]\\d+)?)(?:''|\")?)?)?", Pattern.CASE_INSENSITIVE);
- enum LatLon
- {
+ private static final Pattern PATTERN_BAD_BLANK = Pattern.compile("(\\d)[,.] (\\d{2,})");
+
+ enum LatLon {
LAT,
LON
}
@@ -52,8 +55,7 @@ class GeopointParser {
* @throws Geopoint.ParseException
* if lat or lon could not be parsed
*/
- public static Geopoint parse(final String text)
- {
+ public static Geopoint parse(final String text) {
final ResultWrapper latitudeWrapper = parseHelper(text, LatLon.LAT);
final double lat = latitudeWrapper.result;
// cut away the latitude part when parsing the longitude
@@ -89,8 +91,7 @@ class GeopointParser {
* @throws Geopoint.ParseException
* if lat or lon could not be parsed
*/
- public static Geopoint parse(final String latitude, final String longitude)
- {
+ public static Geopoint parse(final String latitude, final String longitude) {
final double lat = parseLatitude(latitude);
final double lon = parseLongitude(longitude);
@@ -101,11 +102,13 @@ class GeopointParser {
* (non JavaDoc)
* Helper for coordinates-parsing.
*/
- private static ResultWrapper parseHelper(final String text, final LatLon latlon)
- {
+ private static ResultWrapper parseHelper(final String text, final LatLon latlon) {
+
+ MatcherWrapper matcher = new MatcherWrapper(PATTERN_BAD_BLANK, text);
+ String replaceSpaceAfterComma = matcher.replaceAll("$1.$2");
- final Pattern pattern = LatLon.LAT == latlon ? patternLat : patternLon;
- final Matcher matcher = pattern.matcher(text);
+ final Pattern pattern = LatLon.LAT == latlon ? PATTERN_LAT : PATTERN_LON;
+ matcher = new MatcherWrapper(pattern, replaceSpaceAfterComma);
if (matcher.find()) {
final double sign = matcher.group(1).equalsIgnoreCase("S") || matcher.group(1).equalsIgnoreCase("W") ? -1.0 : 1.0;
@@ -153,8 +156,7 @@ class GeopointParser {
* @throws Geopoint.ParseException
* if latitude could not be parsed
*/
- public static double parseLatitude(final String text)
- {
+ public static double parseLatitude(final String text) {
return parseHelper(text, LatLon.LAT).result;
}
@@ -168,8 +170,7 @@ class GeopointParser {
* @throws Geopoint.ParseException
* if longitude could not be parsed
*/
- public static double parseLongitude(final String text)
- {
+ public static double parseLongitude(final String text) {
return parseHelper(text, LatLon.LON).result;
}
}
diff --git a/main/src/cgeo/geocaching/geopoint/Viewport.java b/main/src/cgeo/geocaching/geopoint/Viewport.java
index 97ee21d..4aca538 100644
--- a/main/src/cgeo/geocaching/geopoint/Viewport.java
+++ b/main/src/cgeo/geocaching/geopoint/Viewport.java
@@ -164,7 +164,10 @@ public class Viewport {
@Override
public boolean equals(final Object other) {
- if (other == null || !(other instanceof Viewport)) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Viewport)) {
return false;
}
final Viewport vp = (Viewport) other;
diff --git a/main/src/cgeo/geocaching/loaders/UrlLoader.java b/main/src/cgeo/geocaching/loaders/UrlLoader.java
new file mode 100644
index 0000000..abafd5f
--- /dev/null
+++ b/main/src/cgeo/geocaching/loaders/UrlLoader.java
@@ -0,0 +1,35 @@
+package cgeo.geocaching.loaders;
+
+import cgeo.geocaching.network.Network;
+import cgeo.geocaching.network.Parameters;
+import cgeo.geocaching.utils.Log;
+
+import android.content.Context;
+import android.support.v4.content.AsyncTaskLoader;
+
+public class UrlLoader extends AsyncTaskLoader<String> {
+
+ final private String url;
+ final private Parameters params;
+
+ public UrlLoader(final Context context, final String url, final Parameters params) {
+ super(context);
+ this.url = url;
+ this.params = params;
+ }
+
+ @Override
+ protected void onStartLoading() {
+ forceLoad();
+ }
+
+ @Override
+ public String loadInBackground() {
+ try {
+ return Network.getResponseData(Network.getRequest(url, params));
+ } catch (final Exception e) {
+ Log.w("cgeovisit.UrlLoader.loadInBackground", e);
+ return null;
+ }
+ }
+}
diff --git a/main/src/cgeo/geocaching/maps/AbstractMapSource.java b/main/src/cgeo/geocaching/maps/AbstractMapSource.java
index 90a61d2..1d219d3 100644
--- a/main/src/cgeo/geocaching/maps/AbstractMapSource.java
+++ b/main/src/cgeo/geocaching/maps/AbstractMapSource.java
@@ -9,7 +9,7 @@ public abstract class AbstractMapSource implements MapSource {
private final MapProvider mapProvider;
private final String id;
- public AbstractMapSource(final String id, final MapProvider mapProvider, final String name) {
+ protected AbstractMapSource(final String id, final MapProvider mapProvider, final String name) {
this.id = id;
this.mapProvider = mapProvider;
this.name = name;
diff --git a/main/src/cgeo/geocaching/maps/CGeoMap.java b/main/src/cgeo/geocaching/maps/CGeoMap.java
index e48ca70..c917a37 100644
--- a/main/src/cgeo/geocaching/maps/CGeoMap.java
+++ b/main/src/cgeo/geocaching/maps/CGeoMap.java
@@ -1,15 +1,14 @@
package cgeo.geocaching.maps;
import cgeo.geocaching.DirectionProvider;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
-import cgeo.geocaching.IWaypoint;
-import cgeo.geocaching.LiveMapInfo;
import cgeo.geocaching.R;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.Settings;
import cgeo.geocaching.StoredList;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.cgeocaches;
import cgeo.geocaching.activity.ActivityMixin;
@@ -31,11 +30,13 @@ import cgeo.geocaching.maps.interfaces.MapProvider;
import cgeo.geocaching.maps.interfaces.MapSource;
import cgeo.geocaching.maps.interfaces.MapViewImpl;
import cgeo.geocaching.maps.interfaces.OnMapDragListener;
+import cgeo.geocaching.ui.dialog.LiveMapInfoDialogBuilder;
import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.CancellableHandler;
import cgeo.geocaching.utils.GeoDirHandler;
import cgeo.geocaching.utils.LeastRecentlyUsedSet;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.RunnableWithArgument;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@@ -177,9 +178,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
/** Count of caches currently visible */
private int cachesCnt = 0;
/** List of caches in the viewport */
- private LeastRecentlyUsedSet<cgCache> caches = null;
+ private LeastRecentlyUsedSet<Geocache> caches = null;
/** List of waypoints in the viewport */
- private final LeastRecentlyUsedSet<cgWaypoint> waypoints = new LeastRecentlyUsedSet<cgWaypoint>(MAX_CACHES);
+ private final LeastRecentlyUsedSet<Waypoint> waypoints = new LeastRecentlyUsedSet<Waypoint>(MAX_CACHES);
// storing for offline
private ProgressDialog waitDialog = null;
private int detailTotal = 0;
@@ -226,7 +227,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
countVisibleCaches();
- if (caches != null && caches.size() > 0 && !mapTitle.contains("[")) {
+ if (caches != null && !caches.isEmpty() && !mapTitle.contains("[")) {
title.append(" [").append(cachesCnt);
if (cachesCnt != caches.size()) {
title.append('/').append(caches.size());
@@ -335,13 +336,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
protected void countVisibleCaches() {
- final List<cgCache> protectedCaches = caches.getAsList();
+ final List<Geocache> protectedCaches = caches.getAsList();
int count = 0;
- if (protectedCaches.size() > 0) {
+ if (!protectedCaches.isEmpty()) {
final Viewport viewport = mapView.getViewport();
- for (final cgCache cache : protectedCaches) {
+ for (final Geocache cache : protectedCaches) {
if (cache != null && cache.getCoords() != null) {
if (viewport.contains(cache)) {
count++;
@@ -368,8 +369,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
activity = this.getActivity();
app = (cgeoapplication) activity.getApplication();
- int countBubbleCnt = app.getAllStoredCachesCount(true, CacheType.ALL);
- caches = new LeastRecentlyUsedSet<cgCache>(MAX_CACHES + countBubbleCnt);
+ int countBubbleCnt = cgData.getAllCachesCount();
+ caches = new LeastRecentlyUsedSet<Geocache>(MAX_CACHES + countBubbleCnt);
final MapProvider mapProvider = Settings.getMapProvider();
mapItemFactory = mapProvider.getMapItemFactory();
@@ -469,9 +470,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
prepareFilterBar();
if (!app.isLiveMapHintShown() && !Settings.getHideLiveMapHint()) {
- Intent hintIntent = new Intent(activity, LiveMapInfo.class);
- activity.startActivity(hintIntent);
- app.setLiveMapHintShown();
+ LiveMapInfoDialogBuilder.create(activity).show();
}
}
@@ -494,10 +493,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (!CollectionUtils.isEmpty(dirtyCaches)) {
for (String geocode : dirtyCaches) {
- cgCache cache = app.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
+ Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_WAYPOINTS);
if (cache != null) {
- // remove to update the cache
+ // new collection type needs to remove first
caches.remove(cache);
+ // re-add to update the freshness
caches.add(cache);
}
}
@@ -579,9 +579,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
}
- MenuItem item;
try {
- item = menu.findItem(MENU_TRAIL_MODE); // show trail
+ MenuItem item = menu.findItem(MENU_TRAIL_MODE);
if (Settings.isMapTrail()) {
item.setTitle(res.getString(R.string.map_trail_hide));
} else {
@@ -596,7 +595,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
final Set<String> geocodesInViewport = getGeocodesForCachesInViewport();
- menu.findItem(MENU_STORE_CACHES).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && app.hasUnsavedCaches(new SearchResult(geocodesInViewport)));
+ menu.findItem(MENU_STORE_CACHES).setEnabled(!isLoading() && CollectionUtils.isNotEmpty(geocodesInViewport) && new SearchResult(geocodesInViewport).hasUnsavedCaches());
item = menu.findItem(MENU_CIRCLE_MODE); // show circles
if (overlayCaches != null && overlayCaches.getCircles()) {
@@ -612,7 +611,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
menu.findItem(SUBMENU_STRATEGY).setEnabled(isLiveEnabled);
} catch (Exception e) {
- Log.e("cgeomap.onPrepareOptionsMenu: " + e);
+ Log.e("cgeomap.onPrepareOptionsMenu", e);
}
return true;
@@ -642,7 +641,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final List<String> geocodes = new ArrayList<String>();
for (final String geocode : geocodesInViewport) {
- if (!app.isOffline(geocode, null)) {
+ if (!cgData.isOffline(geocode, null)) {
geocodes.add(geocode);
}
}
@@ -656,42 +655,18 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
return true;
}
- final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler();
-
- waitDialog = new ProgressDialog(activity);
- waitDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- waitDialog.setCancelable(true);
- waitDialog.setCancelMessage(loadDetailsHandler.cancelMessage());
- waitDialog.setMax(detailTotal);
- waitDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
-
- @Override
- public void onCancel(DialogInterface arg0) {
- try {
- if (loadDetailsThread != null) {
- loadDetailsThread.stopIt();
- }
-
- geoDirUpdate.startDir();
- } catch (Exception e) {
- Log.e("cgeocaches.onPrepareOptionsMenu.onCancel: " + e.toString());
- }
- }
- });
-
- float etaTime = detailTotal * 7.0f / 60.0f;
- int roundedEta = Math.round(etaTime);
- if (etaTime < 0.4) {
- waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm));
- } else {
- waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + roundedEta + " " + res.getQuantityString(R.plurals.caches_eta_mins, roundedEta));
+ if (Settings.getChooseList()) {
+ // let user select list to store cache in
+ new StoredList.UserInterface(activity).promptForListSelection(R.string.list_title,
+ new RunnableWithArgument<Integer>() {
+ @Override
+ public void run(final Integer selectedListId) {
+ storeCaches(geocodes, selectedListId);
+ }
+ }, true, StoredList.TEMPORARY_LIST_ID);
+ } else {
+ storeCaches(geocodes, StoredList.STANDARD_LIST_ID);
}
- waitDialog.show();
-
- detailProgressTime = System.currentTimeMillis();
-
- loadDetailsThread = new LoadDetails(loadDetailsHandler, geocodes);
- loadDetailsThread.start();
}
return true;
case MENU_CIRCLE_MODE:
@@ -752,9 +727,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
currentTheme = currentThemeFile.getName();
}
- int currentItem = 0;
List<String> names = new ArrayList<String>();
names.add(res.getString(R.string.map_theme_builtin));
+ int currentItem = 0;
for (File file : themeFiles) {
if (currentTheme.equalsIgnoreCase(file.getName())) {
currentItem = names.size();
@@ -768,7 +743,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
builder.setTitle(R.string.map_theme_select);
- builder.setSingleChoiceItems(names.toArray(new String[] {}), selectedItem,
+ builder.setSingleChoiceItems(names.toArray(new String[names.size()]), selectedItem,
new DialogInterface.OnClickListener() {
@Override
@@ -792,15 +767,15 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
/**
- * @return a Set of geocodes corresponding to the caches that are shown on screen.
+ * @return a non-null Set of geocodes corresponding to the caches that are shown on screen.
*/
private Set<String> getGeocodesForCachesInViewport() {
final Set<String> geocodes = new HashSet<String>();
- final List<cgCache> cachesProtected = caches.getAsList();
+ final List<Geocache> cachesProtected = caches.getAsList();
final Viewport viewport = mapView.getViewport();
- for (final cgCache cache : cachesProtected) {
+ for (final Geocache cache : cachesProtected) {
if (viewport.contains(cache)) {
geocodes.add(cache.getGeocode());
}
@@ -1053,22 +1028,11 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
// check if map moved or zoomed
//TODO Portree Use Rectangle inside with bigger search window. That will stop reloading on every move
- boolean moved = false;
-
- if (liveChanged) {
- moved = true;
- } else if (isLiveEnabled && !downloaded) {
- moved = true;
- } else if (viewport == null) {
- moved = true;
- } else if (zoomNow != zoom) {
- moved = true;
- } else if (mapMoved(viewport, viewportNow) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) || !viewport.includes(viewportNow))) {
- moved = true;
- }
+ final boolean moved = liveChanged || (isLiveEnabled && !downloaded) || (viewport == null) || zoomNow != zoom ||
+ (mapMoved(viewport, viewportNow) && (cachesCnt <= 0 || CollectionUtils.isEmpty(caches) || !viewport.includes(viewportNow)));
// update title on any change
- if (moved || zoomNow != zoom || !viewportNow.equals(viewport)) {
+ if (moved || !viewportNow.equals(viewport)) {
displayHandler.sendEmptyMessage(UPDATE_TITLE);
}
zoom = zoomNow;
@@ -1088,7 +1052,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
yield();
} catch (Exception e) {
- Log.w("cgeomap.LoadTimer.run: " + e.toString());
+ Log.w("cgeomap.LoadTimer.run", e);
}
}
}
@@ -1120,38 +1084,33 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
SearchResult searchResult;
if (mapMode == MapMode.LIVE) {
- if (isLiveEnabled) {
- searchResult = new SearchResult();
- } else {
- searchResult = new SearchResult(app.getStoredInViewport(viewport, Settings.getCacheType()));
- }
+ searchResult = isLiveEnabled ? new SearchResult() : new SearchResult(cgData.loadStoredInViewport(viewport, Settings.getCacheType()));
} else {
// map started from another activity
- searchResult = new SearchResult(searchIntent);
+ searchResult = searchIntent != null ? new SearchResult(searchIntent) : new SearchResult();
if (geocodeIntent != null) {
searchResult.addGeocode(geocodeIntent);
}
}
// live mode search result
if (isLiveEnabled) {
- SearchResult liveResult = new SearchResult(app.getCachedInViewport(viewport, Settings.getCacheType()));
+ SearchResult liveResult = new SearchResult(cgData.loadCachedInViewport(viewport, Settings.getCacheType()));
searchResult.addGeocodes(liveResult.getGeocodes());
}
downloaded = true;
- Set<cgCache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
- // to update the caches they have to be removed first
- caches.removeAll(cachesFromSearchResult);
+ Set<Geocache> cachesFromSearchResult = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_WAYPOINTS);
+ // update the caches
caches.addAll(cachesFromSearchResult);
if (mapMode == MapMode.LIVE) {
final boolean excludeMine = Settings.isExcludeMyCaches();
final boolean excludeDisabled = Settings.isExcludeDisabledCaches();
- final List<cgCache> tempList = caches.getAsList();
+ final List<Geocache> tempList = caches.getAsList();
- for (cgCache cache : tempList) {
- if ((cache.isFound() && excludeMine) || (cache.isOwn() && excludeMine) || (cache.isDisabled() && excludeDisabled)) {
+ for (Geocache cache : tempList) {
+ if ((cache.isFound() && excludeMine) || (cache.isOwner() && excludeMine) || (cache.isDisabled() && excludeDisabled)) {
caches.remove(cache);
}
}
@@ -1162,13 +1121,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
if (isLiveEnabled || mapMode == MapMode.COORDS) {
//All visible waypoints
CacheType type = Settings.getCacheType();
- Set<cgWaypoint> waypointsInViewport = app.getWaypointsInViewport(viewport, Settings.isExcludeMyCaches(), Settings.isExcludeDisabledCaches(), type);
+ Set<Waypoint> waypointsInViewport = cgData.loadWaypoints(viewport, Settings.isExcludeMyCaches(), Settings.isExcludeDisabledCaches(), type);
waypoints.addAll(waypointsInViewport);
}
else
{
//All waypoints from the viewed caches
- for (cgCache c : caches.getAsList()) {
+ for (Geocache c : caches.getAsList()) {
waypoints.addAll(c.getWaypoints());
}
}
@@ -1229,9 +1188,8 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
} while (count < 2);
if (searchResult != null) {
- Set<cgCache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
- // to update the caches they have to be removed first
- caches.removeAll(result);
+ Set<Geocache> result = searchResult.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB);
+ // update the caches
caches.addAll(result);
lastSearchResult = searchResult;
}
@@ -1266,29 +1224,29 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
// display caches
- final List<cgCache> cachesToDisplay = caches.getAsList();
- final List<cgWaypoint> waypointsToDisplay = new ArrayList<cgWaypoint>(waypoints);
+ final List<Geocache> cachesToDisplay = caches.getAsList();
+ final List<Waypoint> waypointsToDisplay = new ArrayList<Waypoint>(waypoints);
final List<CachesOverlayItemImpl> itemsToDisplay = new ArrayList<CachesOverlayItemImpl>();
if (!cachesToDisplay.isEmpty()) {
// Only show waypoints for single view or setting
// when less than showWaypointsthreshold Caches shown
if (mapMode == MapMode.SINGLE || (cachesCnt < Settings.getWayPointsThreshold())) {
- for (cgWaypoint waypoint : waypointsToDisplay) {
+ for (Waypoint waypoint : waypointsToDisplay) {
if (waypoint == null || waypoint.getCoords() == null) {
continue;
}
- itemsToDisplay.add(getItem(waypoint, null, waypoint));
+ itemsToDisplay.add(getWaypointItem(waypoint));
}
}
- for (cgCache cache : cachesToDisplay) {
+ for (Geocache cache : cachesToDisplay) {
if (cache == null || cache.getCoords() == null) {
continue;
}
- itemsToDisplay.add(getItem(cache, cache, null));
+ itemsToDisplay.add(getCacheItem(cache));
}
overlayCaches.updateItems(itemsToDisplay);
@@ -1322,10 +1280,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
if (coordsIntent != null) {
- final cgWaypoint waypoint = new cgWaypoint("some place", waypointTypeIntent != null ? waypointTypeIntent : WaypointType.WAYPOINT, false);
+ final Waypoint waypoint = new Waypoint("some place", waypointTypeIntent != null ? waypointTypeIntent : WaypointType.WAYPOINT, false);
waypoint.setCoords(coordsIntent);
- final CachesOverlayItemImpl item = getItem(waypoint, null, waypoint);
+ final CachesOverlayItemImpl item = getWaypointItem(waypoint);
overlayCaches.updateItems(item);
displayHandler.sendEmptyMessage(INVALIDATE_MAP);
@@ -1342,7 +1300,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final protected Viewport viewport;
- public DoRunnable(final Viewport viewport) {
+ protected DoRunnable(final Viewport viewport) {
this.viewport = viewport;
}
@@ -1364,6 +1322,51 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
}
/**
+ * store caches, invoked by "store offline" menu item
+ *
+ * @param listId
+ * the list to store the caches in
+ */
+ private void storeCaches(List<String> geocodes, int listId) {
+ final LoadDetailsHandler loadDetailsHandler = new LoadDetailsHandler();
+
+ waitDialog = new ProgressDialog(activity);
+ waitDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ waitDialog.setCancelable(true);
+ waitDialog.setCancelMessage(loadDetailsHandler.cancelMessage());
+ waitDialog.setMax(detailTotal);
+ waitDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+
+ @Override
+ public void onCancel(DialogInterface arg0) {
+ try {
+ if (loadDetailsThread != null) {
+ loadDetailsThread.stopIt();
+ }
+
+ geoDirUpdate.startDir();
+ } catch (Exception e) {
+ Log.e("cgeocaches.onPrepareOptionsMenu.onCancel", e);
+ }
+ }
+ });
+
+ float etaTime = detailTotal * 7.0f / 60.0f;
+ int roundedEta = Math.round(etaTime);
+ if (etaTime < 0.4) {
+ waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm));
+ } else {
+ waitDialog.setMessage(res.getString(R.string.caches_downloading) + " " + roundedEta + " " + res.getQuantityString(R.plurals.caches_eta_mins, roundedEta));
+ }
+ waitDialog.show();
+
+ detailProgressTime = System.currentTimeMillis();
+
+ loadDetailsThread = new LoadDetails(loadDetailsHandler, geocodes, listId);
+ loadDetailsThread.start();
+ }
+
+ /**
* Thread to store the caches in the viewport. Started by Activity.
*/
@@ -1371,11 +1374,13 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
final private CancellableHandler handler;
final private List<String> geocodes;
+ final private int listId;
private long last = 0L;
- public LoadDetails(final CancellableHandler handler, final List<String> geocodes) {
+ public LoadDetails(final CancellableHandler handler, final List<String> geocodes, final int listId) {
this.handler = handler;
this.geocodes = geocodes;
+ this.listId = listId;
}
public void stopIt() {
@@ -1396,7 +1401,7 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
break;
}
- if (!app.isOffline(geocode, null)) {
+ if (!cgData.isOffline(geocode, null)) {
if ((System.currentTimeMillis() - last) < 1500) {
try {
int delay = 1000 + (int) (Math.random() * 1000.0) - (int) (System.currentTimeMillis() - last);
@@ -1416,10 +1421,10 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
break;
}
- cgCache.storeCache(null, geocode, StoredList.STANDARD_LIST_ID, false, handler);
+ Geocache.storeCache(null, geocode, listId, false, handler);
}
} catch (Exception e) {
- Log.e("cgeocaches.LoadDetails.run: " + e.toString());
+ Log.e("cgeocaches.LoadDetails.run", e);
} finally {
// one more cache over
detailProgress++;
@@ -1486,9 +1491,9 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
Viewport viewport = null;
if (geocodeCenter != null) {
- viewport = app.getBounds(geocodeCenter);
+ viewport = cgData.getBounds(geocodeCenter);
} else if (searchCenter != null) {
- viewport = app.getBounds(searchCenter.getGeocodes());
+ viewport = cgData.getBounds(searchCenter.getGeocodes());
}
if (viewport == null) {
@@ -1621,116 +1626,100 @@ public class CGeoMap extends AbstractMap implements OnMapDragListener, ViewFacto
dirtyCaches.add(geocode);
}
- /**
- * Returns a OverlayItem represented by an icon
- *
- * @param coord
- * The coords
- * @param cache
- * Cache
- * @param waypoint
- * Waypoint. Mutally exclusive with cache
- * @return
- */
- private CachesOverlayItemImpl getItem(final IWaypoint coord, final cgCache cache, final cgWaypoint waypoint) {
- if (cache != null) {
- final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(coord, cache.getType());
-
- final int hashcode = new HashCodeBuilder()
- .append(cache.isReliableLatLon())
- .append(cache.getType().id)
- .append(cache.isDisabled() || cache.isArchived())
- .append(cache.isOwn())
- .append(cache.isFound())
- .append(cache.hasUserModifiedCoords())
- .append(cache.getPersonalNote())
- .append(cache.isLogOffline())
- .append(cache.getListId() > 0)
- .toHashCode();
-
- final LayerDrawable ldFromCache = overlaysCache.get(hashcode);
- if (ldFromCache != null) {
- item.setMarker(ldFromCache);
- return item;
- }
-
- // Set initial capacities to the maximum of layers and insets to avoid dynamic reallocation
- final ArrayList<Drawable> layers = new ArrayList<Drawable>(9);
- final ArrayList<int[]> insets = new ArrayList<int[]>(8);
-
- // background: disabled or not
- final Drawable marker = getResources().getDrawable(cache.isDisabled() || cache.isArchived() ? R.drawable.marker_disabled : R.drawable.marker);
- layers.add(marker);
- final int resolution = marker.getIntrinsicWidth() > 40 ? 1 : 0;
- // reliable or not
- if (!cache.isReliableLatLon()) {
- insets.add(INSET_RELIABLE[resolution]);
- layers.add(getResources().getDrawable(R.drawable.marker_notreliable));
- }
- // cache type
- layers.add(getResources().getDrawable(cache.getType().markerId));
- insets.add(INSET_TYPE[resolution]);
- // own
- if (cache.isOwn()) {
- layers.add(getResources().getDrawable(R.drawable.marker_own));
- insets.add(INSET_OWN[resolution]);
- // if not, checked if stored
- } else if (cache.getListId() > 0) {
- layers.add(getResources().getDrawable(R.drawable.marker_stored));
- insets.add(INSET_OWN[resolution]);
- }
- // found
- if (cache.isFound()) {
- layers.add(getResources().getDrawable(R.drawable.marker_found));
- insets.add(INSET_FOUND[resolution]);
- // if not, perhaps logged offline
- } else if (cache.isLogOffline()) {
- layers.add(getResources().getDrawable(R.drawable.marker_found_offline));
- insets.add(INSET_FOUND[resolution]);
- }
- // user modified coords
- if (cache.hasUserModifiedCoords()) {
- layers.add(getResources().getDrawable(R.drawable.marker_usermodifiedcoords));
- insets.add(INSET_USERMODIFIEDCOORDS[resolution]);
- }
- // personal note
- if (cache.getPersonalNote() != null) {
- layers.add(getResources().getDrawable(R.drawable.marker_personalnote));
- insets.add(INSET_PERSONALNOTE[resolution]);
- }
-
- final LayerDrawable ld = new LayerDrawable(layers.toArray(new Drawable[layers.size()]));
-
- int index = 1;
- for (final int[] inset : insets) {
- ld.setLayerInset(index++, inset[0], inset[1], inset[2], inset[3]);
- }
-
- overlaysCache.put(hashcode, ld);
-
- item.setMarker(ld);
+ private CachesOverlayItemImpl getCacheItem(final Geocache cache) {
+ final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(cache, cache.getType());
+
+ final int hashcode = new HashCodeBuilder()
+ .append(cache.isReliableLatLon())
+ .append(cache.getType().id)
+ .append(cache.isDisabled() || cache.isArchived())
+ .append(cache.getCacheRealm().id)
+ .append(cache.isOwner())
+ .append(cache.isFound())
+ .append(cache.hasUserModifiedCoords())
+ .append(cache.getPersonalNote())
+ .append(cache.isLogOffline())
+ .append(cache.getListId() > 0)
+ .toHashCode();
+
+ final LayerDrawable ldFromCache = overlaysCache.get(hashcode);
+ if (ldFromCache != null) {
+ item.setMarker(ldFromCache);
return item;
}
- if (waypoint != null) {
-
- final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(coord, null);
- Drawable[] layers = new Drawable[2];
- layers[0] = getResources().getDrawable(R.drawable.marker);
- layers[1] = getResources().getDrawable(waypoint.getWaypointType().markerId);
+ // Set initial capacities to the maximum of layers and insets to avoid dynamic reallocation
+ final ArrayList<Drawable> layers = new ArrayList<Drawable>(9);
+ final ArrayList<int[]> insets = new ArrayList<int[]>(8);
+
+ // background: disabled or not
+ final Drawable marker = getResources().getDrawable(cache.isDisabled() || cache.isArchived() ? cache.getCacheRealm().markerDisabledId : cache.getCacheRealm().markerId);
+ layers.add(marker);
+ final int resolution = marker.getIntrinsicWidth() > 40 ? 1 : 0;
+ // reliable or not
+ if (!cache.isReliableLatLon()) {
+ insets.add(INSET_RELIABLE[resolution]);
+ layers.add(getResources().getDrawable(R.drawable.marker_notreliable));
+ }
+ // cache type
+ layers.add(getResources().getDrawable(cache.getType().markerId));
+ insets.add(INSET_TYPE[resolution]);
+ // own
+ if (cache.isOwner()) {
+ layers.add(getResources().getDrawable(R.drawable.marker_own));
+ insets.add(INSET_OWN[resolution]);
+ // if not, checked if stored
+ } else if (cache.getListId() > 0) {
+ layers.add(getResources().getDrawable(R.drawable.marker_stored));
+ insets.add(INSET_OWN[resolution]);
+ }
+ // found
+ if (cache.isFound()) {
+ layers.add(getResources().getDrawable(R.drawable.marker_found));
+ insets.add(INSET_FOUND[resolution]);
+ // if not, perhaps logged offline
+ } else if (cache.isLogOffline()) {
+ layers.add(getResources().getDrawable(R.drawable.marker_found_offline));
+ insets.add(INSET_FOUND[resolution]);
+ }
+ // user modified coords
+ if (cache.hasUserModifiedCoords()) {
+ layers.add(getResources().getDrawable(R.drawable.marker_usermodifiedcoords));
+ insets.add(INSET_USERMODIFIEDCOORDS[resolution]);
+ }
+ // personal note
+ if (cache.getPersonalNote() != null) {
+ layers.add(getResources().getDrawable(R.drawable.marker_personalnote));
+ insets.add(INSET_PERSONALNOTE[resolution]);
+ }
+
+ final LayerDrawable ld = new LayerDrawable(layers.toArray(new Drawable[layers.size()]));
+
+ int index = 1;
+ for (final int[] inset : insets) {
+ ld.setLayerInset(index++, inset[0], inset[1], inset[2], inset[3]);
+ }
+
+ overlaysCache.put(hashcode, ld);
+
+ item.setMarker(ld);
+ return item;
+ }
- LayerDrawable ld = new LayerDrawable(layers);
- if (layers[0].getIntrinsicWidth() > 40) {
- ld.setLayerInset(1, 9, 12, 10, 13);
- } else {
- ld.setLayerInset(1, 9, 12, 8, 12);
- }
- item.setMarker(ld);
- return item;
+ private CachesOverlayItemImpl getWaypointItem(final Waypoint waypoint) {
+ final CachesOverlayItemImpl item = mapItemFactory.getCachesOverlayItem(waypoint, null);
+ final Drawable[] layers = new Drawable[] {
+ getResources().getDrawable(R.drawable.marker),
+ getResources().getDrawable(waypoint.getWaypointType().markerId)
+ };
+ final LayerDrawable ld = new LayerDrawable(layers);
+ if (layers[0].getIntrinsicWidth() > 40) {
+ ld.setLayerInset(1, 9, 12, 10, 13);
+ } else {
+ ld.setLayerInset(1, 9, 12, 8, 12);
}
-
- return null;
-
+ item.setMarker(ld);
+ return item;
}
}
diff --git a/main/src/cgeo/geocaching/maps/CachesOverlay.java b/main/src/cgeo/geocaching/maps/CachesOverlay.java
index b656900..9bb4cef 100644
--- a/main/src/cgeo/geocaching/maps/CachesOverlay.java
+++ b/main/src/cgeo/geocaching/maps/CachesOverlay.java
@@ -5,8 +5,8 @@ import cgeo.geocaching.IWaypoint;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
import cgeo.geocaching.WaypointPopup;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.Progress;
import cgeo.geocaching.connector.gc.GCMap;
import cgeo.geocaching.enumerations.CacheType;
@@ -209,10 +209,9 @@ public class CachesOverlay extends AbstractItemizedOverlay {
progress.show(context, context.getResources().getString(R.string.map_live), context.getResources().getString(R.string.cache_dialog_loading_details), true, null);
- CachesOverlayItemImpl item = null;
-
// prevent concurrent changes
getOverlayImpl().lock();
+ CachesOverlayItemImpl item = null;
try {
if (index < items.size()) {
item = items.get(index);
@@ -228,7 +227,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
final IWaypoint coordinate = item.getCoord();
if (StringUtils.isNotBlank(coordinate.getCoordType()) && coordinate.getCoordType().equalsIgnoreCase("cache") && StringUtils.isNotBlank(coordinate.getGeocode())) {
- cgCache cache = cgeoapplication.getInstance().loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
+ Geocache cache = cgData.loadCache(coordinate.getGeocode(), LoadFlags.LOAD_CACHE_OR_DB);
RequestDetailsThread requestDetailsThread = new RequestDetailsThread(cache);
if (!requestDetailsThread.requestRequired()) {
// don't show popup if we have enough details
@@ -238,7 +237,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
return true;
}
- if (coordinate.getCoordType() != null && coordinate.getCoordType().equalsIgnoreCase("waypoint") && coordinate.getId() > 0) {
+ if (coordinate.getCoordType() != null && coordinate.getCoordType().equalsIgnoreCase("waypoint") && coordinate.getId() >= 0) {
CGeoMap.markCacheAsDirty(coordinate.getGeocode());
WaypointPopup.startActivity(context, coordinate.getId(), coordinate.getGeocode());
} else {
@@ -248,7 +247,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
progress.dismiss();
} catch (Exception e) {
- Log.e("cgMapOverlay.onTap: " + e.toString());
+ Log.e("cgMapOverlay.onTap", e);
if (progress != null) {
progress.dismiss();
}
@@ -262,7 +261,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
try {
return items.get(index);
} catch (Exception e) {
- Log.e("cgMapOverlay.createItem: " + e.toString());
+ Log.e("cgMapOverlay.createItem", e);
}
return null;
@@ -273,7 +272,7 @@ public class CachesOverlay extends AbstractItemizedOverlay {
try {
return items.size();
} catch (Exception e) {
- Log.e("cgMapOverlay.size: " + e.toString());
+ Log.e("cgMapOverlay.size", e);
}
return 0;
@@ -281,9 +280,9 @@ public class CachesOverlay extends AbstractItemizedOverlay {
private class RequestDetailsThread extends Thread {
- private final cgCache cache;
+ private final Geocache cache;
- public RequestDetailsThread(cgCache cache) {
+ public RequestDetailsThread(Geocache cache) {
this.cache = cache;
}
diff --git a/main/src/cgeo/geocaching/maps/MapProviderFactory.java b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
index cb1f87f..483189f 100644
--- a/main/src/cgeo/geocaching/maps/MapProviderFactory.java
+++ b/main/src/cgeo/geocaching/maps/MapProviderFactory.java
@@ -23,7 +23,7 @@ public class MapProviderFactory {
MapsforgeMapProvider.getInstance();
}
- private static boolean isGoogleMapsInstalled() {
+ public static boolean isGoogleMapsInstalled() {
boolean googleMaps = true;
try {
Class.forName("com.google.android.maps.MapActivity");
diff --git a/main/src/cgeo/geocaching/maps/PositionOverlay.java b/main/src/cgeo/geocaching/maps/PositionOverlay.java
index 1aa2d3b..fec67ef 100644
--- a/main/src/cgeo/geocaching/maps/PositionOverlay.java
+++ b/main/src/cgeo/geocaching/maps/PositionOverlay.java
@@ -158,7 +158,6 @@ public class PositionOverlay implements GeneralOverlay {
if (Settings.isMapTrail()) {
int size = history.size();
if (size > 1) {
- int alpha;
int alphaCnt = size - 201;
if (alphaCnt < 1) {
alphaCnt = 1;
@@ -172,6 +171,7 @@ public class PositionOverlay implements GeneralOverlay {
projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(prev)), historyPointP);
projection.toPixels(mapItemFactory.getGeoPointBase(new Geopoint(now)), historyPointN);
+ int alpha;
if ((alphaCnt - cnt) > 0) {
alpha = 255 / (alphaCnt - cnt);
}
@@ -211,11 +211,8 @@ public class PositionOverlay implements GeneralOverlay {
heightArrowHalf = arrow.getHeight() / 2;
}
- int marginLeft;
- int marginTop;
-
- marginLeft = center.x - widthArrowHalf;
- marginTop = center.y - heightArrowHalf;
+ int marginLeft = center.x - widthArrowHalf;
+ int marginTop = center.y - heightArrowHalf;
Matrix matrix = new Matrix();
matrix.setRotate(heading, widthArrowHalf, heightArrowHalf);
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
index 0377fe9..5649d19 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapActivity.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps.google;
+import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.maps.interfaces.MapActivityImpl;
@@ -12,7 +13,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-public class GoogleMapActivity extends MapActivity implements MapActivityImpl {
+public class GoogleMapActivity extends MapActivity implements MapActivityImpl, FilteredActivity {
private AbstractMap mapBase;
@@ -127,4 +128,8 @@ public class GoogleMapActivity extends MapActivity implements MapActivityImpl {
mapBase.goManual(view);
}
+ @Override
+ public void showFilterMenu(View view) {
+ // do nothing, the filter bar only shows the global filter
+ }
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
index 6973338..1fa38ad 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapProvider.java
@@ -16,7 +16,6 @@ public final class GoogleMapProvider extends AbstractMapProvider {
public static final String GOOGLE_MAP_ID = "GOOGLE_MAP";
public static final String GOOGLE_SATELLITE_ID = "GOOGLE_SATELLITE";
- private static GoogleMapProvider instance;
private final MapItemFactory mapItemFactory;
@@ -29,15 +28,16 @@ public final class GoogleMapProvider extends AbstractMapProvider {
mapItemFactory = new GoogleMapItemFactory();
}
+ private static class Holder {
+ private static final GoogleMapProvider INSTANCE = new GoogleMapProvider();
+ }
+
public static GoogleMapProvider getInstance() {
- if (instance == null) {
- instance = new GoogleMapProvider();
- }
- return instance;
+ return Holder.INSTANCE;
}
public static boolean isSatelliteSource(final MapSource mapSource) {
- return mapSource != null && mapSource instanceof GoogleSatelliteSource;
+ return mapSource instanceof GoogleSatelliteSource;
}
@Override
@@ -67,7 +67,7 @@ public final class GoogleMapProvider extends AbstractMapProvider {
private static abstract class AbstractGoogleMapSource extends AbstractMapSource {
- public AbstractGoogleMapSource(final String id, final MapProvider mapProvider, final String name) {
+ protected AbstractGoogleMapSource(final String id, final MapProvider mapProvider, final String name) {
super(id, mapProvider, name);
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
index 9c134a4..154c3f3 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleMapView.java
@@ -61,7 +61,7 @@ public class GoogleMapView extends MapView implements MapViewImpl {
super.draw(canvas);
} catch (Exception e) {
- Log.e("GoogleMapView.draw: " + e.toString());
+ Log.e("GoogleMapView.draw", e);
}
}
@@ -75,7 +75,7 @@ public class GoogleMapView extends MapView implements MapViewImpl {
super.displayZoomControls(takeFocus);
} catch (Exception e) {
- Log.e("GoogleMapView.displayZoomControls: " + e.toString());
+ Log.e("GoogleMapView.displayZoomControls", e);
}
}
diff --git a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
index d86eafe..773f9ff 100644
--- a/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
+++ b/main/src/cgeo/geocaching/maps/google/GoogleOverlay.java
@@ -27,6 +27,9 @@ public class GoogleOverlay extends Overlay implements OverlayImpl {
break;
case ScaleOverlay:
overlayBase = new ScaleOverlay(activityIn, this);
+ break;
+ default:
+ throw new IllegalArgumentException();
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
index 6cb2539..f850402 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapActivity.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps.mapsforge;
+import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.maps.interfaces.MapActivityImpl;
@@ -12,7 +13,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl {
+public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl, FilteredActivity {
private AbstractMap mapBase;
@@ -121,4 +122,9 @@ public class MapsforgeMapActivity extends MapActivity implements MapActivityImpl
public void goManual(View view) {
mapBase.goManual(view);
}
+
+ @Override
+ public void showFilterMenu(View view) {
+ // do nothing, the filter bar only shows the global filter
+ }
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java
index ad64807..dc0dbf8 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapProvider.java
@@ -31,7 +31,6 @@ public final class MapsforgeMapProvider extends AbstractMapProvider {
public static final String MAPSFORGE_MAPNIK_ID = "MAPSFORGE_MAPNIK";
private boolean oldMap = false;
private MapItemFactory mapItemFactory = new MapsforgeMapItemFactory();
- private static MapsforgeMapProvider instance;
private MapsforgeMapProvider() {
final Resources resources = cgeoapplication.getInstance().getResources();
@@ -42,11 +41,12 @@ public final class MapsforgeMapProvider extends AbstractMapProvider {
updateOfflineMaps();
}
+ private static final class Holder {
+ private static final MapsforgeMapProvider INSTANCE = new MapsforgeMapProvider();
+ }
+
public static MapsforgeMapProvider getInstance() {
- if (instance == null) {
- instance = new MapsforgeMapProvider();
- }
- return instance;
+ return Holder.INSTANCE;
}
public static List<String> getOfflineMaps() {
@@ -65,6 +65,7 @@ public final class MapsforgeMapProvider extends AbstractMapProvider {
}
}
}
+ Collections.sort(mapFileList, String.CASE_INSENSITIVE_ORDER);
return mapFileList;
} catch (Exception e) {
Log.e("Settings.getOfflineMaps: " + e);
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
index 1e4a756..083e5bb 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeMapView.java
@@ -59,7 +59,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
super.draw(canvas);
} catch (Exception e) {
- Log.e("MapsforgeMapView.draw: " + e.toString());
+ Log.e("MapsforgeMapView.draw", e);
}
}
@@ -264,7 +264,7 @@ public class MapsforgeMapView extends MapView implements MapViewImpl {
}
} catch (Exception e) {
- Log.e("MapsforgeMapView.repaintRequired: " + e.toString());
+ Log.e("MapsforgeMapView.repaintRequired", e);
}
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
index b6e31a2..dd7fb75 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/MapsforgeOverlay.java
@@ -29,6 +29,9 @@ public class MapsforgeOverlay extends Overlay implements OverlayImpl {
break;
case ScaleOverlay:
overlayBase = new ScaleOverlay(activityIn, this);
+ break;
+ default:
+ throw new IllegalArgumentException();
}
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
index d45db9a..ed8a7bc 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapActivity024.java
@@ -1,5 +1,6 @@
package cgeo.geocaching.maps.mapsforge.v024;
+import cgeo.geocaching.activity.FilteredActivity;
import cgeo.geocaching.maps.AbstractMap;
import cgeo.geocaching.maps.CGeoMap;
import cgeo.geocaching.maps.interfaces.MapActivityImpl;
@@ -12,7 +13,7 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-public class MapsforgeMapActivity024 extends MapActivity implements MapActivityImpl {
+public class MapsforgeMapActivity024 extends MapActivity implements MapActivityImpl, FilteredActivity {
private AbstractMap mapBase;
@@ -121,4 +122,9 @@ public class MapsforgeMapActivity024 extends MapActivity implements MapActivityI
public void goManual(View view) {
mapBase.goManual(view);
}
+
+ @Override
+ public void showFilterMenu(View view) {
+ // do nothing, the filter bar only shows the global filter
+ }
}
diff --git a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
index d177a47..85d61fe 100644
--- a/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
+++ b/main/src/cgeo/geocaching/maps/mapsforge/v024/MapsforgeMapView024.java
@@ -53,7 +53,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
super.draw(canvas);
} catch (Exception e) {
- Log.e("MapsforgeMapView.draw: " + e.toString());
+ Log.e("MapsforgeMapView.draw", e);
}
}
@@ -208,7 +208,7 @@ public class MapsforgeMapView024 extends MapView implements MapViewImpl {
}
} catch (Exception e) {
- Log.e("MapsforgeMapView.repaintRequired: " + e.toString());
+ Log.e("MapsforgeMapView.repaintRequired", e);
}
}
}
diff --git a/main/src/cgeo/geocaching/network/HtmlImage.java b/main/src/cgeo/geocaching/network/HtmlImage.java
index d47afb9..a409750 100644
--- a/main/src/cgeo/geocaching/network/HtmlImage.java
+++ b/main/src/cgeo/geocaching/network/HtmlImage.java
@@ -3,6 +3,7 @@ package cgeo.geocaching.network;
import cgeo.geocaching.R;
import cgeo.geocaching.StoredList;
import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.compatibility.Compatibility;
import cgeo.geocaching.connector.ConnectorFactory;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.utils.ImageHelper;
@@ -12,15 +13,13 @@ import ch.boye.httpclientandroidlib.HttpResponse;
import org.apache.commons.lang3.StringUtils;
-import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.text.Html;
-import android.view.Display;
-import android.view.WindowManager;
import java.io.File;
import java.io.FileInputStream;
@@ -42,7 +41,8 @@ public class HtmlImage implements Html.ImageGetter {
"besucherzaehler-homepage.de",
"hitwebcounter.com",
"kostenloser-counter.eu",
- "trendcounter.com"
+ "trendcounter.com",
+ "hit-counter-download.com"
};
final private String geocode;
@@ -66,9 +66,9 @@ public class HtmlImage implements Html.ImageGetter {
bfOptions = new BitmapFactory.Options();
bfOptions.inTempStorage = new byte[16 * 1024];
- final Display display = ((WindowManager) cgeoapplication.getInstance().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- this.maxWidth = display.getWidth() - 25;
- this.maxHeight = display.getHeight() - 25;
+ Point displaySize = Compatibility.getDisplaySize();
+ this.maxWidth = displaySize.x - 25;
+ this.maxHeight = displaySize.y - 25;
this.resources = cgeoapplication.getInstance().getResources();
}
@@ -161,7 +161,7 @@ public class HtmlImage implements Html.ImageGetter {
final File fileSec = LocalStorage.getStorageSecFile(pseudoGeocode, url, true);
return loadCachedImage(fileSec, forceKeep);
} catch (Exception e) {
- Log.w("HtmlImage.getDrawable (reading cache): " + e.toString());
+ Log.w("HtmlImage.getDrawable (reading cache)", e);
}
return null;
}
diff --git a/main/src/cgeo/geocaching/network/Network.java b/main/src/cgeo/geocaching/network/Network.java
index 0bd845f..5c4148f 100644
--- a/main/src/cgeo/geocaching/network/Network.java
+++ b/main/src/cgeo/geocaching/network/Network.java
@@ -22,6 +22,7 @@ import ch.boye.httpclientandroidlib.client.methods.HttpGet;
import ch.boye.httpclientandroidlib.client.methods.HttpPost;
import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
import ch.boye.httpclientandroidlib.client.params.ClientPNames;
+import ch.boye.httpclientandroidlib.entity.StringEntity;
import ch.boye.httpclientandroidlib.entity.mime.MultipartEntity;
import ch.boye.httpclientandroidlib.entity.mime.content.FileBody;
import ch.boye.httpclientandroidlib.entity.mime.content.StringBody;
@@ -34,6 +35,7 @@ import ch.boye.httpclientandroidlib.params.HttpParams;
import ch.boye.httpclientandroidlib.protocol.HttpContext;
import ch.boye.httpclientandroidlib.util.EntityUtils;
+import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
@@ -43,11 +45,13 @@ import android.net.Uri;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
import java.net.URLEncoder;
public abstract class Network {
private static final int NB_DOWNLOAD_RETRIES = 4;
+
/** User agent id */
private final static String PC_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1";
/** Native user agent, taken from a Android 2.2 Nexus **/
@@ -58,7 +62,7 @@ public abstract class Network {
private final static HttpParams clientParams = new BasicHttpParams();
static {
- Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, "UTF-8");
+ Network.clientParams.setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, CharEncoding.UTF_8);
Network.clientParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);
Network.clientParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, 30000);
Network.clientParams.setParameter(ClientPNames.HANDLE_REDIRECTS, true);
@@ -115,7 +119,6 @@ public abstract class Network {
if (contentEncoding != null) {
for (final HeaderElement codec : contentEncoding.getElements()) {
if (codec.getName().equalsIgnoreCase("gzip")) {
- Log.d("Decompressing response");
response.setEntity(new GzipDecompressingEntity(response.getEntity()));
return;
}
@@ -153,6 +156,27 @@ public abstract class Network {
}
/**
+ * POST HTTP request with Json POST DATA
+ *
+ * @param uri the URI to request
+ * @param json the json object to add to the POST request
+ * @return the HTTP response, or null in case of an encoding error params
+ */
+ public static HttpResponse postJsonRequest(final String uri, final JSONObject json) {
+ HttpPost request = new HttpPost(uri);
+ request.addHeader("Content-Type", "application/json; charset=utf-8");
+ if (json != null) {
+ try {
+ request.setEntity(new StringEntity(json.toString()));
+ } catch (UnsupportedEncodingException e) {
+ Log.e("postJsonRequest:JSON Entity: UnsupportedEncodingException");
+ return null;
+ }
+ }
+ return doRepeatedRequests(request);
+ }
+
+ /**
* Multipart POST HTTP request
*
* @param uri the URI to request
@@ -206,7 +230,7 @@ public abstract class Network {
request = new HttpPost(uri);
if (params != null) {
try {
- ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
+ ((HttpPost) request).setEntity(new UrlEncodedFormEntity(params, CharEncoding.UTF_8));
} catch (final UnsupportedEncodingException e) {
Log.e("request", e);
return null;
@@ -235,11 +259,8 @@ public abstract class Network {
"X-Requested-With", "XMLHttpRequest")) {
request.setHeader(header.getName(), header.getValue());
}
- if (Settings.getUseNativeUa()) {
- request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.NATIVE_USER_AGENT);
- } else {
- request.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Network.PC_USER_AGENT);
- }
+ request.getParams().setParameter(CoreProtocolPNames.USER_AGENT,
+ Settings.getUseNativeUa() ? Network.NATIVE_USER_AGENT : Network.PC_USER_AGENT);
}
/**
@@ -362,15 +383,21 @@ public abstract class Network {
return response != null && response.getStatusLine().getStatusCode() == 200;
}
+ /**
+ * Get the result of a GET HTTP request returning a JSON body.
+ *
+ * @param uri the base URI of the GET HTTP request
+ * @param params the query parameters, or <code>null</code> if there are none
+ * @return a JSON object if the request was successful and the body could be decoded, <code>null</code> otherwise
+ */
public static JSONObject requestJSON(final String uri, final Parameters params) {
final HttpResponse response = request("GET", uri, params, new Parameters("Accept", "application/json, text/javascript, */*; q=0.01"), null);
- if (isSuccess(response)) {
+ final String responseData = Network.getResponseData(response, false);
+ if (responseData != null) {
try {
- return new JSONObject(Network.getResponseData(response));
+ return new JSONObject(responseData);
} catch (final JSONException e) {
- Log.e("Network.requestJSON", e);
- } catch (final NullPointerException e) {
- Log.e("Network.requestJSON", e);
+ Log.w("Network.requestJSON", e);
}
}
@@ -379,7 +406,7 @@ public abstract class Network {
private static String getResponseDataNoError(final HttpResponse response, boolean replaceWhitespace) {
try {
- String data = EntityUtils.toString(response.getEntity(), "UTF-8");
+ String data = EntityUtils.toString(response.getEntity(), CharEncoding.UTF_8);
return replaceWhitespace ? BaseUtils.replaceWhitespace(data) : data;
} catch (Exception e) {
Log.e("getResponseData", e);
@@ -387,10 +414,26 @@ public abstract class Network {
}
}
+ /**
+ * Get the body of a HTTP response.
+ *
+ * {@link BaseUtils#replaceWhitespace(String)} will be called on the result
+ *
+ * @param response a HTTP response, which can be null
+ * @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise
+ */
public static String getResponseData(final HttpResponse response) {
return Network.getResponseData(response, true);
}
+ /**
+ * Get the body of a HTTP response.
+ *
+ * @param response a HTTP response, which can be null
+ * @param replaceWhitespace <code>true</code> if {@link BaseUtils#replaceWhitespace(String)}
+ * should be called on the body
+ * @return the body if the response comes from a successful HTTP request, <code>null</code> otherwise
+ */
public static String getResponseData(final HttpResponse response, boolean replaceWhitespace) {
if (!isSuccess(response)) {
return null;
@@ -399,7 +442,25 @@ public abstract class Network {
}
public static String rfc3986URLEncode(String text) {
- return StringUtils.replace(URLEncoder.encode(text).replace("+", "%20"), "%7E", "~");
+ return StringUtils.replace(Network.encode(text).replace("+", "%20"), "%7E", "~");
+ }
+
+ public static String decode(final String text) {
+ try {
+ return URLDecoder.decode(text, CharEncoding.UTF_8);
+ } catch (UnsupportedEncodingException e) {
+ Log.e("Network.decode", e);
+ }
+ return null;
+ }
+
+ public static String encode(final String text) {
+ try {
+ return URLEncoder.encode(text, CharEncoding.UTF_8);
+ } catch (UnsupportedEncodingException e) {
+ Log.e("Network.encode", e);
+ }
+ return null;
}
}
diff --git a/main/src/cgeo/geocaching/network/Parameters.java b/main/src/cgeo/geocaching/network/Parameters.java
index 081a926..74f5531 100644
--- a/main/src/cgeo/geocaching/network/Parameters.java
+++ b/main/src/cgeo/geocaching/network/Parameters.java
@@ -4,6 +4,8 @@ import ch.boye.httpclientandroidlib.NameValuePair;
import ch.boye.httpclientandroidlib.client.utils.URLEncodedUtils;
import ch.boye.httpclientandroidlib.message.BasicNameValuePair;
+import org.apache.commons.lang3.CharEncoding;
+
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Collections;
@@ -24,7 +26,6 @@ public class Parameters extends ArrayList<NameValuePair> {
* if the number of key/values is unbalanced
*/
public Parameters(final String... keyValues) {
- super();
put(keyValues);
}
@@ -66,7 +67,7 @@ public class Parameters extends ArrayList<NameValuePair> {
@Override
public String toString() {
- return URLEncodedUtils.format(this, "UTF-8");
+ return URLEncodedUtils.format(this, CharEncoding.UTF_8);
}
/**
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
index 8c3b9dc..1953e1d 100644
--- a/main/src/cgeo/geocaching/network/StatusUpdater.java
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -31,7 +31,7 @@ public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implement
private void requestUpdate() {
final JSONObject response =
Network.requestJSON("http://status.cgeo.org/api/status.json",
- new Parameters("version_code", "" + Version.getVersionCode(cgeoapplication.getInstance()),
+ new Parameters("version_code", String.valueOf(Version.getVersionCode(cgeoapplication.getInstance())),
"version_name", Version.getVersionName(cgeoapplication.getInstance()),
"locale", Locale.getDefault().toString()));
if (response != null) {
diff --git a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
index 2015375..2dee713 100644
--- a/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
+++ b/main/src/cgeo/geocaching/sorting/AbstractCacheComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.utils.Log;
@@ -11,7 +11,7 @@ import cgeo.geocaching.utils.Log;
public abstract class AbstractCacheComparator implements CacheComparator {
@Override
- public final int compare(final cgCache cache1, final cgCache cache2) {
+ public final int compare(final Geocache cache1, final Geocache cache2) {
try {
// first check that we have all necessary data for the comparison
if (!canCompare(cache1, cache2)) {
@@ -19,7 +19,7 @@ public abstract class AbstractCacheComparator implements CacheComparator {
}
return compareCaches(cache1, cache2);
} catch (Exception e) {
- Log.e("AbstractCacheComparator.compare: " + e.toString());
+ Log.e("AbstractCacheComparator.compare", e);
}
return 0;
}
@@ -31,7 +31,7 @@ public abstract class AbstractCacheComparator implements CacheComparator {
* @param cache2
* @return
*/
- protected abstract boolean canCompare(final cgCache cache1, final cgCache cache2);
+ protected abstract boolean canCompare(final Geocache cache1, final Geocache cache2);
/**
* Compares two caches. Logging and exception handling is implemented outside this method already.
@@ -44,5 +44,5 @@ public abstract class AbstractCacheComparator implements CacheComparator {
* @return an integer < 0 if cache1 is less than cache2, 0 if they are equal, and > 0 if cache1 is greater than
* cache2.
*/
- protected abstract int compareCaches(final cgCache cache1, final cgCache cache2);
+ protected abstract int compareCaches(final Geocache cache1, final Geocache cache2);
}
diff --git a/main/src/cgeo/geocaching/sorting/CacheComparator.java b/main/src/cgeo/geocaching/sorting/CacheComparator.java
index c9b5150..7932729 100644
--- a/main/src/cgeo/geocaching/sorting/CacheComparator.java
+++ b/main/src/cgeo/geocaching/sorting/CacheComparator.java
@@ -2,8 +2,8 @@ package cgeo.geocaching.sorting;
import java.util.Comparator;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
-public interface CacheComparator extends Comparator<cgCache> {
+public interface CacheComparator extends Comparator<Geocache> {
}
diff --git a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
index bc63ef6..4d1a994 100644
--- a/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
+++ b/main/src/cgeo/geocaching/sorting/ComparatorUserInterface.java
@@ -43,7 +43,7 @@ public class ComparatorUserInterface {
register(R.string.caches_sort_date_hidden, DateComparator.class);
register(R.string.caches_sort_difficulty, DifficultyComparator.class);
register(R.string.caches_sort_finds, FindsComparator.class);
- register(R.string.caches_sort_gccode, GeocodeComparator.class);
+ register(R.string.caches_sort_geocode, GeocodeComparator.class);
register(R.string.caches_sort_inventory, InventoryComparator.class);
register(R.string.caches_sort_name, NameComparator.class);
register(R.string.caches_sort_favorites, PopularityComparator.class);
diff --git a/main/src/cgeo/geocaching/sorting/DateComparator.java b/main/src/cgeo/geocaching/sorting/DateComparator.java
index 3136d47..3464103 100644
--- a/main/src/cgeo/geocaching/sorting/DateComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DateComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.cgeoapplication;
import java.util.ArrayList;
@@ -12,19 +12,19 @@ import java.util.Date;
public class DateComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(cgCache cache1, cgCache cache2) {
+ protected int compareCaches(Geocache cache1, Geocache cache2) {
final Date date1 = cache1.getHiddenDate();
final Date date2 = cache2.getHiddenDate();
if (date1 != null && date2 != null) {
final int dateDifference = date1.compareTo(date2);
// for equal dates, sort by distance
if (dateDifference == 0) {
- final ArrayList<cgCache> list = new ArrayList<cgCache>();
+ final ArrayList<Geocache> list = new ArrayList<Geocache>();
list.add(cache1);
list.add(cache2);
final DistanceComparator distanceComparator = new DistanceComparator(cgeoapplication.getInstance().currentGeo().getCoords(), list);
diff --git a/main/src/cgeo/geocaching/sorting/DifficultyComparator.java b/main/src/cgeo/geocaching/sorting/DifficultyComparator.java
index 123bab9..73d12fa 100644
--- a/main/src/cgeo/geocaching/sorting/DifficultyComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DifficultyComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by difficulty
@@ -9,12 +9,12 @@ import cgeo.geocaching.cgCache;
public class DifficultyComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return cache1.getDifficulty() != 0.0 && cache2.getDifficulty() != 0.0;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return Float.compare(cache1.getDifficulty(), cache2.getDifficulty());
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/sorting/DistanceComparator.java b/main/src/cgeo/geocaching/sorting/DistanceComparator.java
index d601433..7b0afbb 100644
--- a/main/src/cgeo/geocaching/sorting/DistanceComparator.java
+++ b/main/src/cgeo/geocaching/sorting/DistanceComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.geopoint.Geopoint;
import java.util.List;
@@ -11,9 +11,23 @@ import java.util.List;
*/
public class DistanceComparator extends AbstractCacheComparator {
- public DistanceComparator(final Geopoint coords, List<cgCache> list) {
- // calculate all distances to avoid duplicate calculations during sorting
- for (cgCache cache : list) {
+ final private Geopoint coords;
+ final private List<Geocache> list;
+ private boolean cachedDistances;
+
+ public DistanceComparator(final Geopoint coords, List<Geocache> list) {
+ this.coords = coords;
+ this.list = list;
+ }
+
+ /**
+ * calculate all distances only once to avoid costly re-calculation of the same distance during sorting
+ */
+ private void calculateAllDistances() {
+ if (cachedDistances) {
+ return;
+ }
+ for (Geocache cache : list) {
if (cache.getCoords() != null) {
cache.setDistance(coords.distanceTo(cache.getCoords()));
}
@@ -21,15 +35,17 @@ public class DistanceComparator extends AbstractCacheComparator {
cache.setDistance(null);
}
}
+ cachedDistances = true;
}
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
+ calculateAllDistances();
if (cache1.getCoords() == null && cache2.getCoords() == null) {
return 0;
}
diff --git a/main/src/cgeo/geocaching/sorting/FindsComparator.java b/main/src/cgeo/geocaching/sorting/FindsComparator.java
index 6407b11..ba929b8 100644
--- a/main/src/cgeo/geocaching/sorting/FindsComparator.java
+++ b/main/src/cgeo/geocaching/sorting/FindsComparator.java
@@ -1,28 +1,26 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.enumerations.LogType;
public class FindsComparator extends AbstractCacheComparator {
- private final cgeoapplication app = cgeoapplication.getInstance();
-
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return cache1.getLogCounts() != null && cache2.getLogCounts() != null;
}
@Override
- protected int compareCaches(cgCache cache1, cgCache cache2) {
+ protected int compareCaches(Geocache cache1, Geocache cache2) {
int finds1 = getFindsCount(cache1);
int finds2 = getFindsCount(cache2);
return finds2 - finds1;
}
- private int getFindsCount(cgCache cache) {
+ private static int getFindsCount(Geocache cache) {
if (cache.getLogCounts().isEmpty()) {
- cache.setLogCounts(app.loadLogCounts(cache.getGeocode()));
+ cache.setLogCounts(cgData.loadLogCounts(cache.getGeocode()));
}
Integer logged = cache.getLogCounts().get(LogType.FOUND_IT);
if (logged != null) {
diff --git a/main/src/cgeo/geocaching/sorting/GeocodeComparator.java b/main/src/cgeo/geocaching/sorting/GeocodeComparator.java
index fb93c0e..412649a 100644
--- a/main/src/cgeo/geocaching/sorting/GeocodeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/GeocodeComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import org.apache.commons.lang3.StringUtils;
@@ -11,13 +11,13 @@ import org.apache.commons.lang3.StringUtils;
public class GeocodeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return StringUtils.isNotBlank(cache1.getGeocode())
&& StringUtils.isNotBlank(cache2.getGeocode());
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
final int lengthDiff = cache1.getGeocode().length() - cache2.getGeocode().length();
return lengthDiff != 0 ? lengthDiff : cache1.getGeocode().compareToIgnoreCase(cache2.getGeocode());
}
diff --git a/main/src/cgeo/geocaching/sorting/InventoryComparator.java b/main/src/cgeo/geocaching/sorting/InventoryComparator.java
index fb1360e..73ea2c5 100644
--- a/main/src/cgeo/geocaching/sorting/InventoryComparator.java
+++ b/main/src/cgeo/geocaching/sorting/InventoryComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by number of items in inventory
@@ -8,12 +8,12 @@ import cgeo.geocaching.cgCache;
public class InventoryComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
+ protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return cache2.getInventoryItems() - cache1.getInventoryItems();
}
}
diff --git a/main/src/cgeo/geocaching/sorting/InverseComparator.java b/main/src/cgeo/geocaching/sorting/InverseComparator.java
new file mode 100644
index 0000000..1dc76e2
--- /dev/null
+++ b/main/src/cgeo/geocaching/sorting/InverseComparator.java
@@ -0,0 +1,22 @@
+package cgeo.geocaching.sorting;
+
+import cgeo.geocaching.Geocache;
+
+/**
+ * comparator which inverses the sort order of the given other comparator
+ *
+ */
+public class InverseComparator implements CacheComparator {
+
+ private final CacheComparator originalComparator;
+
+ public InverseComparator(CacheComparator comparator) {
+ this.originalComparator = comparator;
+ }
+
+ @Override
+ public int compare(Geocache lhs, Geocache rhs) {
+ return originalComparator.compare(rhs, lhs);
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/sorting/NameComparator.java b/main/src/cgeo/geocaching/sorting/NameComparator.java
index c32bc48..b432ad0 100644
--- a/main/src/cgeo/geocaching/sorting/NameComparator.java
+++ b/main/src/cgeo/geocaching/sorting/NameComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
import org.apache.commons.lang3.StringUtils;
@@ -11,12 +11,12 @@ import org.apache.commons.lang3.StringUtils;
public class NameComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return StringUtils.isNotBlank(cache1.getName()) && StringUtils.isNotBlank(cache2.getName());
}
@Override
- protected int compareCaches(cgCache cache1, cgCache cache2) {
+ protected int compareCaches(Geocache cache1, Geocache cache2) {
return cache1.getNameForSorting().compareToIgnoreCase(cache2.getNameForSorting());
}
}
diff --git a/main/src/cgeo/geocaching/sorting/PopularityComparator.java b/main/src/cgeo/geocaching/sorting/PopularityComparator.java
index 62ad9a9..e256654 100644
--- a/main/src/cgeo/geocaching/sorting/PopularityComparator.java
+++ b/main/src/cgeo/geocaching/sorting/PopularityComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by popularity (favorite count)
@@ -9,12 +9,12 @@ import cgeo.geocaching.cgCache;
public class PopularityComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
+ protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return cache2.getFavoritePoints() - cache1.getFavoritePoints();
}
}
diff --git a/main/src/cgeo/geocaching/sorting/RatingComparator.java b/main/src/cgeo/geocaching/sorting/RatingComparator.java
index be071c5..72cf6c8 100644
--- a/main/src/cgeo/geocaching/sorting/RatingComparator.java
+++ b/main/src/cgeo/geocaching/sorting/RatingComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by gcvote.com rating
@@ -9,12 +9,12 @@ import cgeo.geocaching.cgCache;
public class RatingComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
+ protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
final float rating1 = cache1.getRating();
final float rating2 = cache2.getRating();
// Voting can be disabled for caches, then assume an average rating instead
diff --git a/main/src/cgeo/geocaching/sorting/SizeComparator.java b/main/src/cgeo/geocaching/sorting/SizeComparator.java
index f946522..d128822 100644
--- a/main/src/cgeo/geocaching/sorting/SizeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/SizeComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by size
@@ -9,12 +9,12 @@ import cgeo.geocaching.cgCache;
public class SizeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return cache1.getSize() != null && cache2.getSize() != null;
}
@Override
- protected int compareCaches(cgCache cache1, cgCache cache2) {
+ protected int compareCaches(Geocache cache1, Geocache cache2) {
return cache2.getSize().comparable - cache1.getSize().comparable;
}
} \ No newline at end of file
diff --git a/main/src/cgeo/geocaching/sorting/StateComparator.java b/main/src/cgeo/geocaching/sorting/StateComparator.java
index bda514f..b99c3c0 100644
--- a/main/src/cgeo/geocaching/sorting/StateComparator.java
+++ b/main/src/cgeo/geocaching/sorting/StateComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sort caches by state (normal, disabled, archived)
@@ -9,16 +9,16 @@ import cgeo.geocaching.cgCache;
public class StateComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
+ protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return getState(cache1) - getState(cache2);
}
- private static int getState(final cgCache cache) {
+ private static int getState(final Geocache cache) {
if (cache.isDisabled()) {
return 1;
}
diff --git a/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java b/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java
index 32bef32..78ba742 100644
--- a/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java
+++ b/main/src/cgeo/geocaching/sorting/StorageTimeComparator.java
@@ -1,16 +1,16 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
public class StorageTimeComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(cgCache cache1, cgCache cache2) {
+ protected int compareCaches(Geocache cache1, Geocache cache2) {
if (cache1.getUpdated() < cache2.getUpdated()) {
return -1;
}
diff --git a/main/src/cgeo/geocaching/sorting/TerrainComparator.java b/main/src/cgeo/geocaching/sorting/TerrainComparator.java
index 9058a3c..be1e9bb 100644
--- a/main/src/cgeo/geocaching/sorting/TerrainComparator.java
+++ b/main/src/cgeo/geocaching/sorting/TerrainComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by terrain rating
@@ -9,12 +9,12 @@ import cgeo.geocaching.cgCache;
public class TerrainComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
+ protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
return cache1.getTerrain() != 0.0 && cache2.getTerrain() != 0.0;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return Float.compare(cache1.getTerrain(), cache2.getTerrain());
}
}
diff --git a/main/src/cgeo/geocaching/sorting/VisitComparator.java b/main/src/cgeo/geocaching/sorting/VisitComparator.java
index 46d8c58..27d3170 100644
--- a/main/src/cgeo/geocaching/sorting/VisitComparator.java
+++ b/main/src/cgeo/geocaching/sorting/VisitComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by last visited date
@@ -9,12 +9,12 @@ import cgeo.geocaching.cgCache;
public class VisitComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(final cgCache cache1, final cgCache cache2) {
+ protected boolean canCompare(final Geocache cache1, final Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(final cgCache cache1, final cgCache cache2) {
+ protected int compareCaches(final Geocache cache1, final Geocache cache2) {
return Long.valueOf(cache2.getVisitedDate()).compareTo(cache1.getVisitedDate());
}
}
diff --git a/main/src/cgeo/geocaching/sorting/VoteComparator.java b/main/src/cgeo/geocaching/sorting/VoteComparator.java
index 09d1620..dc0304b 100644
--- a/main/src/cgeo/geocaching/sorting/VoteComparator.java
+++ b/main/src/cgeo/geocaching/sorting/VoteComparator.java
@@ -1,6 +1,6 @@
package cgeo.geocaching.sorting;
-import cgeo.geocaching.cgCache;
+import cgeo.geocaching.Geocache;
/**
* sorts caches by the users own voting (if available at all)
@@ -8,12 +8,12 @@ import cgeo.geocaching.cgCache;
public class VoteComparator extends AbstractCacheComparator {
@Override
- protected boolean canCompare(cgCache cache1, cgCache cache2) {
+ protected boolean canCompare(Geocache cache1, Geocache cache2) {
return true;
}
@Override
- protected int compareCaches(cgCache cache1, cgCache cache2) {
+ protected int compareCaches(Geocache cache1, Geocache cache2) {
// if there is no vote available, put that cache at the end of the list
return Float.compare(cache2.getMyVote(), cache1.getMyVote());
}
diff --git a/main/src/cgeo/geocaching/twitter/Twitter.java b/main/src/cgeo/geocaching/twitter/Twitter.java
index c630cec..f30830e 100644
--- a/main/src/cgeo/geocaching/twitter/Twitter.java
+++ b/main/src/cgeo/geocaching/twitter/Twitter.java
@@ -1,8 +1,9 @@
package cgeo.geocaching.twitter;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgTrackable;
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.geopoint.Geopoint;
@@ -42,7 +43,7 @@ public final class Twitter {
Log.e("Tweet could not be posted");
}
} catch (Exception e) {
- Log.e("cgBase.postTweet: " + e.toString());
+ Log.e("cgBase.postTweet", e);
}
}
@@ -55,7 +56,7 @@ public final class Twitter {
}
public static void postTweetCache(String geocode) {
- final cgCache cache = cgeoapplication.getInstance().loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
+ final Geocache cache = cgData.loadCache(geocode, LoadFlags.LOAD_CACHE_OR_DB);
String status;
final String url = cache.getUrl();
if (url.length() >= 100) {
@@ -76,7 +77,7 @@ public final class Twitter {
}
public static void postTweetTrackable(String geocode) {
- final cgTrackable trackable = cgeoapplication.getInstance().getTrackableByGeocode(geocode);
+ final Trackable trackable = cgData.loadTrackable(geocode);
String name = trackable.getName();
if (name.length() > 82) {
name = name.substring(0, 81) + '…';
diff --git a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
index 22ee0fb..196d92d 100644
--- a/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
+++ b/main/src/cgeo/geocaching/twitter/TwitterAuthorizationActivity.java
@@ -7,6 +7,7 @@ import cgeo.geocaching.network.Network;
import cgeo.geocaching.network.OAuth;
import cgeo.geocaching.network.Parameters;
import cgeo.geocaching.utils.Log;
+import cgeo.geocaching.utils.MatcherWrapper;
import ch.boye.httpclientandroidlib.client.entity.UrlEncodedFormEntity;
import ch.boye.httpclientandroidlib.util.EntityUtils;
@@ -24,7 +25,6 @@ import android.view.View;
import android.widget.Button;
import android.widget.EditText;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TwitterAuthorizationActivity extends AbstractActivity {
@@ -92,7 +92,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity {
super.onCreate(savedInstanceState);
setTheme();
- setContentView(R.layout.auth);
+ setContentView(R.layout.twitter_authorization_activity);
setTitle(res.getString(R.string.auth_twitter));
init();
@@ -130,24 +130,23 @@ public class TwitterAuthorizationActivity extends AbstractActivity {
}
private void requestToken() {
- final String host = "api.twitter.com";
- final String pathRequest = "/oauth/request_token";
- final String pathAuthorize = "/oauth/authorize";
- final String method = "GET";
int status = 0;
try {
final Parameters params = new Parameters();
+ final String method = "GET";
+ final String pathRequest = "/oauth/request_token";
+ final String host = "api.twitter.com";
OAuth.signOAuth(host, pathRequest, method, true, params, null, null);
final String line = Network.getResponseData(Network.getRequest("https://" + host + pathRequest, params));
if (StringUtils.isNotBlank(line)) {
- final Matcher paramsMatcher1 = paramsPattern1.matcher(line);
+ final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
if (paramsMatcher1.find()) {
OAtoken = paramsMatcher1.group(1);
}
- final Matcher paramsMatcher2 = paramsPattern2.matcher(line);
+ final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line);
if (paramsMatcher2.find()) {
OAtokenSecret = paramsMatcher2.group(1);
}
@@ -157,43 +156,44 @@ public class TwitterAuthorizationActivity extends AbstractActivity {
try {
final Parameters paramsBrowser = new Parameters();
paramsBrowser.put("oauth_callback", "oob");
+ final String pathAuthorize = "/oauth/authorize";
OAuth.signOAuth(host, pathAuthorize, "GET", true, paramsBrowser, OAtoken, OAtokenSecret);
final String encodedParams = EntityUtils.toString(new UrlEncodedFormEntity(paramsBrowser));
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://" + host + pathAuthorize + "?" + encodedParams)));
status = 1;
} catch (Exception e) {
- Log.e("TwitterAuthorizationActivity.requestToken(2): " + e.toString());
+ Log.e("TwitterAuthorizationActivity.requestToken(2)", e);
}
}
}
} catch (Exception e) {
- Log.e("TwitterAuthorizationActivity.requestToken(1): " + e.toString());
+ Log.e("TwitterAuthorizationActivity.requestToken(1)", e);
}
requestTokenHandler.sendEmptyMessage(status);
}
private void changeToken() {
- final String host = "api.twitter.com";
- final String path = "/oauth/access_token";
- final String method = "POST";
int status = 0;
try {
final Parameters params = new Parameters("oauth_verifier", pinEntry.getText().toString());
+ final String method = "POST";
+ final String path = "/oauth/access_token";
+ final String host = "api.twitter.com";
OAuth.signOAuth(host, path, method, true, params, OAtoken, OAtokenSecret);
final String line = StringUtils.defaultString(Network.getResponseData(Network.postRequest("https://" + host + path, params)));
OAtoken = "";
OAtokenSecret = "";
- final Matcher paramsMatcher1 = paramsPattern1.matcher(line);
+ final MatcherWrapper paramsMatcher1 = new MatcherWrapper(paramsPattern1, line);
if (paramsMatcher1.find()) {
OAtoken = paramsMatcher1.group(1);
}
- final Matcher paramsMatcher2 = paramsPattern2.matcher(line);
+ final MatcherWrapper paramsMatcher2 = new MatcherWrapper(paramsPattern2, line);
if (paramsMatcher2.find() && paramsMatcher2.groupCount() > 0) {
OAtokenSecret = paramsMatcher2.group(1);
}
@@ -207,7 +207,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity {
status = 1;
}
} catch (Exception e) {
- Log.e("TwitterAuthorizationActivity.changeToken: " + e.toString());
+ Log.e("TwitterAuthorizationActivity.changeToken", e);
}
changeTokensHandler.sendEmptyMessage(status);
@@ -242,7 +242,7 @@ public class TwitterAuthorizationActivity extends AbstractActivity {
@Override
public void onClick(View arg0) {
- if (((EditText) findViewById(R.id.pin)).getText().toString().length() == 0) {
+ if (StringUtils.isEmpty(((EditText) findViewById(R.id.pin)).getText().toString())) {
helpDialog(res.getString(R.string.auth_dialog_pin_title), res.getString(R.string.auth_dialog_pin_message));
return;
}
diff --git a/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
new file mode 100644
index 0000000..333ef11
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/AbstractCachingPageViewCreator.java
@@ -0,0 +1,32 @@
+package cgeo.geocaching.ui;
+
+import cgeo.geocaching.activity.AbstractViewPagerActivity.PageViewCreator;
+
+import android.view.View;
+
+/**
+ * View creator which destroys the created view on every {@link #notifyDataSetChanged()}.
+ *
+ * @param <ViewClass>
+ */
+public abstract class AbstractCachingPageViewCreator<ViewClass extends View> implements PageViewCreator {
+
+ public ViewClass view;
+
+ @Override
+ public final void notifyDataSetChanged() {
+ view = null;
+ }
+
+ @Override
+ public final View getView() {
+ if (view == null) {
+ view = getDispatchedView();
+ }
+
+ return view;
+ }
+
+ @Override
+ public abstract ViewClass getDispatchedView();
+}
diff --git a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
index 2a83ddc..e98bd77 100644
--- a/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
+++ b/main/src/cgeo/geocaching/ui/CacheDetailsCreator.java
@@ -1,7 +1,7 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Units;
@@ -35,7 +35,7 @@ public final class CacheDetailsCreator {
}
public TextView add(final int nameId, final CharSequence value) {
- final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_item, null);
+ final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_information_item, null);
final TextView nameView = (TextView) layout.findViewById(R.id.name);
nameView.setText(res.getString(nameId));
lastValueView = (TextView) layout.findViewById(R.id.value);
@@ -49,23 +49,22 @@ public final class CacheDetailsCreator {
}
public RelativeLayout addStars(final int nameId, final float value) {
- final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_layout, null);
+ final RelativeLayout layout = (RelativeLayout) activity.getLayoutInflater().inflate(R.layout.cache_information_item, null);
final TextView nameView = (TextView) layout.findViewById(R.id.name);
lastValueView = (TextView) layout.findViewById(R.id.value);
final LinearLayout layoutStars = (LinearLayout) layout.findViewById(R.id.stars);
nameView.setText(activity.getResources().getString(nameId));
lastValueView.setText(String.format("%.1f", value) + ' ' + activity.getResources().getString(R.string.cache_rating_of) + " 5");
- layoutStars.addView(createStarImages(value), 1);
+ createStarImages(layoutStars, value);
+ layoutStars.setVisibility(View.VISIBLE);
parentView.addView(layout);
return layout;
}
- private LinearLayout createStarImages(final float value) {
+ private void createStarImages(final ViewGroup starsContainer, final float value) {
final LayoutInflater inflater = LayoutInflater.from(activity);
- final LinearLayout starsContainer = new LinearLayout(activity);
- starsContainer.setOrientation(LinearLayout.HORIZONTAL);
for (int i = 0; i < 5; i++) {
ImageView star = (ImageView) inflater.inflate(R.layout.star, null);
@@ -78,11 +77,9 @@ public final class CacheDetailsCreator {
}
starsContainer.addView(star);
}
-
- return starsContainer;
}
- public void addCacheState(cgCache cache) {
+ public void addCacheState(Geocache cache) {
if (cache.isLogOffline() || cache.isArchived() || cache.isDisabled() || cache.isPremiumMembersOnly() || cache.isFound()) {
final List<String> states = new ArrayList<String>(5);
if (cache.isLogOffline()) {
@@ -104,7 +101,7 @@ public final class CacheDetailsCreator {
}
}
- public void addRating(cgCache cache) {
+ public void addRating(Geocache cache) {
if (cache.getRating() > 0) {
final RelativeLayout itemLayout = addStars(R.string.cache_rating, cache.getRating());
if (cache.getVotes() > 0) {
@@ -115,25 +112,25 @@ public final class CacheDetailsCreator {
}
}
- public void addSize(cgCache cache) {
+ public void addSize(Geocache cache) {
if (null != cache.getSize() && cache.showSize()) {
add(R.string.cache_size, cache.getSize().getL10n());
}
}
- public void addDifficulty(cgCache cache) {
+ public void addDifficulty(Geocache cache) {
if (cache.getDifficulty() > 0) {
addStars(R.string.cache_difficulty, cache.getDifficulty());
}
}
- public void addTerrain(cgCache cache) {
+ public void addTerrain(Geocache cache) {
if (cache.getTerrain() > 0) {
addStars(R.string.cache_terrain, cache.getTerrain());
}
}
- public void addDistance(final cgCache cache, final TextView cacheDistanceView) {
+ public void addDistance(final Geocache cache, final TextView cacheDistanceView) {
Float distance = null;
if (cache.getCoords() != null) {
final Geopoint currentCoords = cgeoapplication.getInstance().currentGeo().getCoords();
diff --git a/main/src/cgeo/geocaching/ui/CacheListAdapter.java b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
index 65d3fbc..41e27a6 100644
--- a/main/src/cgeo/geocaching/ui/CacheListAdapter.java
+++ b/main/src/cgeo/geocaching/ui/CacheListAdapter.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.ui;
import cgeo.geocaching.CacheDetailActivity;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.IGeoData;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheType;
@@ -12,6 +12,7 @@ import cgeo.geocaching.filter.IFilter;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.sorting.CacheComparator;
import cgeo.geocaching.sorting.DistanceComparator;
+import cgeo.geocaching.sorting.InverseComparator;
import cgeo.geocaching.sorting.VisitComparator;
import cgeo.geocaching.utils.AngleUtils;
import cgeo.geocaching.utils.Log;
@@ -43,11 +44,12 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
-public class CacheListAdapter extends ArrayAdapter<cgCache> {
+public class CacheListAdapter extends ArrayAdapter<Geocache> {
private LayoutInflater inflater = null;
private CacheComparator cacheComparator = null;
@@ -56,14 +58,15 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
private long lastSort = 0L;
private boolean selectMode = false;
private IFilter currentFilter = null;
- private List<cgCache> originalList = null;
+ private List<Geocache> originalList = null;
final private Set<CompassMiniView> compasses = new LinkedHashSet<CompassMiniView>();
final private Set<DistanceView> distances = new LinkedHashSet<DistanceView>();
final private CacheListType cacheListType;
final private Resources res;
/** Resulting list of caches */
- final private List<cgCache> list;
+ final private List<Geocache> list;
+ private boolean inverseSort = false;
private static final int SWIPE_MIN_DISTANCE = 60;
private static final int SWIPE_MAX_OFF_PATH = 100;
@@ -104,7 +107,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
ImageView dirImg;
}
- public CacheListAdapter(final Activity activity, final List<cgCache> list, CacheListType cacheListType) {
+ public CacheListAdapter(final Activity activity, final List<Geocache> list, CacheListType cacheListType) {
super(activity, 0, list);
final IGeoData currentGeo = cgeoapplication.getInstance().currentGeo();
if (currentGeo != null) {
@@ -149,6 +152,14 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
* @param comparator
*/
public void setComparator(final CacheComparator comparator) {
+ // selecting the same sorting twice will toggle the order
+ if (cacheComparator != null && comparator != null && cacheComparator.getClass().equals(comparator.getClass())) {
+ inverseSort = !inverseSort;
+ }
+ else {
+ // always reset the inversion for a new sorting criteria
+ inverseSort = false;
+ }
cacheComparator = comparator;
forceSort();
}
@@ -157,7 +168,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
return cacheComparator;
}
- public cgCache findCacheByGeocode(String geocode) {
+ public Geocache findCacheByGeocode(String geocode) {
for (int i = 0; i < getCount(); i++) {
if (getItem(i).getGeocode().equalsIgnoreCase(geocode)) {
return getItem(i);
@@ -172,7 +183,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
public void reFilter() {
if (currentFilter != null) {
// Back up the list again
- originalList = new ArrayList<cgCache>(list);
+ originalList = new ArrayList<Geocache>(list);
currentFilter.filter(list);
}
@@ -184,7 +195,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
public void setFilter(final IFilter filter) {
// Backup current caches list if it isn't backed up yet
if (originalList == null) {
- originalList = new ArrayList<cgCache>(list);
+ originalList = new ArrayList<Geocache>(list);
}
// If there is already a filter in place, this is a request to change or clear the filter, so we have to
@@ -213,7 +224,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
public int getCheckedCount() {
int checked = 0;
- for (cgCache cache : list) {
+ for (Geocache cache : list) {
if (cache.isStatusChecked()) {
checked++;
}
@@ -225,7 +236,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
this.selectMode = selectMode;
if (!selectMode) {
- for (final cgCache cache : list) {
+ for (final Geocache cache : list) {
cache.setStatusChecked(false);
}
}
@@ -241,7 +252,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
}
public void invertSelection() {
- for (cgCache cache : list) {
+ for (Geocache cache : list) {
cache.setStatusChecked(!cache.isStatusChecked());
}
notifyDataSetChanged();
@@ -257,7 +268,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
updateSortByDistance();
}
else {
- Collections.sort(list, cacheComparator);
+ Collections.sort(list, getPotentialInversion(cacheComparator));
}
notifyDataSetChanged();
@@ -291,8 +302,8 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
if (coords == null) {
return;
}
- final ArrayList<cgCache> oldList = new ArrayList<cgCache>(list);
- Collections.sort(list, new DistanceComparator(coords, list));
+ final ArrayList<Geocache> oldList = new ArrayList<Geocache>(list);
+ Collections.sort(list, getPotentialInversion(new DistanceComparator(coords, list)));
// avoid an update if the list has not changed due to location update
if (list.equals(oldList)) {
@@ -302,6 +313,13 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
lastSort = System.currentTimeMillis();
}
+ private Comparator<? super Geocache> getPotentialInversion(final CacheComparator comparator) {
+ if (inverseSort) {
+ return new InverseComparator(comparator);
+ }
+ return comparator;
+ }
+
private boolean isSortedByDistance() {
return cacheComparator == null || cacheComparator instanceof DistanceComparator;
}
@@ -328,7 +346,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
return null;
}
- final cgCache cache = getItem(position);
+ final Geocache cache = getItem(position);
View v = rowView;
@@ -390,17 +408,24 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
holder.logStatusMark.setVisibility(View.GONE);
}
- if (cache.getNameSp() == null) {
- cache.setNameSp((new Spannable.Factory()).newSpannable(cache.getName()));
- if (cache.isDisabled() || cache.isArchived()) { // strike
- cache.getNameSp().setSpan(new StrikethroughSpan(), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- if (cache.isArchived()) {
- cache.getNameSp().setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, cache.getNameSp().toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ Spannable spannable = null;
+ if (cache.isDisabled() || cache.isArchived()) { // strike
+ spannable = Spannable.Factory.getInstance().newSpannable(cache.getName());
+ spannable.setSpan(new StrikethroughSpan(), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ if (cache.isArchived()) { // red color
+ if (spannable == null) {
+ spannable = Spannable.Factory.getInstance().newSpannable(cache.getName());
}
+ spannable.setSpan(new ForegroundColorSpan(res.getColor(R.color.archived_cache_color)), 0, spannable.toString().length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
- holder.text.setText(cache.getNameSp(), TextView.BufferType.SPANNABLE);
+ if (spannable != null) {
+ holder.text.setText(spannable, TextView.BufferType.SPANNABLE);
+ }
+ else {
+ holder.text.setText(cache.getName());
+ }
holder.text.setCompoundDrawablesWithIntrinsicBounds(getCacheIcon(cache), null, null, null);
if (cache.getInventoryItems() > 0) {
@@ -508,7 +533,7 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
return v;
}
- private static Drawable getCacheIcon(cgCache cache) {
+ private static Drawable getCacheIcon(Geocache cache) {
int hashCode = getIconHashCode(cache.getType(), cache.hasUserModifiedCoords() || cache.hasFinalDefined());
final Drawable drawable = gcIconDrawables.get(hashCode);
if (drawable != null) {
@@ -529,9 +554,9 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
private static class SelectionCheckBoxListener implements View.OnClickListener {
- private final cgCache cache;
+ private final Geocache cache;
- public SelectionCheckBoxListener(cgCache cache) {
+ public SelectionCheckBoxListener(Geocache cache) {
this.cache = cache;
}
@@ -546,9 +571,9 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
private boolean touch = true;
private final GestureDetector gestureDetector;
- private final cgCache cache;
+ private final Geocache cache;
- public TouchListener(final cgCache cache) {
+ public TouchListener(final Geocache cache) {
this.cache = cache;
final FlingGesture dGesture = new FlingGesture(cache);
gestureDetector = new GestureDetector(getContext(), dGesture);
@@ -597,9 +622,9 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
private class FlingGesture extends GestureDetector.SimpleOnGestureListener {
- private final cgCache cache;
+ private final Geocache cache;
- public FlingGesture(cgCache cache) {
+ public FlingGesture(Geocache cache) {
this.cache = cache;
}
@@ -627,20 +652,20 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
return true;
}
} catch (Exception e) {
- Log.w("CacheListAdapter.FlingGesture.onFling: " + e.toString());
+ Log.w("CacheListAdapter.FlingGesture.onFling", e);
}
return false;
}
}
- public List<cgCache> getFilteredList() {
+ public List<Geocache> getFilteredList() {
return list;
}
- public List<cgCache> getCheckedCaches() {
- final ArrayList<cgCache> result = new ArrayList<cgCache>();
- for (cgCache cache : list) {
+ public List<Geocache> getCheckedCaches() {
+ final ArrayList<Geocache> result = new ArrayList<Geocache>();
+ for (Geocache cache : list) {
if (cache.isStatusChecked()) {
result.add(cache);
}
@@ -648,12 +673,12 @@ public class CacheListAdapter extends ArrayAdapter<cgCache> {
return result;
}
- public List<cgCache> getCheckedOrAllCaches() {
- final List<cgCache> result = getCheckedCaches();
+ public List<Geocache> getCheckedOrAllCaches() {
+ final List<Geocache> result = getCheckedCaches();
if (!result.isEmpty()) {
return result;
}
- return new ArrayList<cgCache>(list);
+ return new ArrayList<Geocache>(list);
}
public int getCheckedOrAllCount() {
diff --git a/main/src/cgeo/geocaching/ui/CompassMiniView.java b/main/src/cgeo/geocaching/ui/CompassMiniView.java
index 44fb8e2..da8f69e 100644
--- a/main/src/cgeo/geocaching/ui/CompassMiniView.java
+++ b/main/src/cgeo/geocaching/ui/CompassMiniView.java
@@ -97,17 +97,17 @@ final public class CompassMiniView extends View {
targetCoords = point;
}
- protected void updateAzimuth(float azimuth) {
+ public void updateAzimuth(float azimuth) {
this.azimuth = azimuth;
updateDirection();
}
- protected void updateHeading(float heading) {
+ public void updateHeading(float heading) {
this.heading = heading;
updateDirection();
}
- protected void updateCurrentCoords(final Geopoint currentCoords) {
+ public void updateCurrentCoords(final Geopoint currentCoords) {
if (currentCoords == null || targetCoords == null) {
return;
}
diff --git a/main/src/cgeo/geocaching/ui/CompassView.java b/main/src/cgeo/geocaching/ui/CompassView.java
index 048e280..0ef3a43 100644
--- a/main/src/cgeo/geocaching/ui/CompassView.java
+++ b/main/src/cgeo/geocaching/ui/CompassView.java
@@ -185,16 +185,13 @@ public class CompassView extends View {
int canvasCenterX = (compassRoseWidth / 2) + ((getWidth() - compassRoseWidth) / 2);
int canvasCenterY = (compassRoseHeight / 2) + ((getHeight() - compassRoseHeight) / 2);
- int marginLeftTemp;
- int marginTopTemp;
-
super.onDraw(canvas);
canvas.save();
canvas.setDrawFilter(setfil);
- marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2;
- marginTopTemp = (getHeight() - compassUnderlayHeight) / 2;
+ int marginLeftTemp = (getWidth() - compassUnderlayWidth) / 2;
+ int marginTopTemp = (getHeight() - compassUnderlayHeight) / 2;
canvas.drawBitmap(compassUnderlay, marginLeftTemp, marginTopTemp, null);
diff --git a/main/src/cgeo/geocaching/ui/Formatter.java b/main/src/cgeo/geocaching/ui/Formatter.java
index 53a7276..412b993 100644
--- a/main/src/cgeo/geocaching/ui/Formatter.java
+++ b/main/src/cgeo/geocaching/ui/Formatter.java
@@ -1,8 +1,8 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.R;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgWaypoint;
+import cgeo.geocaching.Waypoint;
import cgeo.geocaching.cgeoapplication;
import cgeo.geocaching.enumerations.CacheListType;
import cgeo.geocaching.enumerations.CacheSize;
@@ -13,6 +13,7 @@ import org.apache.commons.lang3.StringUtils;
import android.content.Context;
import android.text.format.DateUtils;
+import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
@@ -70,8 +71,8 @@ public abstract class Formatter {
* @return the formatted string
*/
public static String formatShortDate(long date) {
- return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE
- | DateUtils.FORMAT_NUMERIC_DATE);
+ DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context);
+ return dateFormat.format(date);
}
/**
@@ -108,7 +109,7 @@ public abstract class Formatter {
return DateUtils.formatDateTime(context, date, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL);
}
- public static String formatCacheInfoLong(cgCache cache, CacheListType cacheListType) {
+ public static String formatCacheInfoLong(Geocache cache, CacheListType cacheListType) {
final ArrayList<String> infos = new ArrayList<String>();
if (StringUtils.isNotBlank(cache.getGeocode())) {
infos.add(cache.getGeocode());
@@ -125,7 +126,7 @@ public abstract class Formatter {
return StringUtils.join(infos, Formatter.SEPARATOR);
}
- public static String formatCacheInfoShort(cgCache cache) {
+ public static String formatCacheInfoShort(Geocache cache) {
final ArrayList<String> infos = new ArrayList<String>();
if (cache.hasDifficulty()) {
infos.add("D " + String.format("%.1f", cache.getDifficulty()));
@@ -143,7 +144,7 @@ public abstract class Formatter {
return StringUtils.join(infos, Formatter.SEPARATOR);
}
- public static String formatCacheInfoHistory(cgCache cache) {
+ public static String formatCacheInfoHistory(Geocache cache) {
final ArrayList<String> infos = new ArrayList<String>(3);
infos.add(StringUtils.upperCase(cache.getGeocode()));
infos.add(Formatter.formatDate(cache.getVisitedDate()));
@@ -151,12 +152,13 @@ public abstract class Formatter {
return StringUtils.join(infos, Formatter.SEPARATOR);
}
- public static String formatWaypointInfo(cgWaypoint waypoint) {
+ public static String formatWaypointInfo(Waypoint waypoint) {
final List<String> infos = new ArrayList<String>(3);
- if (WaypointType.ALL_TYPES_EXCEPT_OWN.contains(waypoint.getWaypointType())) {
- infos.add(waypoint.getWaypointType().getL10n());
+ WaypointType waypointType = waypoint.getWaypointType();
+ if (waypointType != WaypointType.OWN && waypointType != null) {
+ infos.add(waypointType.getL10n());
}
- if (cgWaypoint.PREFIX_OWN.equalsIgnoreCase(waypoint.getPrefix())) {
+ if (Waypoint.PREFIX_OWN.equalsIgnoreCase(waypoint.getPrefix())) {
infos.add(cgeoapplication.getInstance().getString(R.string.waypoint_custom));
} else {
if (StringUtils.isNotBlank(waypoint.getPrefix())) {
diff --git a/main/src/cgeo/geocaching/ui/ImagesList.java b/main/src/cgeo/geocaching/ui/ImagesList.java
index 3d6f95c..9464114 100644
--- a/main/src/cgeo/geocaching/ui/ImagesList.java
+++ b/main/src/cgeo/geocaching/ui/ImagesList.java
@@ -1,14 +1,14 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.Image;
import cgeo.geocaching.R;
import cgeo.geocaching.StoredList;
-import cgeo.geocaching.cgImage;
import cgeo.geocaching.files.LocalStorage;
import cgeo.geocaching.network.HtmlImage;
+import cgeo.geocaching.utils.IOUtils;
import cgeo.geocaching.utils.Log;
import org.apache.commons.lang3.StringUtils;
-import org.mapsforge.core.IOUtils;
import android.app.Activity;
import android.app.ProgressDialog;
@@ -43,7 +43,7 @@ public class ImagesList {
private static final int MENU_BROWSER = 202;
private BitmapDrawable currentDrawable;
- private cgImage currentImage;
+ private Image currentImage;
public enum ImageType {
LogImages(R.string.cache_log_images_title, R.string.cache_log_images_loading),
@@ -53,7 +53,7 @@ public class ImagesList {
private final int titleResId;
private final int loadingResId;
- private ImageType(final int title, final int loading) {
+ ImageType(final int title, final int loading) {
this.titleResId = title;
this.loadingResId = loading;
}
@@ -73,7 +73,7 @@ public class ImagesList {
/**
* map image view id to image
*/
- private final SparseArray<cgImage> images = new SparseArray<cgImage>();
+ private final SparseArray<Image> images = new SparseArray<Image>();
private final String geocode;
private LinearLayout imagesView;
@@ -83,7 +83,7 @@ public class ImagesList {
inflater = activity.getLayoutInflater();
}
- public void loadImages(final View parentView, final List<cgImage> images, ImageType imageType, final boolean offline) {
+ public void loadImages(final View parentView, final List<Image> images, ImageType imageType, final boolean offline) {
imagesView = (LinearLayout) parentView.findViewById(R.id.spoiler_list);
@@ -95,9 +95,8 @@ public class ImagesList {
progressDialog.setMax(count);
progressDialog.show();
- LinearLayout rowView;
- for (final cgImage img : images) {
- rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null);
+ for (final Image img : images) {
+ LinearLayout rowView = (LinearLayout) inflater.inflate(R.layout.cache_image_item, null);
if (StringUtils.isNotBlank(img.getTitle())) {
((TextView) rowView.findViewById(R.id.title)).setText(Html.fromHtml(img.getTitle()));
@@ -118,10 +117,10 @@ public class ImagesList {
private class AsyncImgLoader extends AsyncTask<Void, Void, BitmapDrawable> {
final private LinearLayout view;
- final private cgImage img;
+ final private Image img;
final boolean offline;
- public AsyncImgLoader(final LinearLayout view, final cgImage img, final boolean offline) {
+ public AsyncImgLoader(final LinearLayout view, final Image img, final boolean offline) {
this.view = view;
this.img = img;
this.offline = offline;
@@ -179,10 +178,6 @@ public class ImagesList {
bitmaps.clear();
}
- public cgImage getImage(int id) {
- return images.get(id);
- }
-
public void onCreateContextMenu(ContextMenu menu, View v) {
final Resources res = activity.getResources();
menu.setHeaderTitle(res.getString(R.string.cache_image));
@@ -215,7 +210,7 @@ public class ImagesList {
fos = new FileOutputStream(file);
image.getBitmap().compress(CompressFormat.JPEG, 100, fos);
} catch (Exception e) {
- Log.e("ImagesActivity.handleMessage.onClick: " + e.toString());
+ Log.e("ImagesActivity.handleMessage.onClick", e);
return;
} finally {
IOUtils.closeQuietly(fos);
diff --git a/main/src/cgeo/geocaching/ui/LoggingUI.java b/main/src/cgeo/geocaching/ui/LoggingUI.java
index 0e048c3..2615947 100644
--- a/main/src/cgeo/geocaching/ui/LoggingUI.java
+++ b/main/src/cgeo/geocaching/ui/LoggingUI.java
@@ -1,10 +1,10 @@
package cgeo.geocaching.ui;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.LogEntry;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.cgData;
import cgeo.geocaching.activity.IAbstractActivity;
import cgeo.geocaching.enumerations.LogType;
@@ -52,7 +52,7 @@ public class LoggingUI extends AbstractUIFactory {
private final int stringId;
- private SpecialLogType(final int stringId) {
+ SpecialLogType(final int stringId) {
this.stringId = stringId;
}
@@ -65,7 +65,7 @@ public class LoggingUI extends AbstractUIFactory {
private static final int MENU_LOG_VISIT = 100;
private static final int MENU_LOG_VISIT_OFFLINE = 101;
- public static void addMenuItems(final Menu menu, final cgCache cache) {
+ public static void addMenuItems(final Menu menu, final Geocache cache) {
if (cache == null) {
return;
}
@@ -80,7 +80,7 @@ public class LoggingUI extends AbstractUIFactory {
}
}
- public static boolean onMenuItemSelected(final MenuItem item, IAbstractActivity activity, cgCache cache) {
+ public static boolean onMenuItemSelected(final MenuItem item, IAbstractActivity activity, Geocache cache) {
switch (item.getItemId()) {
case MENU_LOG_VISIT:
cache.logVisit(activity);
@@ -93,8 +93,8 @@ public class LoggingUI extends AbstractUIFactory {
}
}
- private static void showOfflineMenu(final cgCache cache, final Activity activity) {
- final LogEntry currentLog = cgeoapplication.getInstance().loadLogOffline(cache.getGeocode());
+ private static void showOfflineMenu(final Geocache cache, final Activity activity) {
+ final LogEntry currentLog = cgData.loadLogOffline(cache.getGeocode());
final LogType currentLogType = currentLog == null ? null : currentLog.type;
final List<LogType> logTypes = cache.getPossibleLogTypes();
@@ -123,7 +123,8 @@ public class LoggingUI extends AbstractUIFactory {
break;
case CLEAR_LOG:
- cgeoapplication.getInstance().clearLogOffline(cache.getGeocode());
+ cgData.clearLogOffline(cache.getGeocode());
+ break;
}
} else {
cache.logOffline(activity, logTypeEntry.logType);
diff --git a/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java
new file mode 100644
index 0000000..4724466
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/WeakReferenceHandler.java
@@ -0,0 +1,27 @@
+package cgeo.geocaching.ui;
+
+import android.app.Activity;
+import android.os.Handler;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Standard handler implementation which uses a weak reference to its activity. This avoids that activities stay in
+ * memory due to references from the handler to the activity (see Android Lint warning "HandlerLeak")
+ *
+ * Create static private subclasses of this handler class in your activity.
+ *
+ * @param <ActivityType>
+ */
+public abstract class WeakReferenceHandler<ActivityType extends Activity> extends Handler {
+
+ private final WeakReference<ActivityType> activityRef;
+
+ protected WeakReferenceHandler(final ActivityType activity) {
+ this.activityRef = new WeakReference<ActivityType>(activity);
+ }
+
+ protected ActivityType getActivity() {
+ return activityRef.get();
+ }
+}
diff --git a/main/src/cgeo/geocaching/cgeocoords.java b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
index 1cf9630..224d527 100644
--- a/main/src/cgeo/geocaching/cgeocoords.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CoordinatesInputDialog.java
@@ -1,5 +1,9 @@
-package cgeo.geocaching;
+package cgeo.geocaching.ui.dialog;
+import cgeo.geocaching.Geocache;
+import cgeo.geocaching.IGeoData;
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
import cgeo.geocaching.Settings.coordInputFormatEnum;
import cgeo.geocaching.activity.AbstractActivity;
import cgeo.geocaching.activity.ActivityMixin;
@@ -24,11 +28,11 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
-public class cgeocoords extends Dialog {
+public class CoordinatesInputDialog extends Dialog {
final private AbstractActivity context;
final private IGeoData geo;
- final private cgCache cache;
+ final private Geocache cache;
private Geopoint gp;
private EditText eLat, eLon;
@@ -42,7 +46,7 @@ public class cgeocoords extends Dialog {
private coordInputFormatEnum currentFormat = null;
- public cgeocoords(final AbstractActivity context, final cgCache cache, final Geopoint gp, final IGeoData geo) {
+ public CoordinatesInputDialog(final AbstractActivity context, final Geocache cache, final Geopoint gp, final IGeoData geo) {
super(context);
this.context = context;
this.geo = geo;
@@ -378,6 +382,8 @@ public class cgeocoords extends Dialog {
break;
case Plain:
// This case has been handled above
+ default:
+ throw new IllegalArgumentException();
}
return true;
diff --git a/main/src/cgeo/geocaching/ui/CustomProgressDialog.java b/main/src/cgeo/geocaching/ui/dialog/CustomProgressDialog.java
index f7772be..93d4b87 100644
--- a/main/src/cgeo/geocaching/ui/CustomProgressDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/CustomProgressDialog.java
@@ -1,4 +1,4 @@
-package cgeo.geocaching.ui;
+package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.utils.Log;
diff --git a/main/src/cgeo/geocaching/ui/DateDialog.java b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
index 5dfd9b9..a9c579c 100644
--- a/main/src/cgeo/geocaching/ui/DateDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/DateDialog.java
@@ -1,4 +1,4 @@
-package cgeo.geocaching.ui;
+package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.R;
diff --git a/main/src/cgeo/geocaching/ui/EditorDialog.java b/main/src/cgeo/geocaching/ui/dialog/EditorDialog.java
index 50b3e27..c73e25d 100644
--- a/main/src/cgeo/geocaching/ui/EditorDialog.java
+++ b/main/src/cgeo/geocaching/ui/dialog/EditorDialog.java
@@ -1,4 +1,4 @@
-package cgeo.geocaching.ui;
+package cgeo.geocaching.ui.dialog;
import cgeo.geocaching.CacheDetailActivity;
import cgeo.geocaching.R;
@@ -53,7 +53,7 @@ public class EditorDialog extends Dialog {
@Override
public void show() {
super.show();
- getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
+ getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
}
diff --git a/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
new file mode 100644
index 0000000..9955958
--- /dev/null
+++ b/main/src/cgeo/geocaching/ui/dialog/LiveMapInfoDialogBuilder.java
@@ -0,0 +1,43 @@
+package cgeo.geocaching.ui.dialog;
+
+import cgeo.geocaching.R;
+import cgeo.geocaching.Settings;
+import cgeo.geocaching.cgeoapplication;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.view.View;
+import android.widget.CheckBox;
+
+public class LiveMapInfoDialogBuilder {
+
+ public static AlertDialog create(Activity activity) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+
+ final View layout = activity.getLayoutInflater().inflate(R.layout.livemapinfo, null);
+ builder.setView(layout);
+
+ final CheckBox checkBoxHide = (CheckBox) layout.findViewById(R.id.live_map_hint_hide);
+
+ final int showCount = Settings.getLiveMapHintShowCount();
+ if (showCount > 2) {
+ checkBoxHide.setVisibility(View.VISIBLE);
+ }
+ Settings.setLiveMapHintShowCount(showCount + 1);
+
+ builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ cgeoapplication.getInstance().setLiveMapHintShown();
+ if (checkBoxHide.getVisibility() == View.VISIBLE && checkBoxHide.isChecked()) {
+ Settings.setHideLiveHint(true);
+ }
+ }
+ });
+ return builder.create();
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/utils/AngleUtils.java b/main/src/cgeo/geocaching/utils/AngleUtils.java
index e2b4a66..6e59a91 100644
--- a/main/src/cgeo/geocaching/utils/AngleUtils.java
+++ b/main/src/cgeo/geocaching/utils/AngleUtils.java
@@ -8,9 +8,11 @@ public class AngleUtils {
/**
* Return the angle to turn of to go from an angle to the other
- *
- * @param from the origin angle in degrees
- * @param to the target angle in degreees
+ *
+ * @param from
+ * the origin angle in degrees
+ * @param to
+ * the target angle in degrees
* @return a value in degrees, in the [-180, 180[ range
*/
public static float difference(final float from, final float to) {
diff --git a/main/src/cgeo/geocaching/utils/CryptUtils.java b/main/src/cgeo/geocaching/utils/CryptUtils.java
index f04327e..df2baa0 100644
--- a/main/src/cgeo/geocaching/utils/CryptUtils.java
+++ b/main/src/cgeo/geocaching/utils/CryptUtils.java
@@ -46,16 +46,14 @@ public final class CryptUtils {
boolean plaintext = false;
final int length = text.length();
- int c;
- int capitalized;
for (int index = 0; index < length; index++) {
- c = text.charAt(index);
+ int c = text.charAt(index);
if (c == '[') {
plaintext = true;
} else if (c == ']') {
plaintext = false;
} else if (!plaintext) {
- capitalized = c & 32;
+ int capitalized = c & 32;
c &= ~capitalized;
c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c)
| capitalized;
@@ -73,7 +71,7 @@ public final class CryptUtils {
digest.update(text.getBytes(), 0, text.length());
hashed = new BigInteger(1, digest.digest()).toString(16);
} catch (Exception e) {
- Log.e("cgBase.md5: " + e.toString());
+ Log.e("cgBase.md5", e);
}
return hashed;
@@ -87,7 +85,7 @@ public final class CryptUtils {
digest.update(text.getBytes(), 0, text.length());
hashed = new BigInteger(1, digest.digest()).toString(16);
} catch (Exception e) {
- Log.e("cgBase.sha1: " + e.toString());
+ Log.e("cgBase.sha1", e);
}
return hashed;
@@ -102,7 +100,7 @@ public final class CryptUtils {
mac.init(secretKeySpec);
macBytes = mac.doFinal(text.getBytes());
} catch (Exception e) {
- Log.e("cgBase.hashHmac: " + e.toString());
+ Log.e("cgBase.hashHmac", e);
}
return macBytes;
@@ -116,16 +114,14 @@ public final class CryptUtils {
boolean plaintext = false;
final int length = span.length();
- int c;
- int capitalized;
for (int index = 0; index < length; index++) {
- c = span.charAt(index);
+ int c = span.charAt(index);
if (c == '[') {
plaintext = true;
} else if (c == ']') {
plaintext = false;
} else if (!plaintext) {
- capitalized = c & 32;
+ int capitalized = c & 32;
c &= ~capitalized;
c = ((c >= 'A') && (c <= 'Z') ? ((c - 'A' + 13) % 26 + 'A') : c)
| capitalized;
diff --git a/main/src/cgeo/geocaching/utils/IOUtils.java b/main/src/cgeo/geocaching/utils/IOUtils.java
new file mode 100644
index 0000000..73db12f
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/IOUtils.java
@@ -0,0 +1,20 @@
+package cgeo.geocaching.utils;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+final public class IOUtils {
+
+ private IOUtils() {}
+
+ public static void closeQuietly(final Closeable closeable) {
+ if (closeable != null) {
+ try {
+ closeable.close();
+ } catch (final IOException e) {
+ Log.w("closeQuietly: unable to close " + closeable, e);
+ }
+ }
+ }
+
+}
diff --git a/main/src/cgeo/geocaching/utils/ImageHelper.java b/main/src/cgeo/geocaching/utils/ImageHelper.java
index 4c18b06..98cad64 100644
--- a/main/src/cgeo/geocaching/utils/ImageHelper.java
+++ b/main/src/cgeo/geocaching/utils/ImageHelper.java
@@ -1,13 +1,12 @@
package cgeo.geocaching.utils;
import cgeo.geocaching.cgeoapplication;
+import cgeo.geocaching.compatibility.Compatibility;
-import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
-import android.view.Display;
-import android.view.WindowManager;
public class ImageHelper {
@@ -24,9 +23,9 @@ public class ImageHelper {
*/
public static BitmapDrawable scaleBitmapToFitDisplay(final Bitmap image) {
final cgeoapplication app = cgeoapplication.getInstance();
- final Display display = ((WindowManager) app.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- final int maxWidth = display.getWidth() - 25;
- final int maxHeight = display.getHeight() - 25;
+ Point displaySize = Compatibility.getDisplaySize();
+ final int maxWidth = displaySize.x - 25;
+ final int maxHeight = displaySize.y - 25;
Bitmap result = image;
int width = image.getWidth();
diff --git a/main/src/cgeo/geocaching/utils/LazyInitializedList.java b/main/src/cgeo/geocaching/utils/LazyInitializedList.java
index 25af811..27649e8 100644
--- a/main/src/cgeo/geocaching/utils/LazyInitializedList.java
+++ b/main/src/cgeo/geocaching/utils/LazyInitializedList.java
@@ -1,103 +1,63 @@
package cgeo.geocaching.utils;
+import java.util.AbstractList;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.Callable;
-public abstract class LazyInitializedList<ElementType> implements Iterable<ElementType> {
+public abstract class LazyInitializedList<ElementType> extends AbstractList<ElementType> implements Callable<List<ElementType>> {
private volatile List<ElementType> list;
- private void initializeList() {
+ private List<ElementType> getList() {
if (list == null) {
- synchronized (this) {
- if (list == null) {
- list = loadFromDatabase();
+ synchronized(this) {
+ try {
+ list = call();
+ if (list == null) {
+ Log.e("LazyInitializedList.getList: null result");
+ }
+ } catch (final Exception e) {
+ Log.e("LazyInitializedList.getList", e);
}
}
}
+ return list;
}
- protected abstract List<ElementType> loadFromDatabase();
-
- public void add(final ElementType element) {
- initializeList();
- list.add(element);
- }
-
- public void prepend(final ElementType element) {
- initializeList();
- list.add(0, element);
- }
-
- public void set(final List<ElementType> elements) {
- if (elements != null) {
- list = new ArrayList<ElementType>(elements);
- } else {
- list = new ArrayList<ElementType>();
- }
- }
-
- public void set(LazyInitializedList<ElementType> other) {
- if (other != null) {
- list = new ArrayList<ElementType>(other.asList());
- } else {
- list = new ArrayList<ElementType>();
- }
+ @Override
+ public boolean add(final ElementType element) {
+ return getList().add(element);
}
- public boolean isEmpty() {
- initializeList();
- return list.isEmpty();
+ @Override
+ public ElementType set(final int index, final ElementType element) {
+ return getList().set(index, element);
}
+ @Override
public ElementType remove(final int index) {
- initializeList();
- return list.remove(index);
+ return getList().remove(index);
}
+ @Override
public void add(int index, final ElementType element) {
- initializeList();
- list.add(index, element);
+ getList().add(index, element);
}
+ @Override
public int size() {
- initializeList();
- return list.size();
+ return getList().size();
}
@Override
- public Iterator<ElementType> iterator() {
- initializeList();
- return list.iterator();
- }
-
public ElementType get(final int index) {
- initializeList();
- return list.get(index);
+ return getList().get(index);
}
- public boolean contains(final ElementType element) {
- initializeList();
- return list.contains(element);
- }
-
- public boolean isNotEmpty() {
- initializeList();
- return !list.isEmpty();
- }
-
- /**
- * @return an unmodifiable list of the elements
- */
- public List<ElementType> asList() {
- initializeList();
- return Collections.unmodifiableList(list);
+ @Override
+ public void clear() {
+ list = new ArrayList<ElementType>();
}
- public int indexOf(ElementType element) {
- initializeList();
- return list.indexOf(element);
- }
}
diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java
index f0bc4f5..6122532 100644
--- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java
+++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedMap.java
@@ -16,7 +16,7 @@ import java.util.Map;
*/
public abstract class LeastRecentlyUsedMap<K, V> extends LinkedHashMap<K, V> {
- private static enum OperationModes {
+ private enum OperationModes {
LRU_CACHE, BOUNDED
}
diff --git a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
index b654fd6..698d38a 100644
--- a/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
+++ b/main/src/cgeo/geocaching/utils/LeastRecentlyUsedSet.java
@@ -9,7 +9,7 @@ import java.util.List;
/**
* Synchronized set wrapper for the LeastRecentlyUsedMap.
- *
+ *
* This code is heavily based on the HashSet code that represent Map as a Set.
* Unfortunately HashSet does not allow to use a custom Map as its Storage.
* Therefore overriding removeEldestEntry() is impossible for a normal LinkedHashSet.
@@ -50,7 +50,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
/**
* Synchronized access to set size
* Copy of the HashSet code if size()
- *
+ *
* @see HashSet
*/
@Override
@@ -61,7 +61,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
/**
* Synchronized check of set emptiness
* Copy of the HashSet code if isEmpty()
- *
+ *
* @see HashSet
*/
@Override
@@ -72,7 +72,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
/**
* Synchronized check for containment
* Copy of the HashSet code if contains()
- *
+ *
* @see HashSet
*/
@Override
@@ -83,18 +83,21 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
/**
* Synchronized addition of an item
* Copy of the HashSet code if add()
- *
+ *
* @see HashSet
*/
@Override
public synchronized boolean add(E e) {
+ if (e == null) {
+ throw new IllegalArgumentException("LeastRecentlyUsedSet cannot take null element");
+ }
return map.put(e, PRESENT) == null;
}
/**
* Synchronized removal of a contained item
* Copy of the HashSet code if remove()
- *
+ *
* @see HashSet
*/
@Override
@@ -117,7 +120,7 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
/**
* Synchronized clearing of the set
* Copy of the HashSet code if clear()
- *
+ *
* @see HashSet
*/
@Override
@@ -128,12 +131,12 @@ public class LeastRecentlyUsedSet<E> extends AbstractSet<E>
/**
* (synchronized) Clone of the set
* Copy of the HashSet code if clone()
- *
+ *
* @see HashSet
*/
@Override
@SuppressWarnings("unchecked")
- public Object clone() {
+ public Object clone() throws CloneNotSupportedException {
try {
synchronized (this) {
final LeastRecentlyUsedSet<E> newSet = (LeastRecentlyUsedSet<E>) super.clone();
diff --git a/main/src/cgeo/geocaching/utils/Log.java b/main/src/cgeo/geocaching/utils/Log.java
index 6213661..6d57b75 100644
--- a/main/src/cgeo/geocaching/utils/Log.java
+++ b/main/src/cgeo/geocaching/utils/Log.java
@@ -1,5 +1,11 @@
package cgeo.geocaching.utils;
+import android.os.Environment;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
final public class Log {
@@ -9,6 +15,7 @@ final public class Log {
* the debug flag is cached here so that we don't need to access the settings every time we have to evaluate it
*/
private static boolean isDebug = true;
+ private static boolean first = true;
public static boolean isDebug() {
return isDebug;
@@ -74,4 +81,31 @@ final public class Log {
public static void e(final String msg, final Throwable t) {
android.util.Log.e(TAG, msg, t);
}
+
+ /**
+ * Log the whole content of a string into "/sdcard/cgeo-debug.log".
+ * <br/>
+ * Sometimes, the string we want to work on while debugging or developing a new feature is too long to
+ * be fully stored in Android logcat. This method will log the content of the string in a file named
+ * "/sdcard/cgeo-debug.log". The file will be reset at every run, and if called several times during a run,
+ * the contents will be appended to one another.
+ * <br/>
+ * <strong>This method should never be called in production.</strong>
+ *
+ * @param msg the message to log, or to add to the log if other messages have been stored in the same run
+ */
+ public synchronized static void logToFile(final String msg) {
+ final File file = new File(Environment.getExternalStorageDirectory(), "cgeo-debug.log");
+ if (first) {
+ first = false;
+ file.delete();
+ }
+ try {
+ final Writer writer = new FileWriter(file, true);
+ writer.write(msg);
+ writer.close();
+ } catch (final IOException e) {
+ Log.e("logToFile: cannot write to " + file, e);
+ }
+ }
}
diff --git a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
index 7cacd9d..0a8e547 100644
--- a/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
+++ b/main/src/cgeo/geocaching/utils/LogTemplateProvider.java
@@ -2,8 +2,8 @@ package cgeo.geocaching.utils;
import cgeo.geocaching.R;
import cgeo.geocaching.Settings;
-import cgeo.geocaching.cgCache;
-import cgeo.geocaching.cgTrackable;
+import cgeo.geocaching.Trackable;
+import cgeo.geocaching.Geocache;
import cgeo.geocaching.connector.gc.GCConstants;
import cgeo.geocaching.connector.gc.Login;
import cgeo.geocaching.network.Network;
@@ -28,15 +28,15 @@ public class LogTemplateProvider {
*
*/
public static class LogContext {
- private cgCache cache;
- private cgTrackable trackable;
+ private Geocache cache;
+ private Trackable trackable;
private boolean offline = false;
- public LogContext(final cgCache cache) {
+ public LogContext(final Geocache cache) {
this(cache, false);
}
- public LogContext(final cgTrackable trackable) {
+ public LogContext(final Trackable trackable) {
this.trackable = trackable;
}
@@ -44,16 +44,16 @@ public class LogTemplateProvider {
this(null, offline);
}
- public LogContext(final cgCache cache, boolean offline) {
+ public LogContext(final Geocache cache, boolean offline) {
this.cache = cache;
this.offline = offline;
}
- public cgCache getCache() {
+ public Geocache getCache() {
return cache;
}
- public cgTrackable getTrackable() {
+ public Trackable getTrackable() {
return trackable;
}
@@ -148,11 +148,11 @@ public class LogTemplateProvider {
@Override
public String getValue(final LogContext context) {
- cgTrackable trackable = context.getTrackable();
+ Trackable trackable = context.getTrackable();
if (trackable != null) {
return trackable.getOwner();
}
- cgCache cache = context.getCache();
+ Geocache cache = context.getCache();
if (cache != null) {
return cache.getOwnerDisplayName();
}
diff --git a/main/src/cgeo/geocaching/utils/MatcherWrapper.java b/main/src/cgeo/geocaching/utils/MatcherWrapper.java
new file mode 100644
index 0000000..c3c1663
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/MatcherWrapper.java
@@ -0,0 +1,91 @@
+package cgeo.geocaching.utils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Wrapper around the regex {@link Matcher} class. This implementation optimizes the memory usage of the matched
+ * Strings.
+ *
+ */
+public class MatcherWrapper {
+ private final Matcher matcher;
+
+ public MatcherWrapper(Pattern pattern, String input) {
+ this.matcher = pattern.matcher(input);
+ }
+
+ /**
+ * see {@link Matcher#find()}
+ */
+ public boolean find() {
+ return matcher.find();
+ }
+
+ /**
+ * see {@link Matcher#group(int)}
+ */
+ public String group(int index) {
+ return newString(matcher.group(index));
+ }
+
+ /**
+ * This method explicitly creates a new String instance from an already existing String. This is necessary to avoid
+ * huge memory leaks in our parser. If we do regular expression matching on large Strings, the returned matches are
+ * otherwise memory mapped substrings of the huge original String, therefore blocking the garbage collector from
+ * removing the huge input String.
+ * <p>
+ * Do not change this method, even if Findbugs and other tools will report a violation for that line!
+ *
+ * @param input
+ * @return
+ */
+ private static String newString(String input) {
+ if (input == null) {
+ return null;
+ }
+ return new String(input); // DON'T REMOVE THE "new String" HERE!
+ }
+
+ /**
+ * see {@link Matcher#groupCount()}
+ */
+ public int groupCount() {
+ return matcher.groupCount();
+ }
+
+ /**
+ * see {@link Matcher#group()}
+ */
+ public String group() {
+ return newString(matcher.group());
+ }
+
+ /**
+ * see {@link Matcher#start()}
+ */
+ public int start() {
+ return matcher.start();
+ }
+
+ /**
+ * see {@link Matcher#replaceAll(String)}
+ */
+ public String replaceAll(String replacement) {
+ return newString(matcher.replaceAll(replacement));
+ }
+
+ /**
+ * see {@link Matcher#matches()}
+ */
+ public boolean matches() {
+ return matcher.matches();
+ }
+
+ /**
+ * see {@link Matcher#replaceFirst(String)}
+ */
+ public String replaceFirst(String replacement) {
+ return newString(matcher.replaceFirst(replacement));
+ }
+}
diff --git a/main/src/cgeo/geocaching/utils/PeriodicHandler.java b/main/src/cgeo/geocaching/utils/PeriodicHandler.java
index 3f6c345..ac6b22a 100644
--- a/main/src/cgeo/geocaching/utils/PeriodicHandler.java
+++ b/main/src/cgeo/geocaching/utils/PeriodicHandler.java
@@ -26,7 +26,7 @@ abstract public class PeriodicHandler extends Handler {
* @param period
* The period in milliseconds.
*/
- public PeriodicHandler(final long period) {
+ protected PeriodicHandler(final long period) {
this.period = period;
}
diff --git a/main/src/cgeo/geocaching/utils/TranslationUtils.java b/main/src/cgeo/geocaching/utils/TranslationUtils.java
index a29c5a7..4d318f0 100644
--- a/main/src/cgeo/geocaching/utils/TranslationUtils.java
+++ b/main/src/cgeo/geocaching/utils/TranslationUtils.java
@@ -1,12 +1,11 @@
package cgeo.geocaching.utils;
import cgeo.geocaching.activity.AbstractActivity;
+import cgeo.geocaching.network.Network;
import android.content.Intent;
import android.net.Uri;
-import java.net.URLEncoder;
-
/**
* Utilities used for translating
*/
@@ -30,7 +29,7 @@ public final class TranslationUtils {
* @return URI ready to be parsed
*/
private static String buildTranslationURI(final String toLang, final String text) {
- String content = URLEncoder.encode(text);
+ String content = Network.encode(text);
// the app works better without the "+", the website works better with "+", therefore assume using the app if installed
if (ProcessUtils.isInstalled(TRANSLATION_APP)) {
content = content.replace("+", "%20");
diff --git a/main/src/cgeo/geocaching/utils/XmlUtils.java b/main/src/cgeo/geocaching/utils/XmlUtils.java
new file mode 100644
index 0000000..4e08f42
--- /dev/null
+++ b/main/src/cgeo/geocaching/utils/XmlUtils.java
@@ -0,0 +1,41 @@
+package cgeo.geocaching.utils;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+
+public class XmlUtils {
+
+ private XmlUtils() {
+ // Do not instantiate
+ }
+
+ /**
+ * Insert an attribute-less tag with enclosed text in a XML serializer output.
+ *
+ * @param serializer an XML serializer
+ * @param prefix an XML prefix, see {@link XmlSerializer#startTag(String, String)}
+ * @param tag an XML tag
+ * @param text some text to insert
+ * @throws IOException
+ */
+ public static void simpleText(final XmlSerializer serializer, final String prefix, final String tag, final String text) throws IOException {
+ serializer.startTag(prefix, tag);
+ serializer.text(text);
+ serializer.endTag(prefix, tag);
+ }
+
+ /**
+ * Insert pairs of attribute-less tags and enclosed texts in a XML serializer output
+ *
+ * @param serializer an XML serializer
+ * @param prefix an XML prefix, see {@link XmlSerializer#startTag(String, String)} shared by all tags
+ * @param tagAndText an XML tag, the corresponding text, another XML tag, the corresponding text, …
+ * @throws IOException
+ */
+ public static void multipleTexts(final XmlSerializer serializer, final String prefix, final String... tagAndText) throws IOException {
+ for (int i = 0; i < tagAndText.length; i += 2) {
+ simpleText(serializer, prefix, tagAndText[i], tagAndText[i+1]);
+ }
+ }
+}
diff --git a/main/src/com/viewpagerindicator/TitlePageIndicator.java b/main/src/com/viewpagerindicator/TitlePageIndicator.java
index a181fed..94ac962 100644
--- a/main/src/com/viewpagerindicator/TitlePageIndicator.java
+++ b/main/src/com/viewpagerindicator/TitlePageIndicator.java
@@ -65,7 +65,7 @@ public class TitlePageIndicator extends View implements PageIndicator {
public final int value;
- private IndicatorStyle(int value) {
+ IndicatorStyle(int value) {
this.value = value;
}
@@ -686,15 +686,13 @@ public class TitlePageIndicator extends View implements PageIndicator {
* @return The width of the view, honoring constraints from measureSpec
*/
private int measureWidth(int measureSpec) {
- int result;
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.");
}
- result = specSize;
- return result;
+ return specSize;
}
/**
diff --git a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java b/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java
index 28950b9..af4c03e 100644
--- a/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java
+++ b/main/src/gnu/android/app/appmanualclient/AppManualReaderClient.java
@@ -233,9 +233,8 @@ public class AppManualReaderClient {
// manuals this doesn't matter, as the user then can choose which
// one to use on a single or permanent basis.
//
- String logTag = "appmanualclient";
- for ( ;; ) {
- Uri uri = Uri.parse(URI_SCHEME_APPMANUAL + "://" + manualIdentifier
+ 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);
@@ -300,7 +299,8 @@ public class AppManualReaderClient {
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
}
try {
- if ( Log.isLoggable(logTag, Log.INFO) ) {
+ String logTag = "appmanualclient";
+ if ( Log.isLoggable(logTag, Log.INFO) ) {
Log.i(logTag,
"Trying to activate manual: uri=" + uri.toString());
}
diff --git a/main/src/org/openintents/intents/FileManagerIntents.java b/main/src/org/openintents/intents/FileManagerIntents.java
new file mode 100644
index 0000000..8ff10c8
--- /dev/null
+++ b/main/src/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.
+ * <p>These specifiers extend the standard Android specifiers.</p>
+ */
+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.
+ *
+ * <p>Constant Value: "org.openintents.action.PICK_FILE"</p>
+ */
+ 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.
+ *
+ * <p>Constant Value: "org.openintents.action.PICK_DIRECTORY"</p>
+ */
+ 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.
+ *
+ * <p>Constant Value: "org.openintents.action.MULTI_SELECT"</p>
+ */
+ 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.
+ *
+ * <p>This is shown in the title bar of the file manager.</p>
+ *
+ * <p>Constant Value: "org.openintents.extra.TITLE"</p>
+ */
+ public static final String EXTRA_TITLE = "org.openintents.extra.TITLE";
+
+ /**
+ * The text on the button to display.
+ *
+ * <p>Depending on the use, it makes sense to set this to "Open" or "Save".</p>
+ *
+ * <p>Constant Value: "org.openintents.extra.BUTTON_TEXT"</p>
+ */
+ public static final String EXTRA_BUTTON_TEXT = "org.openintents.extra.BUTTON_TEXT";
+
+ /**
+ * Flag indicating to show only writeable files and folders.
+ *
+ * <p>Constant Value: "org.openintents.extra.WRITEABLE_ONLY"</p>
+ */
+ 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.
+ *
+ * <p>Constant Value: "org.openintents.extra.SEARCH_INIT_PATH"</p>
+ */
+ public static final String EXTRA_SEARCH_INIT_PATH = "org.openintents.extra.SEARCH_INIT_PATH";
+
+ /**
+ * The search query as sent to SearchService.
+ *
+ * <p>Constant Value: "org.openintents.extra.SEARCH_QUERY"</p>
+ */
+ public static final String EXTRA_SEARCH_QUERY = "org.openintents.extra.SEARCH_QUERY";
+
+ /**
+ * <p>Constant Value: "org.openintents.extra.DIR_PATH"</p>
+ */
+ public static final String EXTRA_DIR_PATH = "org.openintents.extra.DIR_PATH";
+
+ /**
+ * Extension by which to filter.
+ *
+ * <p>Constant Value: "org.openintents.extra.FILTER_FILETYPE"</p>
+ */
+ public static final String EXTRA_FILTER_FILETYPE = "org.openintents.extra.FILTER_FILETYPE";
+
+ /**
+ * Mimetype by which to filter.
+ *
+ * <p>Constant Value: "org.openintents.extra.FILTER_MIMETYPE"</p>
+ */
+ public static final String EXTRA_FILTER_MIMETYPE = "org.openintents.extra.FILTER_MIMETYPE";
+
+ /**
+ * Only show directories.
+ *
+ * <p>Constant Value: "org.openintents.extra.DIRECTORIES_ONLY"</p>
+ */
+ 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";
+}