/** * Copyright (C) 2009 Anders Aagaard <aagaande@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.neuron.trafikanten.views.map; import java.io.File; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.AnalyticsUtils; import com.google.android.FixedMyLocationOverlay; import com.google.android.TransparentPanel; import com.google.android.maps.GeoPoint; import com.google.android.maps.MapActivity; import com.google.android.maps.MapView; import com.google.android.maps.MyLocationOverlay; import com.google.android.maps.Overlay; import com.neuron.trafikanten.R; import com.neuron.trafikanten.dataProviders.IGenericProviderHandler; import com.neuron.trafikanten.dataProviders.trafikanten.TrafikantenTrip; import com.neuron.trafikanten.dataSets.RouteData; import com.neuron.trafikanten.dataSets.StationData; import com.neuron.trafikanten.db.FavoriteDbAdapter; public class GenericMap extends MapActivity { private final static String TAG = "Trafikanten-Map"; private static final int DIALOG_LIST = Menu.FIRST; private MyLocationOverlay locationOverlay; private static GenericStationOverlay stationOverlay; private static ViewHolder viewHolder = new ViewHolder(); private FavoriteDbAdapter favoriteDbAdapter = null; private Drawable iconMapMarker = null; /* * For route loading: */ private ArrayList<RouteData> routeList; private int routeLength = 0; private TrafikantenTrip tripProvider = null; /* * Holder for currently selected station in panel */ static private StationData selectedStation; /* * Options menu items */ private final static int MYLOCATION_ID = Menu.FIRST; /* * Variables cached locally for performance */ private MapView mapView; public static void Show(Activity activity, @SuppressWarnings("rawtypes") ArrayList stationList, boolean isRoute, int what) { Intent intent = new Intent(activity, GenericMap.class); if (isRoute) { intent.putExtra(RouteData.PARCELABLE, stationList); } else { intent.putExtra(StationData.PARCELABLE, stationList); } activity.startActivityForResult(intent, what); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.map); favoriteDbAdapter = new FavoriteDbAdapter(this); iconMapMarker = getResources().getDrawable(R.drawable.icon_mapmarker); AnalyticsUtils.getInstance(this).trackPageView("/map"); /* * Setup map view */ String apiKey = "0C4n0QlD7VKWny63h-bygLe8DF4bhWdnxCYYhNA"; try { if (new File("/sdcard/trafikanten.debug").exists()) { apiKey = "0C4n0QlD7VKUBXEwAaDHHuGHIpMavSe5zbT27AQ"; } } catch (Exception e) { // We don't care if this fails. } mapView = new MapView(this, apiKey); mapView.setBuiltInZoomControls(true); mapView.setClickable(true); final RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.view); final View panel = LayoutInflater.from(this).inflate(R.layout.map_overlay, null); relativeLayout.addView(mapView); relativeLayout.addView(panel); viewHolder.list = (ImageButton) findViewById(R.id.list); viewHolder.infoPanel = (TransparentPanel) findViewById(R.id.infoPanel); viewHolder.infoPanel.setVisibility(View.GONE); viewHolder.name = (TextView) findViewById(R.id.name); viewHolder.information = (TextView) findViewById(R.id.information); viewHolder.select = (ImageButton) findViewById(R.id.select); /* * Setup onClick handler for list button */ viewHolder.list.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showDialog(DIALOG_LIST); } }); /* * Setup onClick handler for select station button */ viewHolder.select.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.putExtra(StationData.PARCELABLE, selectedStation); setResult(RESULT_OK, intent); finish(); } }); /* * Setup overlays */ final List<Overlay> overlays = mapView.getOverlays(); stationOverlay = new GenericStationOverlay(iconMapMarker); /* * Load stations */ if (savedInstanceState == null) { final Bundle bundle = getIntent().getExtras(); if (bundle.containsKey(StationData.PARCELABLE)) { /* * Load stations passed to us */ final ArrayList<StationData> stationList = bundle.getParcelableArrayList(StationData.PARCELABLE); favoriteDbAdapter.refreshFavorites(stationList); stationOverlay.add(this, stationList); overlays.add(stationOverlay); } else if (bundle.containsKey(RouteData.PARCELABLE)) { /* * Load stations passed to us */ routeList = bundle.getParcelableArrayList(RouteData.PARCELABLE); routeLength = routeList.size() + 1; setProgress(0); loadRouteData(); /* * Hide select station button, it does nothing in this view */ final View panelSelectStationButton = panel.findViewById(R.id.select); panelSelectStationButton.setVisibility(View.GONE); } } else { // TODO : saveInstanceState in mapview. finish(); } /* * Add MyLocationOverlay so we can see where we are. */ locationOverlay = new FixedMyLocationOverlay(this, mapView); boolean animateToGpsPosition = true; if (animateToGpsPosition) { locationOverlay.runOnFirstFix(new Runnable() { public void run() { mapView.getController().animateTo(locationOverlay.getMyLocation()); } }); } /* * Add all overlays to the overlay list */ overlays.add(locationOverlay); } /* * This takes routeList[0] and deals with it until routeList.size == 0, then it add the overlay and stops. */ private void loadRouteData() { if (routeList.size() == 0) { /* * Activate routeOverlay and add it to the map. */ RouteOverlay routeOverlay = new RouteOverlay(iconMapMarker, stationOverlay.items); final List<Overlay> overlays = mapView.getOverlays(); overlays.add(routeOverlay); overlays.add(stationOverlay); setProgress(10000); mapView.invalidate(); return; } final RouteData routeData = routeList.get(0); routeList.remove(0); setProgress((routeLength - routeList.size() + 1) * 10000 / routeLength); if (routeData.tourID == 0) { /* * We got no tour id, just add the stations directly. */ stationOverlay.add(GenericMap.this, routeData.fromStation, false, routeData.transportType); stationOverlay.add(GenericMap.this, routeData.toStation, true, routeData.transportType); loadRouteData(); return; } /* * We have a tour id, lets get our list. */ AnalyticsUtils.getInstance(this).trackPageView("/map/showTrip"); tripProvider = new TrafikantenTrip(this, routeData.tourID, routeData.fromStation.stationId, routeData.toStation.stationId, new IGenericProviderHandler<StationData>() { @Override public void onData(StationData data) { stationOverlay.add(GenericMap.this, data, true, routeData.transportType); } @Override public void onExtra(int i, Object data) {} @Override public void onPostExecute(Exception exception) { tripProvider = null; if (exception != null) { Log.w(TAG,"onException " + exception); Toast.makeText(GenericMap.this, getText(R.string.trafikantenErrorOther), Toast.LENGTH_SHORT).show(); setProgress(10000); } else { loadRouteData(); } } @Override public void onPreExecute() {} }); } static public void onStationTap(StationData station) { viewHolder.infoPanel.setVisibility(View.VISIBLE); viewHolder.name.setText(station.stopName); viewHolder.information.setText(station.extra); selectedStation = station; } @Override protected void onPrepareDialog(int id, Dialog dialog) { switch(id) { case DIALOG_LIST: /* * Dialog contains a list, force recreating it. */ removeDialog(DIALOG_LIST); dialog = onCreateDialog(DIALOG_LIST); break; } super.onPrepareDialog(id, dialog); } /* * Creating dialogs * @see android.app.Activity#onCreateDialog(int) */ @Override protected Dialog onCreateDialog(int id) { switch(id) { case DIALOG_LIST: /* * TODO : If stationOverlay items are dynamic, and can be updated while if the view is open, this will need to be converted to prepareDialog */ AlertDialog.Builder builder = new AlertDialog.Builder(GenericMap.this); builder.setTitle(getText(R.string.selectStation)); String[] items = new String[stationOverlay.size()]; for (int i = 0; i < stationOverlay.size(); i++) { items[i] = stationOverlay.getItem(i).station.stopName; } builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final StationOverlayItem stationItem = stationOverlay.getItem(which); mapView.getController().animateTo(stationItem.getPoint()); onStationTap(stationItem.station); } }); return builder.create(); } return super.onCreateDialog(id); } /* * Setup options menu (available on menu button) * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) */ @Override public boolean onCreateOptionsMenu(Menu menu) { final MenuItem myLocation = menu.add(0, MYLOCATION_ID, 0, R.string.myLocation); myLocation.setIcon(android.R.drawable.ic_menu_mylocation); return true; } /* * Options menu item selected (available on menu button) * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem) */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case MYLOCATION_ID: final GeoPoint point = locationOverlay.getMyLocation(); if (point == null) { Toast.makeText(this, R.string.noLocationFound, Toast.LENGTH_SHORT).show(); } else { mapView.getController().animateTo(locationOverlay.getMyLocation()); } break; } return super.onOptionsItemSelected(item); } @Override protected boolean isRouteDisplayed() { return false; } @Override protected void onPause() { locationOverlay.disableMyLocation(); super.onPause(); } @Override protected void onResume() { super.onResume(); locationOverlay.enableMyLocation(); } @Override protected void onSaveInstanceState(Bundle outState) { // TODO Auto-generated method stub super.onSaveInstanceState(outState); } @Override protected void onStop() { favoriteDbAdapter.close(); if (tripProvider != null) { tripProvider.kill(); } super.onStop(); } static class ViewHolder { ImageButton list; TransparentPanel infoPanel; TextView name; TextView information; ImageButton select; } }