diff options
Diffstat (limited to 'main/src/cgeo/geocaching/maps/google/v1')
10 files changed, 737 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleCacheOverlay.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleCacheOverlay.java new file mode 100644 index 0000000..9b18c2d --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleCacheOverlay.java @@ -0,0 +1,120 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.maps.CachesOverlay; +import cgeo.geocaching.maps.interfaces.ItemizedOverlayImpl; +import cgeo.geocaching.maps.interfaces.MapProjectionImpl; +import cgeo.geocaching.maps.interfaces.MapViewImpl; + +import com.google.android.maps.ItemizedOverlay; +import com.google.android.maps.MapView; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Point; +import android.graphics.drawable.Drawable; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +/** + * Google specific implementation of the itemized cache overlay + */ +public class GoogleCacheOverlay extends ItemizedOverlay<GoogleCacheOverlayItem> implements ItemizedOverlayImpl { + + private CachesOverlay base; + private Lock lock = new ReentrantLock(); + + public GoogleCacheOverlay(Context contextIn, Drawable markerIn) { + super(boundCenterBottom(markerIn)); + base = new CachesOverlay(this, contextIn); + } + + @Override + public CachesOverlay getBase() { + return base; + } + + @Override + protected GoogleCacheOverlayItem createItem(int i) { + if (base == null) { + return null; + } + + return (GoogleCacheOverlayItem) base.createItem(i); + } + + @Override + public int size() { + if (base == null) { + return 0; + } + + return base.size(); + } + + @Override + protected boolean onTap(int arg0) { + if (base == null) { + return false; + } + + return base.onTap(arg0); + } + + @Override + public void draw(Canvas canvas, MapView mapView, boolean shadow) { + base.draw(canvas, castMapViewImpl(mapView), shadow); + } + + private static MapViewImpl castMapViewImpl(MapView mapView) { + assert mapView instanceof MapViewImpl; + return (MapViewImpl) mapView; + } + + @Override + public void superPopulate() { + populate(); + } + + @Override + public Drawable superBoundCenterBottom(Drawable marker) { + return ItemizedOverlay.boundCenterBottom(marker); + } + + @Override + public void superSetLastFocusedItemIndex(int i) { + super.setLastFocusedIndex(i); + } + + @Override + public boolean superOnTap(int index) { + return super.onTap(index); + } + + @Override + public void superDraw(Canvas canvas, MapViewImpl mapView, boolean shadow) { + super.draw(canvas, (MapView) mapView, shadow); + } + + @Override + public void superDrawOverlayBitmap(Canvas canvas, Point drawPosition, + MapProjectionImpl projection, byte drawZoomLevel) { + // Nothing to do here... + } + + @Override + public void lock() { + lock.lock(); + } + + @Override + public void unlock() { + lock.unlock(); + } + + @Override + public MapViewImpl getMapViewImpl() { + throw new UnsupportedOperationException(); + } + +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleCacheOverlayItem.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleCacheOverlayItem.java new file mode 100644 index 0000000..463aae9 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleCacheOverlayItem.java @@ -0,0 +1,30 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.IWaypoint; +import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; + +import com.google.android.maps.GeoPoint; +import com.google.android.maps.OverlayItem; + +public class GoogleCacheOverlayItem extends OverlayItem implements CachesOverlayItemImpl { + final private IWaypoint coord; + final private boolean applyDistanceRule; + + public GoogleCacheOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) { + super(new GeoPoint(coordinate.getCoords().getLatitudeE6(), coordinate.getCoords().getLongitudeE6()), coordinate.getName(), ""); + + this.coord = coordinate; + this.applyDistanceRule = applyDistanceRule; + } + + @Override + public IWaypoint getCoord() { + return coord; + } + + @Override + public boolean applyDistanceRule() { + return applyDistanceRule; + } + +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleGeoPoint.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleGeoPoint.java new file mode 100644 index 0000000..2f540ad --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleGeoPoint.java @@ -0,0 +1,19 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.maps.interfaces.GeoPointImpl; + +import com.google.android.maps.GeoPoint; + +public class GoogleGeoPoint extends GeoPoint implements GeoPointImpl { + + public GoogleGeoPoint(int latitudeE6, int longitudeE6) { + super(latitudeE6, longitudeE6); + } + + @Override + public Geopoint getCoords() { + return new Geopoint(getLatitudeE6() / 1e6, getLongitudeE6() / 1e6); + } + +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapActivity.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapActivity.java new file mode 100644 index 0000000..374e7b0 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapActivity.java @@ -0,0 +1,129 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.activity.ActivityMixin; +import cgeo.geocaching.activity.FilteredActivity; +import cgeo.geocaching.maps.AbstractMap; +import cgeo.geocaching.maps.CGeoMap; +import cgeo.geocaching.maps.interfaces.MapActivityImpl; + +import com.google.android.maps.MapActivity; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +public class GoogleMapActivity extends MapActivity implements MapActivityImpl, FilteredActivity { + + private AbstractMap mapBase; + + public GoogleMapActivity() { + mapBase = new CGeoMap(this); + } + + @Override + protected boolean isRouteDisplayed() { + return false; + } + + @Override + public Activity getActivity() { + return this; + } + + @Override + protected void onCreate(Bundle icicle) { + mapBase.onCreate(icicle); + } + + @Override + protected void onSaveInstanceState(final Bundle outState) { + mapBase.onSaveInstanceState(outState); + } + + @Override + protected void onDestroy() { + mapBase.onDestroy(); + } + + @Override + protected void onPause() { + mapBase.onPause(); + } + + @Override + protected void onResume() { + mapBase.onResume(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + return mapBase.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + return mapBase.onOptionsItemSelected(item); + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + return mapBase.onPrepareOptionsMenu(menu); + } + + @Override + protected void onStop() { + mapBase.onStop(); + } + + @Override + public void superOnCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public boolean superOnCreateOptionsMenu(Menu menu) { + return super.onCreateOptionsMenu(menu); + } + + @Override + public void superOnDestroy() { + super.onDestroy(); + } + + @Override + public boolean superOnOptionsItemSelected(MenuItem item) { + return super.onOptionsItemSelected(item); + } + + @Override + public void navigateUp(View view) { + ActivityMixin.navigateUp(this); + } + + @Override + public void superOnResume() { + super.onResume(); + } + + @Override + public void superOnStop() { + super.onStop(); + } + + @Override + public void superOnPause() { + super.onPause(); + } + + @Override + public boolean superOnPrepareOptionsMenu(Menu menu) { + return super.onPrepareOptionsMenu(menu); + } + + @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/v1/GoogleMapController.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapController.java new file mode 100644 index 0000000..ea95676 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapController.java @@ -0,0 +1,42 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.maps.interfaces.GeoPointImpl; +import cgeo.geocaching.maps.interfaces.MapControllerImpl; + +import com.google.android.maps.GeoPoint; +import com.google.android.maps.MapController; + +public class GoogleMapController implements MapControllerImpl { + + private MapController mapController; + + public GoogleMapController(MapController mapControllerIn) { + mapController = mapControllerIn; + } + + @Override + public void animateTo(GeoPointImpl geoPoint) { + mapController.animateTo(castToGeoPointImpl(geoPoint)); + } + + private static GeoPoint castToGeoPointImpl(GeoPointImpl geoPoint) { + assert geoPoint instanceof GeoPoint; + return (GeoPoint) geoPoint; + } + + @Override + public void setCenter(GeoPointImpl geoPoint) { + mapController.setCenter(castToGeoPointImpl(geoPoint)); + } + + @Override + public void setZoom(int mapzoom) { + mapController.setZoom(mapzoom); + } + + @Override + public void zoomToSpan(int latSpanE6, int lonSpanE6) { + mapController.zoomToSpan(latSpanE6, lonSpanE6); + } + +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapItemFactory.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapItemFactory.java new file mode 100644 index 0000000..d7e9380 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapItemFactory.java @@ -0,0 +1,20 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.IWaypoint; +import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.maps.interfaces.CachesOverlayItemImpl; +import cgeo.geocaching.maps.interfaces.GeoPointImpl; +import cgeo.geocaching.maps.interfaces.MapItemFactory; + +public class GoogleMapItemFactory implements MapItemFactory { + + @Override + public GeoPointImpl getGeoPointBase(final Geopoint coords) { + return new GoogleGeoPoint(coords.getLatitudeE6(), coords.getLongitudeE6()); + } + + @Override + public CachesOverlayItemImpl getCachesOverlayItem(final IWaypoint coordinate, boolean applyDistanceRule) { + return new GoogleCacheOverlayItem(coordinate, applyDistanceRule); + } +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapProjection.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapProjection.java new file mode 100644 index 0000000..901a369 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapProjection.java @@ -0,0 +1,29 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.maps.interfaces.GeoPointImpl; +import cgeo.geocaching.maps.interfaces.MapProjectionImpl; + +import com.google.android.maps.GeoPoint; +import com.google.android.maps.Projection; + +import android.graphics.Point; + +public class GoogleMapProjection implements MapProjectionImpl { + + private Projection projection; + + public GoogleMapProjection(Projection projectionIn) { + projection = projectionIn; + } + + @Override + public void toPixels(GeoPointImpl leftGeo, Point left) { + projection.toPixels((GeoPoint) leftGeo, left); + } + + @Override + public Object getImpl() { + return projection; + } + +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapProvider.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapProvider.java new file mode 100644 index 0000000..884e076 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapProvider.java @@ -0,0 +1,92 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.CgeoApplication; +import cgeo.geocaching.R; +import cgeo.geocaching.maps.AbstractMapProvider; +import cgeo.geocaching.maps.AbstractMapSource; +import cgeo.geocaching.maps.interfaces.MapItemFactory; +import cgeo.geocaching.maps.interfaces.MapProvider; +import cgeo.geocaching.maps.interfaces.MapSource; + +import com.google.android.maps.MapActivity; + +import android.content.res.Resources; + +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 final MapItemFactory mapItemFactory; + + private GoogleMapProvider() { + final Resources resources = CgeoApplication.getInstance().getResources(); + + registerMapSource(new GoogleMapSource(this, resources.getString(R.string.map_source_google_map))); + registerMapSource(new GoogleSatelliteSource(this, resources.getString(R.string.map_source_google_satellite))); + + mapItemFactory = new GoogleMapItemFactory(); + } + + private static class Holder { + private static final GoogleMapProvider INSTANCE = new GoogleMapProvider(); + } + + public static GoogleMapProvider getInstance() { + return Holder.INSTANCE; + } + + public static boolean isSatelliteSource(final MapSource mapSource) { + return mapSource instanceof GoogleSatelliteSource; + } + + @Override + public Class<? extends MapActivity> getMapClass() { + return GoogleMapActivity.class; + } + + @Override + public int getMapViewId() { + return R.id.map; + } + + @Override + public int getMapLayoutId() { + return R.layout.map_google; + } + + @Override + public MapItemFactory getMapItemFactory() { + return mapItemFactory; + } + + @Override + public boolean isSameActivity(final MapSource source1, final MapSource source2) { + return true; + } + + private static abstract class AbstractGoogleMapSource extends AbstractMapSource { + + protected AbstractGoogleMapSource(final String id, final MapProvider mapProvider, final String name) { + super(id, mapProvider, name); + } + + } + + private static final class GoogleMapSource extends AbstractGoogleMapSource { + + public GoogleMapSource(final MapProvider mapProvider, final String name) { + super(GOOGLE_MAP_ID, mapProvider, name); + } + + } + + private static final class GoogleSatelliteSource extends AbstractGoogleMapSource { + + public GoogleSatelliteSource(MapProvider mapProvider, String name) { + super(GOOGLE_SATELLITE_ID, mapProvider, name); + } + + } + +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java new file mode 100644 index 0000000..c611790 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleMapView.java @@ -0,0 +1,202 @@ +package cgeo.geocaching.maps.google.v1; + +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; + +import cgeo.geocaching.geopoint.Viewport; +import cgeo.geocaching.maps.CachesOverlay; +import cgeo.geocaching.maps.PositionAndScaleOverlay; +import cgeo.geocaching.maps.interfaces.GeneralOverlay; +import cgeo.geocaching.maps.interfaces.GeoPointImpl; +import cgeo.geocaching.maps.interfaces.MapControllerImpl; +import cgeo.geocaching.maps.interfaces.MapProjectionImpl; +import cgeo.geocaching.maps.interfaces.MapViewImpl; +import cgeo.geocaching.maps.interfaces.OnMapDragListener; +import cgeo.geocaching.settings.Settings; +import cgeo.geocaching.utils.Log; + +import com.google.android.maps.GeoPoint; +import com.google.android.maps.MapView; + +import org.apache.commons.lang3.reflect.MethodUtils; +import org.eclipse.jdt.annotation.NonNull; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.Gravity; +import android.view.MotionEvent; +import android.widget.FrameLayout; +import android.widget.ZoomButtonsController; + +public class GoogleMapView extends MapView implements MapViewImpl { + private GestureDetector gestureDetector; + private OnMapDragListener onDragListener; + private final GoogleMapController mapController = new GoogleMapController(getController()); + + public GoogleMapView(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(context); + } + + public GoogleMapView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initialize(context); + } + + public GoogleMapView(Context context, String apiKey) { + super(context, apiKey); + initialize(context); + } + + private void initialize(Context context) { + if (isInEditMode()) { + return; + } + gestureDetector = new GestureDetector(context, new GestureListener()); + } + + @Override + public void draw(final Canvas canvas) { + try { + if (getMapZoomLevel() > 22) { // to avoid too close zoom level (mostly on Samsung Galaxy S series) + getController().setZoom(22); + } + + super.draw(canvas); + } catch (Exception e) { + Log.e("GoogleMapView.draw", e); + } + } + + @Override + public void displayZoomControls(boolean takeFocus) { + try { + // Push zoom controls to the right + FrameLayout.LayoutParams zoomParams = new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); + zoomParams.gravity = Gravity.RIGHT; + // The call to retrieve the zoom buttons controller is undocumented and works so far on all devices + // supported by Google Play, but fails at least on one Jolla. + final ZoomButtonsController controller = (ZoomButtonsController) MethodUtils.invokeMethod(this, "getZoomButtonsController"); + controller.getZoomControls().setLayoutParams(zoomParams); + + super.displayZoomControls(takeFocus); + } catch (NoSuchMethodException e) { + Log.w("GoogleMapView.displayZoomControls: unable to explicitly place the zoom buttons"); + } catch (Exception e) { + Log.e("GoogleMapView.displayZoomControls", e); + } + } + + @Override + public MapControllerImpl getMapController() { + return mapController; + } + + @Override + @NonNull + public GeoPointImpl getMapViewCenter() { + GeoPoint point = getMapCenter(); + return new GoogleGeoPoint(point.getLatitudeE6(), point.getLongitudeE6()); + } + + @Override + public Viewport getViewport() { + return new Viewport(getMapViewCenter(), getLatitudeSpan() / 1e6, getLongitudeSpan() / 1e6); + } + + @Override + public void clearOverlays() { + getOverlays().clear(); + } + + @Override + public MapProjectionImpl getMapProjection() { + return new GoogleMapProjection(getProjection()); + } + + @Override + public CachesOverlay createAddMapOverlay(Context context, Drawable drawable) { + + GoogleCacheOverlay ovl = new GoogleCacheOverlay(context, drawable); + getOverlays().add(ovl); + return ovl.getBase(); + } + + @Override + public PositionAndScaleOverlay createAddPositionAndScaleOverlay() { + + GoogleOverlay ovl = new GoogleOverlay(); + getOverlays().add(ovl); + return (PositionAndScaleOverlay) ovl.getBase(); + } + + @Override + public int getMapZoomLevel() { + return getZoomLevel(); + } + + @Override + public void setMapSource() { + setSatellite(GoogleMapProvider.isSatelliteSource(Settings.getMapSource())); + } + + @Override + public void repaintRequired(GeneralOverlay overlay) { + invalidate(); + } + + @Override + public void setOnDragListener(OnMapDragListener onDragListener) { + this.onDragListener = onDragListener; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + try { + gestureDetector.onTouchEvent(ev); + return super.onTouchEvent(ev); + } catch (Exception e) { + Log.e("GoogleMapView.onTouchEvent", e); + } + return false; + } + + private class GestureListener extends SimpleOnGestureListener { + @Override + public boolean onDoubleTap(MotionEvent e) { + getController().zoomInFixing((int) e.getX(), (int) e.getY()); + if (onDragListener != null) { + onDragListener.onDrag(); + } + return true; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + if (onDragListener != null) { + onDragListener.onDrag(); + } + return super.onScroll(e1, e2, distanceX, distanceY); + } + } + + @Override + public boolean needsInvertedColors() { + return false; + } + + @Override + public boolean hasMapThemes() { + // Not supported + return false; + } + + @Override + public void setMapTheme() { + // Not supported + } +} diff --git a/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java b/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java new file mode 100644 index 0000000..40a5539 --- /dev/null +++ b/main/src/cgeo/geocaching/maps/google/v1/GoogleOverlay.java @@ -0,0 +1,54 @@ +package cgeo.geocaching.maps.google.v1; + +import cgeo.geocaching.maps.PositionAndScaleOverlay; +import cgeo.geocaching.maps.interfaces.GeneralOverlay; +import cgeo.geocaching.maps.interfaces.MapViewImpl; +import cgeo.geocaching.maps.interfaces.OverlayImpl; + +import com.google.android.maps.MapView; +import com.google.android.maps.Overlay; + +import android.graphics.Canvas; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class GoogleOverlay extends Overlay implements OverlayImpl { + + private PositionAndScaleOverlay overlayBase = null; + private Lock lock = new ReentrantLock(); + + public GoogleOverlay() { + overlayBase = new PositionAndScaleOverlay(this); + } + + @Override + public void draw(Canvas canvas, MapView mapView, boolean shadow) { + super.draw(canvas, mapView, shadow); + + if (overlayBase != null) { + assert mapView instanceof MapViewImpl; + overlayBase.draw(canvas, (MapViewImpl) mapView, shadow); + } + } + + public GeneralOverlay getBase() { + return overlayBase; + } + + @Override + public void lock() { + lock.lock(); + } + + @Override + public void unlock() { + lock.unlock(); + } + + @Override + public MapViewImpl getMapViewImpl() { + throw new UnsupportedOperationException(); + } + +} |
