package org.ohmage.fragments; import com.google.android.maps.GeoPoint; import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.Overlay; import com.google.android.maps.OverlayItem; import org.ohmage.ConfigHelper; import org.ohmage.R; import org.ohmage.db.DbContract.Responses; import org.ohmage.db.DbContract.Surveys; import org.ohmage.feedback.visualization.MapOverlayItem; import org.ohmage.feedback.visualization.MapViewItemizedOverlay; import org.ohmage.service.SurveyGeotagService; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import java.util.List; public class ResponseMapFragment extends FilterableMapFragment { private static final String RESPONSE_ID = "response_id"; private Button mMapPinNext; private Button mMapPinPrevious; private TextView mMapPinIdxButton; private int mPinIndex; private MapViewItemizedOverlay mItemizedOverlay; private Long mResponseId; /** * Create an instance of {@link ResponseMapFragment} which creates a point * for a single response * @param the response id */ public static ResponseMapFragment newInstance(long responseId) { ResponseMapFragment f = new ResponseMapFragment(); Bundle args = new Bundle(); args.putLong(RESPONSE_ID, responseId); f.setArguments(args); return f; } @Override public void onCreate(Bundle args) { super.onCreate(args); if(getArguments() != null && getArguments().containsKey(RESPONSE_ID)) mResponseId = getArguments().getLong(RESPONSE_ID); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); inflater.inflate(R.layout.response_map_navigator_layout, (ViewGroup) view); mMapPinNext = (Button) view.findViewById(R.id.map_pin_next); mMapPinPrevious = (Button) view.findViewById(R.id.map_pin_previous); mMapPinIdxButton = (TextView) view.findViewById(R.id.map_pin_index); mMapPinNext.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int overlayListSize = mItemizedOverlay.size(); if(overlayListSize > 0){ if(mPinIndex < (overlayListSize-1)){ mPinIndex = (mPinIndex + 1) % overlayListSize; mItemizedOverlay.onTap(mPinIndex); setNavigatorButtons(); } } } }); mMapPinPrevious.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int overlayListSize = mItemizedOverlay.size(); if(overlayListSize > 0){ if(mPinIndex > 0){ mPinIndex = (mPinIndex - 1) % overlayListSize; mItemizedOverlay.onTap(mPinIndex); setNavigatorButtons(); } } } }); return view; } @Override public void onResume() { super.onResume(); // When the map comes back it could have data from another map on it, so we need to restart our loader getLoaderManager().restartLoader(0, null, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { if(mResponseId == null) { return new ResponseLoader(this, ResponseMapQuery.PROJECTION, Responses.RESPONSE_LOCATION_STATUS + "='" + SurveyGeotagService.LOCATION_VALID + "'").onCreateLoader(id, args); } else return new CursorLoader(getActivity(), Responses.buildResponseUri(mResponseId), ResponseMapQuery.PROJECTION, null, null, null); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { //Add overlays to the map List<Overlay> mapOverlays = getMapView().getOverlays(); Drawable drawable = this.getResources().getDrawable(R.drawable.bg_map_marker); if(mItemizedOverlay != null) mItemizedOverlay.clearBalloon(); mItemizedOverlay = new MapViewItemizedOverlay(drawable, getMapView()); mItemizedOverlay.setOnFocusChangeListener(new ItemizedOverlay.OnFocusChangeListener() { @Override public void onFocusChanged(ItemizedOverlay overlay, OverlayItem newFocus) { mPinIndex = overlay.getLastFocusedIndex(); if(newFocus == null) { mPinIndex = -1; mItemizedOverlay.hideBalloon(); } setNavigatorButtons(); } }); mItemizedOverlay.setBalloonBottomOffset(40); for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){ Double lat = cursor.getDouble(ResponseMapQuery.LOCATION_LATITUDE); Double lon = cursor.getDouble(ResponseMapQuery.LOCATION_LONGITUDE); GeoPoint point = new GeoPoint((int)(lat.doubleValue()*1e6), (int)(lon.doubleValue()*1e6)); String title = cursor.getString(ResponseMapQuery.TITLE); StringBuilder text = new StringBuilder(); // Only show the campaign urn if we aren't in single campaign mode if(!ConfigHelper.isSingleCampaignMode()) text.append(cursor.getString(ResponseMapQuery.CAMPAIGN_URN) + "\n"); text.append(cursor.getString(ResponseMapQuery.DATE)); String id = cursor.getString(ResponseMapQuery.ID); MapOverlayItem overlayItem = new MapOverlayItem(point, title, text.toString(), (mResponseId != null) ? null : id); mItemizedOverlay.addOverlay(overlayItem); } mapOverlays.clear(); getMapView().invalidate(); if(mItemizedOverlay.size() > 0){ mapOverlays.add(mItemizedOverlay); int maxLatitude = mItemizedOverlay.getMaxLatitude(); int minLatitude = mItemizedOverlay.getMinLatitude(); int maxLongitude = mItemizedOverlay.getMaxLongitude(); int minLongitude = mItemizedOverlay.getMinLongitude(); getMapControl().animateTo(new GeoPoint((maxLatitude+minLatitude)/2, (maxLongitude+minLongitude)/2)); getMapControl().zoomToSpan(Math.abs(maxLatitude-minLatitude), Math.abs(maxLongitude-minLongitude)); } //Set Map Pin Navigators. if(mResponseId == null) { mMapPinIdxButton.setVisibility(View.VISIBLE); mMapPinNext.setVisibility(View.VISIBLE); mMapPinPrevious.setVisibility(View.VISIBLE); } else { mMapPinIdxButton.setVisibility(View.GONE); mMapPinNext.setVisibility(View.GONE); mMapPinPrevious.setVisibility(View.GONE); } mPinIndex = -1; mMapPinIdxButton.setText(""); } @Override public void onLoaderReset(Loader<Cursor> loader) { // } protected static class ResponseMapQuery { public static final String[] PROJECTION = new String[] { Responses._ID, Responses.RESPONSE_LOCATION_STATUS, Responses.RESPONSE_LOCATION_LATITUDE, Responses.RESPONSE_LOCATION_LONGITUDE, Surveys.SURVEY_TITLE, Responses.CAMPAIGN_URN, Responses.RESPONSE_DATE }; public static final int ID = 0; public static final int LOCATION_STATUS = 1; public static final int LOCATION_LATITUDE = 2; public static final int LOCATION_LONGITUDE = 3; public static final int TITLE = 4; public static final int CAMPAIGN_URN = 5; public static final int DATE = 6; } public void setNavigatorButtons() { if(mPinIndex == -1) mMapPinIdxButton.setText(null); else mMapPinIdxButton.setText(""+(mPinIndex+1)+"/"+mItemizedOverlay.size()); } }