package de.stephanlindauer.criticalmaps.fragments; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.method.LinkMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.RelativeLayout; import android.widget.TextView; import com.squareup.otto.Subscribe; import org.osmdroid.DefaultResourceProxyImpl; import org.osmdroid.util.GeoPoint; import org.osmdroid.views.MapView; import javax.inject.Inject; import butterknife.Bind; import butterknife.BindDrawable; import butterknife.ButterKnife; import de.stephanlindauer.criticalmaps.App; import de.stephanlindauer.criticalmaps.R; import de.stephanlindauer.criticalmaps.events.NewLocationEvent; import de.stephanlindauer.criticalmaps.events.NewServerResponseEvent; import de.stephanlindauer.criticalmaps.model.OtherUsersLocationModel; import de.stephanlindauer.criticalmaps.model.OwnLocationModel; import de.stephanlindauer.criticalmaps.overlays.LocationMarker; import de.stephanlindauer.criticalmaps.provider.EventBusProvider; import de.stephanlindauer.criticalmaps.managers.LocationUpdateManager; import de.stephanlindauer.criticalmaps.utils.MapViewUtils; public class MapFragment extends Fragment { // constants private final static String KEY_MAP_ZOOMLEVEL = "map_zoomlevel"; private final static String KEY_MAP_POSITION = "map_position"; private final static String KEY_INITIAL_LOCATION_SET = "initial_location_set"; //dependencies @Inject OwnLocationModel ownLocationModel; @Inject OtherUsersLocationModel otherUsersLocationModel; @Inject EventBusProvider eventService; @Inject LocationUpdateManager locationUpdateManager; //view private MapView mapView; @Bind(R.id.set_current_location_center) ImageButton setCurrentLocationCenter; @Bind(R.id.map_container) RelativeLayout mapContainer; @Bind(R.id.searching_for_location_overlay_map) RelativeLayout searchingForLocationOverlay; @Bind(R.id.map_osm_notice) TextView osmNoticeOverlay; //misc private DefaultResourceProxyImpl resourceProxy; private boolean isInitialLocationSet = false; //cache drawables @BindDrawable(R.drawable.map_marker) Drawable locationIcon; @BindDrawable(R.drawable.map_marker_own) Drawable ownLocationIcon; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.fragment_map, container, false); ButterKnife.bind(this, view); return view; } @Override public void onActivityCreated(final Bundle savedState) { super.onActivityCreated(savedState); App.components().inject(this); resourceProxy = new DefaultResourceProxyImpl(getActivity().getApplication()); osmNoticeOverlay.setMovementMethod(LinkMovementMethod.getInstance()); mapView = MapViewUtils.createMapView(getActivity(), resourceProxy); mapContainer.addView(mapView); setCurrentLocationCenter.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if (ownLocationModel.ownLocation != null) animateToLocation(ownLocationModel.ownLocation); } }); if (savedState != null) { Integer zoomLevel = (Integer) savedState.get(KEY_MAP_ZOOMLEVEL); int[] position = savedState.getIntArray(KEY_MAP_POSITION); if (zoomLevel != null && position != null) { mapView.getController().setZoom(zoomLevel); mapView.scrollTo(position[0], position[1]); } isInitialLocationSet = savedState.getBoolean(KEY_INITIAL_LOCATION_SET, false); } else { setInitialMapLocation(); } } private void setInitialMapLocation() { if (ownLocationModel.ownLocation == null) { GeoPoint lastKnownLocation = locationUpdateManager.getLastKnownLocation(); if (lastKnownLocation != null) { setToLocation(lastKnownLocation); } } } private void refreshView() { mapView.getOverlays().clear(); for (GeoPoint currentOtherUsersLocation : otherUsersLocationModel.getOtherUsersLocations()) { LocationMarker otherPeoplesMarker = new LocationMarker(mapView, resourceProxy); otherPeoplesMarker.setPosition(currentOtherUsersLocation); otherPeoplesMarker.setIcon(locationIcon); mapView.getOverlays().add(otherPeoplesMarker); } if (ownLocationModel.ownLocation != null) { GeoPoint currentUserLocation = ownLocationModel.ownLocation; LocationMarker ownMarker = new LocationMarker(mapView, resourceProxy); ownMarker.setPosition(currentUserLocation); ownMarker.setIcon(ownLocationIcon); mapView.getOverlays().add(ownMarker); } mapView.invalidate(); } @Override public void onResume() { super.onResume(); if (ownLocationModel.ownLocation != null) { if (!isInitialLocationSet) { handleFirstLocationUpdate(); } else { searchingForLocationOverlay.setVisibility(View.GONE); } } eventService.register(this); refreshView(); } private void handleFirstLocationUpdate() { searchingForLocationOverlay.setVisibility(View.GONE); animateToLocation(ownLocationModel.ownLocation); isInitialLocationSet = true; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(KEY_MAP_ZOOMLEVEL, mapView.getZoomLevel()); outState.putIntArray(KEY_MAP_POSITION, new int[]{mapView.getScrollX(), mapView.getScrollY()}); outState.putBoolean(KEY_INITIAL_LOCATION_SET, isInitialLocationSet); } @Override public void onPause() { super.onPause(); eventService.unregister(this); } @Override public void onDestroyView() { super.onDestroyView(); mapView = null; ButterKnife.unbind(this); } @Subscribe public void handleNewServerData(NewServerResponseEvent e) { refreshView(); } @Subscribe public void handleNewLocation(NewLocationEvent e) { // if this is the first location update handle it accordingly if (!isInitialLocationSet) { handleFirstLocationUpdate(); } refreshView(); } private void animateToLocation(final GeoPoint location) { mapView.getController().animateTo(location); } private void setToLocation(GeoPoint lastKnownLocation) { mapView.getController().setCenter(lastKnownLocation); } }