package net.naonedbus.fragment.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import net.naonedbus.BuildConfig; import net.naonedbus.NBApplication; import net.naonedbus.R; import net.naonedbus.activity.impl.MapActivity; import net.naonedbus.bean.Equipement; import net.naonedbus.bean.Equipement.Type; import net.naonedbus.loader.MapLoader; import net.naonedbus.loader.MapLoader.MapLoaderCallback; import net.naonedbus.manager.impl.EquipementManager; import net.naonedbus.map.ToastedMarkerOptionsChooser; import net.naonedbus.map.layer.BiclooMapLayer; import net.naonedbus.map.layer.EquipementMapLayer; import net.naonedbus.map.layer.ParkingMapLayer; import net.naonedbus.map.layer.ProxyInfoWindowAdapter; import net.naonedbus.provider.impl.NaoLocationManager; import net.naonedbus.widget.adapter.impl.EquipementCursorAdapter; import android.app.Activity; import android.content.SharedPreferences; import android.database.Cursor; import android.database.CursorWrapper; import android.location.Location; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.SubMenu; import com.actionbarsherlock.widget.SearchView; import com.actionbarsherlock.widget.SearchView.OnSuggestionListener; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.UiSettings; import com.google.android.gms.maps.model.LatLng; import com.twotoasters.clusterkraf.Clusterkraf; import com.twotoasters.clusterkraf.InputPoint; public class MapFragment extends SherlockFragment implements MapLoaderCallback, OnSuggestionListener { public static final String PARAM_ITEM_ID = "itemId"; public static final String PARAM_ITEM_TYPE = "itemType"; private static String LOG_TAG = "MapFragment"; private static boolean DBG = BuildConfig.DEBUG; private static final int MENU_GROUP_TYPES = 1; private static final String PREF_MAP_LAYER = "map.layer."; private final Map<Equipement.Type, List<InputPoint>> mInputPoints = new HashMap<Equipement.Type, List<InputPoint>>(); private final com.twotoasters.clusterkraf.Options mOptions = new com.twotoasters.clusterkraf.Options(); private final Set<Equipement.Type> mSelectedTypes = new HashSet<Equipement.Type>(); private final NaoLocationManager mLocationProvider; private SharedPreferences mPreferences; private SupportMapFragment mSupportMapFragment; private GoogleMap mGoogleMap; private Clusterkraf mClusterkraf; private MapLoader mMapLoader; private MenuItem mSearchMenuItem; private MenuItem mRefreshMenuItem; private EquipementCursorAdapter mSearchAdapter; private Equipement mLastSearchedItem; private Integer mParamItemId; private Integer mParamItemType; private boolean mGooglePlayServiceAvailable; private boolean mIsMapActivity; public MapFragment() { mLocationProvider = NBApplication.getLocationProvider(); } @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setRetainInstance(true); setHasOptionsMenu(true); if (getArguments() != null && getArguments().containsKey(PARAM_ITEM_ID)) { mParamItemId = getArguments().getInt(PARAM_ITEM_ID); mParamItemType = getArguments().getInt(PARAM_ITEM_TYPE); mSelectedTypes.add(Equipement.Type.getTypeById(mParamItemType)); } } @Override public void onAttach(final Activity activity) { super.onAttach(activity); mIsMapActivity = activity instanceof MapActivity; } @Override public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) { if (container == null) // must put this in return null; final View view = inflater.inflate(R.layout.fragment_map, container, false); mSupportMapFragment = (SupportMapFragment) getFragmentManager().findFragmentById(R.id.map); mGoogleMap = mSupportMapFragment.getMap(); mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); final Equipement.Type[] types = Equipement.Type.values(); for (final Equipement.Type type : types) { if (isLayerPreferenceEnabled(type.getId())) { mSelectedTypes.add(type); } } initMap(); initClusterkraf(inflater); return view; } @Override public void onDestroyView() { removeMapFragment(); super.onDestroyView(); } private void removeMapFragment() { if (!mIsMapActivity) { final Fragment fragment = (getFragmentManager().findFragmentById(R.id.map)); if (fragment != null) { final FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction(); ft.remove(fragment); ft.commitAllowingStateLoss(); } } } @Override public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); if (mGooglePlayServiceAvailable) { inflater.inflate(R.menu.fragment_map, menu); mRefreshMenuItem = menu.findItem(R.id.menu_refresh); final EquipementManager manager = EquipementManager.getInstance(); final Cursor cursor = manager.getCursor(getActivity().getContentResolver()); mSearchAdapter = new EquipementCursorAdapter(getActivity(), cursor); mSearchMenuItem = menu.findItem(R.id.menu_search); final SearchView searchView = (SearchView) mSearchMenuItem.getActionView(); searchView.setSuggestionsAdapter(mSearchAdapter); searchView.setOnSuggestionListener(this); final SubMenu filterSubMenu = menu.findItem(R.id.menu_layers).getSubMenu(); final Equipement.Type[] types = Equipement.Type.values(); for (final Equipement.Type type : types) { final MenuItem item = filterSubMenu.add(MENU_GROUP_TYPES, type.getId(), 0, type.getTitleRes()); item.setCheckable(true); } } } @Override public void onPrepareOptionsMenu(final Menu menu) { if (mGooglePlayServiceAvailable) { final Equipement.Type[] types = Equipement.Type.values(); final SubMenu filterSubMenu = menu.findItem(R.id.menu_layers).getSubMenu(); for (final Equipement.Type type : types) { final MenuItem item = filterSubMenu.findItem(type.getId()); item.setChecked(mSelectedTypes.contains(type)); } } } @Override public boolean onOptionsItemSelected(final MenuItem item) { if (item.getGroupId() == MENU_GROUP_TYPES) { final Equipement.Type type = Equipement.Type.getTypeById(item.getItemId()); item.setChecked(!item.isChecked()); setLayerPreference(type.getId(), item.isChecked()); if (item.isChecked()) { mSelectedTypes.add(type); loadMarkers(type); } else { mSelectedTypes.remove(type); removeMarkers(type); } } else { if (item.getItemId() == R.id.menu_satellite) { item.setChecked(!item.isChecked()); if (item.isChecked()) { mGoogleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); } else { mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); } } } return super.onOptionsItemSelected(item); } @Override public boolean onSuggestionSelect(final int position) { onSearchItemClick(position); return true; } @Override public boolean onSuggestionClick(final int position) { onSearchItemClick(position); return true; } private void initMap() { final int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity()); if (resultCode == ConnectionResult.SUCCESS) { mGooglePlayServiceAvailable = true; final UiSettings uiSettings = mGoogleMap.getUiSettings(); uiSettings.setScrollGesturesEnabled(true); uiSettings.setZoomGesturesEnabled(true); uiSettings.setCompassEnabled(true); mGoogleMap.setMyLocationEnabled(true); final Location currenLocation = mLocationProvider.getLastLocation(); if (currenLocation != null) { final CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom( new LatLng(currenLocation.getLatitude(), currenLocation.getLongitude()), 15); mGoogleMap.animateCamera(cameraUpdate); } } else { mGooglePlayServiceAvailable = false; GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(), 1).show(); if (mRefreshMenuItem != null) { mRefreshMenuItem.setVisible(false); } } } private void initClusterkraf(final LayoutInflater inflater) { if (mGoogleMap != null) { final ToastedMarkerOptionsChooser markerOptionsChooser = new ToastedMarkerOptionsChooser(getActivity()); markerOptionsChooser.setDefaultMapLayer(new EquipementMapLayer(inflater)); markerOptionsChooser.registerMapLayer(Type.TYPE_BICLOO, new BiclooMapLayer(inflater)); markerOptionsChooser.registerMapLayer(Type.TYPE_PARKING, new ParkingMapLayer(inflater)); final ProxyInfoWindowAdapter infoWindowAdapter = new ProxyInfoWindowAdapter(getActivity()); infoWindowAdapter.setDefaultMapLayer(new EquipementMapLayer(inflater)); infoWindowAdapter.registerMapLayer(Type.TYPE_BICLOO, new BiclooMapLayer(inflater)); infoWindowAdapter.registerMapLayer(Type.TYPE_PARKING, new ParkingMapLayer(inflater)); mOptions.setPixelDistanceToJoinCluster(60); mOptions.setZoomToBoundsPadding(30); mOptions.setMarkerOptionsChooser(markerOptionsChooser); mOptions.setOnInfoWindowClickDownstreamListener(infoWindowAdapter); // customize the options before you construct a Clusterkraf instance mClusterkraf = new Clusterkraf(mGoogleMap, mOptions, null); mClusterkraf.setClusterkrafInfoWindowAdapter(infoWindowAdapter); loadMarkers(); } } private void onSearchItemClick(final int position) { final EquipementManager manager = EquipementManager.getInstance(); final CursorWrapper cursorWrapper = (CursorWrapper) mSearchAdapter.getItem(position); final Equipement equipement = manager.getSingleFromCursorWrapper(cursorWrapper); selectEquipement(equipement); mSearchMenuItem.collapseActionView(); } private void selectEquipement(final Equipement equipement) { final Type type = equipement.getType(); if (mInputPoints.get(type) == null) { mLastSearchedItem = equipement; mSelectedTypes.add(type); setLayerPreference(type.getId(), true); loadMarkers(); } else { final InputPoint inputPoint = findInputPoint(equipement); if (inputPoint != null) { mClusterkraf.showInfoWindow(inputPoint); } else { Toast.makeText(getActivity(), getString(R.string.msg_element_not_localized), Toast.LENGTH_LONG).show(); } } } private InputPoint findInputPoint(final Equipement equipement) { final List<InputPoint> inputPoints = mInputPoints.get(equipement.getType()); if (inputPoints != null) { for (final InputPoint inputPoint : inputPoints) { final Equipement item = (Equipement) inputPoint.getTag(); if (item.getNormalizedNom().equals(equipement.getNormalizedNom())) { return inputPoint; } } } return null; } private InputPoint findInputPoint(final Type itemType, final int itemId) { final List<InputPoint> inputPoints = mInputPoints.get(itemType); if (inputPoints != null) { for (final InputPoint inputPoint : inputPoints) { final Equipement item = (Equipement) inputPoint.getTag(); if (item.getId() == itemId) { return inputPoint; } } } return null; } private void loadMarkers() { if (DBG) Log.d(LOG_TAG, "loadMarkers " + mSelectedTypes); synchronized (mClusterkraf) { mClusterkraf.clear(); } final Equipement.Type[] types = mSelectedTypes.toArray(new Equipement.Type[mSelectedTypes.size()]); mMapLoader = new MapLoader(getActivity(), this); mMapLoader.execute(types); } private void loadMarkers(final Equipement.Type type) { mMapLoader = new MapLoader(getActivity(), this); mMapLoader.execute(type); } private void removeMarkers(final Equipement.Type type) { final List<InputPoint> inputPoints = mInputPoints.get(type); mClusterkraf.removeAll(inputPoints); } /** * Indique si le calque est activé ou non dans les préférences. * * @param id * @return Vrai si le calque est activé. */ private boolean isLayerPreferenceEnabled(final Integer id) { if (id == Equipement.Type.TYPE_ARRET.getId()) { return mPreferences.getBoolean(PREF_MAP_LAYER + id, true); } else { return mPreferences.getBoolean(PREF_MAP_LAYER + id, false); } } /** * Changer la valeur d'activation d'un calque. * * @param id * @param enabled */ private void setLayerPreference(final Integer id, final boolean enabled) { mPreferences.edit().putBoolean(PREF_MAP_LAYER + id, enabled).commit(); } @Override public void onLayerLoaded(final ArrayList<InputPoint> result) { if (result != null && !result.isEmpty()) { final Equipement tag = (Equipement) result.get(0).getTag(); final Type type = tag.getType(); if (DBG) Log.d(LOG_TAG, "onLayerLoaded " + type); mInputPoints.put(type, result); synchronized (mClusterkraf) { mClusterkraf.addAll(result); } if (mParamItemType != null && type.getId() == mParamItemType) { final InputPoint inputPoint = findInputPoint(Type.getTypeById(mParamItemType), mParamItemId); if (inputPoint != null) { mClusterkraf.showInfoWindow(inputPoint); } mParamItemType = null; mParamItemId = null; } } } @Override public void onMapLoaderStart() { if (DBG) Log.d(LOG_TAG, "onMapLoaderStart " + mRefreshMenuItem); if (mRefreshMenuItem != null) { mRefreshMenuItem.setVisible(true); } } @Override public void onMapLoaderEnd() { if (DBG) Log.d(LOG_TAG, "onMapLoaderEnd " + mRefreshMenuItem); if (mRefreshMenuItem != null) { mRefreshMenuItem.setVisible(false); } if (mLastSearchedItem != null) { selectEquipement(mLastSearchedItem); mLastSearchedItem = null; } } }