/**
* Copyright 2010 Mark Wyszomierski
*/
package com.joelapenna.foursquared;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;
import com.joelapenna.foursquare.types.Group;
import com.joelapenna.foursquare.types.Venue;
import com.joelapenna.foursquared.maps.CrashFixMyLocationOverlay;
import com.joelapenna.foursquared.maps.VenueItemizedOverlayWithIcons;
import com.joelapenna.foursquared.maps.VenueItemizedOverlayWithIcons.VenueItemizedOverlayTapListener;
import com.joelapenna.foursquared.util.GeoUtils;
import com.joelapenna.foursquared.widget.MapCalloutView;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
/**
* @date June 30, 2010
* @author Mark Wyszomierski (markww@gmail.com)
*/
public class NearbyVenuesMapActivity extends MapActivity {
public static final String TAG = "PlacesMapActivity";
public static final boolean DEBUG = FoursquaredSettings.DEBUG;
private String mTappedVenueId;
private Observer mSearchResultsObserver;
private MapCalloutView mCallout;
private MapView mMapView;
private MapController mMapController;
private ArrayList<VenueItemizedOverlayWithIcons> mVenueGroupOverlays =
new ArrayList<VenueItemizedOverlayWithIcons>();
private MyLocationOverlay mMyLocationOverlay;
private boolean mConstructedPinsOnce;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_map_activity);
mConstructedPinsOnce = false;
mCallout = (MapCalloutView) findViewById(R.id.map_callout);
mCallout.setVisibility(View.GONE);
mCallout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(NearbyVenuesMapActivity.this, VenueActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(Foursquared.EXTRA_VENUE_ID, mTappedVenueId);
startActivity(intent);
}
});
initMap();
mSearchResultsObserver = new Observer() {
@Override
public void update(Observable observable, Object data) {
if (DEBUG) Log.d(TAG, "Observed search results change.");
clearMap();
loadSearchResults(NearbyVenuesActivity.searchResultsObservable.getSearchResults());
recenterMap();
}
};
}
@Override
public void onResume() {
super.onResume();
if (DEBUG) Log.d(TAG, "onResume()");
mMyLocationOverlay.enableMyLocation();
//mMyLocationOverlay.enableCompass(); // Disabled due to a sdk 1.5
// emulator bug
// If this is the first time we're showing the activity, try generating the overlay
// immediately. If the results are already loaded, the observer would not be called.
if (!mConstructedPinsOnce) {
clearMap();
loadSearchResults(NearbyVenuesActivity.searchResultsObservable.getSearchResults());
recenterMap();
mConstructedPinsOnce = true;
}
//NearbyVenuesActivity.
NearbyVenuesActivity.searchResultsObservable.addObserver(mSearchResultsObserver);
}
@Override
public void onPause() {
super.onPause();
if (DEBUG) Log.d(TAG, "onPause()");
mMyLocationOverlay.disableMyLocation();
mMyLocationOverlay.disableCompass();
NearbyVenuesActivity.searchResultsObservable.deleteObserver(mSearchResultsObserver);
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
private void initMap() {
mMapView = (MapView) findViewById(R.id.mapView);
mMapView.setBuiltInZoomControls(true);
mMapController = mMapView.getController();
mMyLocationOverlay = new CrashFixMyLocationOverlay(this, mMapView);
mMapView.getOverlays().add(mMyLocationOverlay);
}
private void loadSearchResults(Group<Group<Venue>> venues) {
if (venues == null) {
if (DEBUG) Log.d(TAG, "no search results. Not loading.");
return;
}
if (DEBUG) Log.d(TAG, "Loading search results");
// One CheckinItemizedOverlay per group!
VenueItemizedOverlayWithIcons mappableVenuesOverlay = createMappableVenuesOverlay(venues);
if (mappableVenuesOverlay != null) {
mVenueGroupOverlays.add(mappableVenuesOverlay);
}
// Only add the list of checkin group overlays if it contains any
// overlays.
if (mVenueGroupOverlays.size() > 0) {
mMapView.getOverlays().addAll(mVenueGroupOverlays);
} else {
Toast.makeText(this, getResources().getString(
R.string.friendsmapactivity_no_checkins), Toast.LENGTH_LONG).show();
}
}
private void clearMap() {
if (DEBUG) Log.d(TAG, "clearMap()");
mVenueGroupOverlays.clear();
mMapView.getOverlays().clear();
mMapView.getOverlays().add(mMyLocationOverlay);
mMapView.postInvalidate();
}
/**
* We can do something more fun here like create an overlay per category, so the user
* can hide parks and show only bars, for example.
*/
private VenueItemizedOverlayWithIcons createMappableVenuesOverlay(Group<Group<Venue>> group) {
Group<Venue> mappableVenues = new Group<Venue>();
for (Group<Venue> it : group) {
for (Venue jt : it) {
mappableVenues.add(jt);
}
}
if (mappableVenues.size() > 0) {
VenueItemizedOverlayWithIcons overlay = new VenueItemizedOverlayWithIcons(
this,
((Foursquared) getApplication()).getRemoteResourceManager(),
getResources().getDrawable(R.drawable.pin_checkin_multiple),
mVenueOverlayTapListener);
overlay.setGroup(mappableVenues);
return overlay;
} else {
return null;
}
}
private void recenterMap() {
// Previously we'd try to zoom to span, but this gives us odd results a lot of times,
// so falling back to zoom at a fixed level.
GeoPoint center = mMyLocationOverlay.getMyLocation();
if (center != null) {
if (DEBUG) Log.d(TAG, "Using MyLocaionOverlay as center point for recenterMap().");
mMapController.animateTo(center);
mMapController.setZoom(16);
} else {
// Location overlay wasn't ready yet, try using last known geolocation from manager.
Location bestLocation = GeoUtils.getBestLastGeolocation(this);
if (bestLocation != null) {
if (DEBUG) Log.d(TAG, "Using last known location as center point for recenterMap().");
mMapController.animateTo(GeoUtils.locationToGeoPoint(bestLocation));
mMapController.setZoom(16);
} else {
// We have no location information at all, so we'll just show the map at a high
// zoom level and the user can zoom in as they wish.
if (DEBUG) Log.d(TAG, "No location info available for recenterMap().");
mMapController.setZoom(8);
}
}
}
/** Handle taps on one of the pins. */
private VenueItemizedOverlayTapListener mVenueOverlayTapListener =
new VenueItemizedOverlayTapListener() {
@Override
public void onTap(OverlayItem itemSelected, OverlayItem itemLastSelected, Venue venue) {
mTappedVenueId = venue.getId();
mCallout.setTitle(venue.getName());
mCallout.setMessage(venue.getAddress());
mCallout.setVisibility(View.VISIBLE);
mMapController.animateTo(GeoUtils.stringLocationToGeoPoint(
venue.getGeolat(), venue.getGeolong()));
}
@Override
public void onTap(GeoPoint p, MapView mapView) {
mCallout.setVisibility(View.GONE);
}
};
}