com.ratebeer.android.gui.fragments.PlacesFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.ratebeer.android.gui.fragments.PlacesFragment.java

Source

/*
This file is part of RateBeer For Android.
    
RateBeer for Android 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.
    
RateBeer for Android 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 RateBeer for Android.  If not, see 
<http://www.gnu.org/licenses/>.
 */
package com.ratebeer.android.gui.fragments;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.googlecode.androidannotations.annotations.AfterViews;
import com.googlecode.androidannotations.annotations.EFragment;
import com.googlecode.androidannotations.annotations.InstanceState;
import com.googlecode.androidannotations.annotations.OptionsItem;
import com.googlecode.androidannotations.annotations.OptionsMenu;
import com.googlecode.androidannotations.annotations.ViewById;
import com.ratebeer.android.R;
import com.ratebeer.android.api.ApiMethod;
import com.ratebeer.android.api.CommandFailureResult;
import com.ratebeer.android.api.CommandSuccessResult;
import com.ratebeer.android.api.command.GetPlacesAroundCommand;
import com.ratebeer.android.api.command.GetPlacesAroundCommand.Place;
import com.ratebeer.android.app.location.LocationUtils;
import com.ratebeer.android.app.location.MyLocation;
import com.ratebeer.android.app.location.MyLocation.LocationResult;
import com.ratebeer.android.app.location.TouchableMapViewPager;
import com.ratebeer.android.gui.components.RateBeerActivity;
import com.ratebeer.android.gui.components.RateBeerMapFragment;
import com.ratebeer.android.gui.components.SelectLocationDialog;
import com.ratebeer.android.gui.components.SelectLocationDialog.OnLocationSelectedListener;
import com.ratebeer.android.gui.components.helpers.ArrayAdapter;
import com.viewpagerindicator.TabPageIndicator;

@EFragment(R.layout.fragment_places)
@OptionsMenu(R.menu.places)
public class PlacesFragment extends RateBeerMapFragment implements OnLocationSelectedListener {

    private static final int DEFAULT_RADIUS = 25;
    private static final String GEOCODER_PROVIDER = "geocoder";

    @InstanceState
    protected ArrayList<Place> places = null;
    @InstanceState
    protected Location lastLocation = null;

    @ViewById
    protected TouchableMapViewPager pager;
    @ViewById
    protected TabPageIndicator titles;
    private ListView placesView;
    private Map<String, Place> markersMap = new HashMap<String, GetPlacesAroundCommand.Place>();

    public PlacesFragment() {
    }

    @AfterViews
    public void init() {

        pager.setAdapter(new PlacesPagerAdapter());
        titles.setViewPager(pager);
        titles.setOnPageChangeListener(pager.getOnPageChangeListener());

        if (places != null) {
            publishResults(places);
        }

        // Retrieve already with a (old) stored location
        lastLocation = getSettings().getLastUserLocation();
        if (lastLocation != null) {
            execute(new GetPlacesAroundCommand(getUser(), DEFAULT_RADIUS, lastLocation.getLatitude(),
                    lastLocation.getLongitude()));
        }

        // Always trigger a location update as well
        refreshPlaces();

    }

    @OptionsItem(R.id.menu_location)
    protected void onSelectNewLocation() {
        new SelectLocationDialog(this).show(getFragmentManager(), "SelectLocationDialog");
    }

    // Implements OnLocationSelectedListener
    @Override
    public void onStartLocationSearch(String query) {
        // Try to find a location for the user query, using a Geocoder
        try {
            List<Address> point = new Geocoder(getActivity()).getFromLocationName(query, 1);
            if (point.size() <= 0) {
                // Cannot find address: give an error
                publishException(null, getString(R.string.error_nolocation));
            } else {
                // Found a location! Now look for places
                lastLocation = new Location(GEOCODER_PROVIDER);
                lastLocation.setLongitude(point.get(0).getLongitude());
                lastLocation.setLatitude(point.get(0).getLatitude());
                execute(new GetPlacesAroundCommand(getUser(), DEFAULT_RADIUS, lastLocation.getLatitude(),
                        lastLocation.getLongitude()));
            }
        } catch (IOException e) {
            // Can't connect to Geocoder server: give an error
            publishException(null, getString(R.string.error_nolocation));
        }
    }

    // Implements OnLocationSelectedListener
    @Override
    public void onUseCurrentLocation() {
        refreshPlaces();
    }

    @OptionsItem(R.id.menu_refresh)
    protected void refreshPlaces() {
        // Get the current location (if possible)
        if (new MyLocation().getLocation(getActivity(), onLocationResult)) {
            // Force the progress indicator to start
            ((RateBeerActivity) getActivity()).setProgress(true);
        } else {
            publishException(null, getString(R.string.error_locationnotsupported));
        }
    }

    private LocationResult onLocationResult = new LocationResult() {

        @Override
        public void gotLocation(Location location) {
            if (location == null && getView() != null) {
                getView().post(new Runnable() {
                    @Override
                    public void run() {
                        if (getActivity() != null) {
                            publishException(null, getString(R.string.error_nolocation));
                        }
                    }
                });
                return;
            }
            // Now get the places at this location, if this fragment is still bound to an activity
            PlacesFragment.this.lastLocation = location;
            if (getActivity() != null && getView() != null && PlacesFragment.this.lastLocation != null) {
                getView().post(new Runnable() {
                    @Override
                    public void run() {
                        getSettings().saveLastUserLocation(lastLocation);
                        execute(new GetPlacesAroundCommand(getUser(), DEFAULT_RADIUS, lastLocation.getLatitude(),
                                lastLocation.getLongitude()));
                    }
                });
            }
        }
    };

    private OnItemClickListener onItemSelected = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            Place item = ((PlacesAdapter) placesView.getAdapter()).getItem(position);
            load(PlaceViewFragment_.builder().place(item).currentLocation(lastLocation).build());
        }
    };

    @Override
    public void onTaskSuccessResult(CommandSuccessResult result) {
        if (result.getCommand().getMethod() == ApiMethod.GetPlacesAround) {
            publishResults(((GetPlacesAroundCommand) result.getCommand()).getPlaces());
        }
    }

    private void publishResults(ArrayList<Place> result) {
        this.places = result;
        //Collections.sort(result, new PlacesComparator(sortOrder));
        if (placesView.getAdapter() == null) {
            placesView.setAdapter(new PlacesAdapter(getActivity(), result));
        } else {
            ((PlacesAdapter) placesView.getAdapter()).replace(result);
        }

        if (lastLocation != null && getMap() != null) {

            // TODO: Show user location
            LocationUtils.initGoogleMap(getMap(), lastLocation.getLatitude(), lastLocation.getLongitude());
            for (Place place : places) {
                Marker m = getMap()
                        .addMarker(new MarkerOptions().position(new LatLng(place.latitude, place.longitude))
                                .title(place.placeName).snippet(LocationUtils.getPlaceSnippet(getActivity(), place))
                                .icon(BitmapDescriptorFactory.defaultMarker(LocationUtils.getPlaceColour(place))));
                markersMap.put(m.getId(), place);
            }
            getMap().setOnInfoWindowClickListener(onInfoWindowClicked);
            getMap().setMyLocationEnabled(true);

        }

    }

    private OnInfoWindowClickListener onInfoWindowClicked = new OnInfoWindowClickListener() {
        @Override
        public void onInfoWindowClick(Marker marker) {
            load(PlaceViewFragment_.builder().place(markersMap.get(marker.getId())).currentLocation(lastLocation)
                    .build());
        }
    };

    @Override
    public void onTaskFailureResult(CommandFailureResult result) {
        publishException(null, result.getException());
    }

    @Override
    protected void publishException(TextView textview, String message) {
        ((RateBeerActivity) getActivity()).setProgress(false);
        super.publishException(textview, message);
    }

    private class PlacesAdapter extends ArrayAdapter<Place> {

        public PlacesAdapter(Context context, List<Place> objects) {
            super(context, objects);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            // Get the right view, using a ViewHolder
            ViewHolder holder;
            if (convertView == null) {
                convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_place, null);
                holder = new ViewHolder();
                holder.placeName = (TextView) convertView.findViewById(R.id.placeName);
                holder.placeType = (TextView) convertView.findViewById(R.id.placeType);
                holder.distance = (TextView) convertView.findViewById(R.id.distance);
                holder.city = (TextView) convertView.findViewById(R.id.city);
                holder.score = (TextView) convertView.findViewById(R.id.score);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            // Bind the data
            Place item = getItem(position);
            holder.placeName.setText(item.placeName);
            holder.placeType.setText(getPlaceTypeName(getActivity(), item.placeType));
            holder.distance
                    .setText(LocationUtils.getPlaceDistance(getSettings(), getResources(), item, lastLocation));
            holder.city.setText(item.city);
            holder.score.setText(item.avgRating == -1 ? "?" : Integer.toString(item.avgRating));

            return convertView;
        }

    }

    public static String getPlaceTypeName(Context context, int placeType) {
        switch (placeType) {
        case 1:
            return context.getString(R.string.places_brewpub);
        case 2:
            return context.getString(R.string.places_bar);
        case 3:
            return context.getString(R.string.places_beerstore);
        case 4:
            return context.getString(R.string.places_restaurant);
        case 5:
            return context.getString(R.string.places_brewer);
        default:
            return context.getString(R.string.places_unknown);
        }
    }

    protected static class ViewHolder {
        TextView placeName, placeType, distance, city, score;
    }

    private class PlacesPagerAdapter extends PagerAdapter {

        private ListView pagerListView;
        private FrameLayout pagerMapView;

        public PlacesPagerAdapter() {
            LayoutInflater inflater = getActivity().getLayoutInflater();
            pagerListView = (ListView) inflater.inflate(R.layout.fragment_pagerlist, null);
            pagerMapView = (FrameLayout) inflater.inflate(R.layout.fragment_placesmap, null);

            placesView = pagerListView;
            placesView.setOnItemClickListener(onItemSelected);

            setMapView((MapView) pagerMapView.findViewById(R.id.map_nearby));
        }

        @Override
        public int getCount() {
            return 2;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
            case 0:
                return getActivity().getString(R.string.places_nearby).toUpperCase(Locale.getDefault());
            case 1:
                return getActivity().getString(R.string.places_map).toUpperCase(Locale.getDefault());
            }
            return null;
        }

        @Override
        public Object instantiateItem(View container, int position) {
            switch (position) {
            case 0:
                ((ViewPager) container).addView(pagerListView, 0);
                return pagerListView;
            case 1:
                ((ViewPager) container).addView(pagerMapView, 0);
                return pagerMapView;
            }
            return null;
        }

        @Override
        public void destroyItem(View container, int position, Object object) {
            ((ViewPager) container).removeView((View) object);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == (View) object;
        }

    }

}