/** * Copyright 2009 Joe LaPenna */ 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.Stats; import com.joelapenna.foursquare.types.Venue; import com.joelapenna.foursquare.util.VenueUtils; import com.joelapenna.foursquared.maps.CrashFixMyLocationOverlay; import com.joelapenna.foursquared.maps.VenueItemizedOverlay; import com.joelapenna.foursquared.widget.MapCalloutView; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import java.util.Observable; import java.util.Observer; /** * @author Joe LaPenna (joe@joelapenna.com) */ public class SearchVenuesMapActivity extends MapActivity { public static final String TAG = "SearchVenuesMapActivity"; public static final boolean DEBUG = FoursquaredSettings.DEBUG; private String mTappedVenueId; private Observer mSearchResultsObserver; private MapCalloutView mCallout; private MapView mMapView; private MapController mMapController; private VenueItemizedOverlay mVenueItemizedOverlay; private MyLocationOverlay mMyLocationOverlay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.search_map_activity); initMap(); 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(SearchVenuesMapActivity.this, VenueActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.putExtra(VenueActivity.INTENT_EXTRA_VENUE_ID, mTappedVenueId); startActivity(intent); } }); mSearchResultsObserver = new Observer() { @Override public void update(Observable observable, Object data) { if (DEBUG) Log.d(TAG, "Observed search results change."); clearMap(); loadSearchResults(SearchVenuesActivity.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 clearMap(); loadSearchResults(SearchVenuesActivity.searchResultsObservable.getSearchResults()); recenterMap(); SearchVenuesActivity.searchResultsObservable.addObserver(mSearchResultsObserver); } @Override public void onPause() { super.onPause(); if (DEBUG) Log.d(TAG, "onPause()"); mMyLocationOverlay.disableMyLocation(); mMyLocationOverlay.disableCompass(); SearchVenuesActivity.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); mMyLocationOverlay.runOnFirstFix(new Runnable() { public void run() { if (DEBUG) Log.d(TAG, "runOnFirstFix()"); mMapView.getController().animateTo(mMyLocationOverlay.getMyLocation()); mMapView.getController().setZoom(16); } }); } private void loadSearchResults(Group<Group<Venue>> searchResults) { if (searchResults == null) { if (DEBUG) Log.d(TAG, "no search results. Not loading."); return; } if (DEBUG) Log.d(TAG, "Loading search results"); // Put our location on the map. mMapView.getOverlays().add(mMyLocationOverlay); Group<Venue> mappableVenues = new Group<Venue>(); mappableVenues.setType("Mappable Venues"); // For each group of venues. final int groupCount = searchResults.size(); for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) { Group<Venue> group = searchResults.get(groupIndex); // For each venue group final int venueCount = group.size(); for (int venueIndex = 0; venueIndex < venueCount; venueIndex++) { Venue venue = group.get(venueIndex); if (VenueUtils.hasValidLocation(venue)) { mappableVenues.add(venue); } } } // Construct the venues overlay and attach it if we have a mappable set of venues. if (mappableVenues.size() > 0) { mVenueItemizedOverlay = new VenueItemizedOverlayWithButton( // this.getResources().getDrawable(R.drawable.map_marker_blue), // this.getResources().getDrawable(R.drawable.map_marker_blue_muted)); mVenueItemizedOverlay.setGroup(mappableVenues); mMapView.getOverlays().add(mVenueItemizedOverlay); } } private void clearMap() { if (DEBUG) Log.d(TAG, "clearMap()"); mMapView.getOverlays().clear(); mMapView.postInvalidate(); } private void recenterMap() { if (DEBUG) Log.d(TAG, "Recentering map."); GeoPoint center = mMyLocationOverlay.getMyLocation(); // if we have venues in a search result, focus on those. if (mVenueItemizedOverlay != null && mVenueItemizedOverlay.size() > 0) { if (DEBUG) Log.d(TAG, "Centering on venues: " + String.valueOf(mVenueItemizedOverlay.getLatSpanE6()) + " " + String.valueOf(mVenueItemizedOverlay.getLonSpanE6())); mMapController.setCenter(mVenueItemizedOverlay.getCenter()); mMapController.zoomToSpan(mVenueItemizedOverlay.getLatSpanE6(), mVenueItemizedOverlay .getLonSpanE6()); } else if (center != null && SearchVenuesActivity.searchResultsObservable.getQuery() == SearchVenuesActivity.QUERY_NEARBY) { if (DEBUG) Log.d(TAG, "recenterMap via MyLocation as we are doing a nearby search"); mMapController.animateTo(center); mMapController.zoomToSpan(center.getLatitudeE6(), center.getLongitudeE6()); } else if (center != null) { if (DEBUG) Log.d(TAG, "Fallback, recenterMap via MyLocation overlay"); mMapController.animateTo(center); mMapController.setZoom(16); return; } } private class VenueItemizedOverlayWithButton extends VenueItemizedOverlay { public static final String TAG = "VenueItemizedOverlayWithButton"; public static final boolean DEBUG = FoursquaredSettings.DEBUG; private Drawable mBeenThereMarker; public VenueItemizedOverlayWithButton(Drawable defaultMarker, Drawable beenThereMarker) { super(defaultMarker); mBeenThereMarker = boundCenterBottom(beenThereMarker); } @Override public OverlayItem createItem(int i) { VenueOverlayItem item = (VenueOverlayItem)super.createItem(i); Stats stats = item.getVenue().getStats(); if (stats != null && stats.getBeenhere() != null && stats.getBeenhere().me()) { if (DEBUG) Log.d(TAG, "using the beenThereMarker for: " + item.getVenue()); item.setMarker(mBeenThereMarker); } return item; } @Override public boolean onTap(GeoPoint p, MapView mapView) { if (DEBUG) Log.d(TAG, "onTap: " + this + " " + p + " " + mapView); mCallout.setVisibility(View.GONE); return super.onTap(p, mapView); } @Override protected boolean onTap(int i) { if (DEBUG) Log.d(TAG, "onTap: " + this + " " + i); VenueOverlayItem item = (VenueOverlayItem)getItem(i); mTappedVenueId = item.getVenue().getId(); mCallout.setTitle(item.getVenue().getName()); mCallout.setMessage(item.getVenue().getAddress()); mCallout.setVisibility(View.VISIBLE); return true; } } }