net.naonedbus.fragment.impl.ItineraireFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.naonedbus.fragment.impl.ItineraireFragment.java

Source

/**
 * Copyright (C) 2013 Romain Guefveneu.
 *   
 *  This file is part of naonedbus.
 *   
 *  Naonedbus 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.
 *  
 *  Naonedbus 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 net.naonedbus.fragment.impl;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;

import net.naonedbus.NBApplication;
import net.naonedbus.R;
import net.naonedbus.activity.impl.AddressSearchActivity;
import net.naonedbus.bean.Equipement;
import net.naonedbus.bean.Equipement.Type;
import net.naonedbus.bean.ItineraryWrapper;
import net.naonedbus.bean.async.AsyncResult;
import net.naonedbus.fragment.AbstractListFragment;
import net.naonedbus.loader.ItineraryLoader;
import net.naonedbus.provider.impl.NaoLocationManager;
import net.naonedbus.provider.impl.NaoLocationManager.NaoLocationListener;
import net.naonedbus.task.AddressResolverTask;
import net.naonedbus.task.AddressResolverTask.AddressTaskListener;
import net.naonedbus.utils.ColorUtils;
import net.naonedbus.utils.FormatUtils;
import net.naonedbus.widget.adapter.impl.DateKindSpinnerAdaper;
import net.naonedbus.widget.adapter.impl.ItineraryWrapperArrayAdapter;

import org.joda.time.MutableDateTime;

import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Intent;
import android.graphics.Color;
import android.location.Address;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.DatePicker;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;

import com.bugsense.trace.BugSenseHandler;

public class ItineraireFragment extends AbstractListFragment
        implements LoaderCallbacks<AsyncResult<List<ItineraryWrapper>>>, OnDateSetListener, OnTimeSetListener,
        NaoLocationListener {

    private static final String BUNDLE_LOCATION_FROM = "ItineraireFragment:locationFrom";
    private static final String BUNDLE_LOCATION_TO = "ItineraireFragment:locationTo";
    private static final String BUNDLE_ADDRESS_FROM = "ItineraireFragment:addressFrom";
    private static final String BUNDLE_ADDRESS_TO = "ItineraireFragment:addressTo";
    private static final String BUNDLE_DATE_TIME = "ItineraireFragment:dateTime";
    private static final String BUNDLE_ARRIVE_BY = "ItineraireFragment:arriveBy";
    private static final String BUNDLE_ICON_FROM = "ItineraireFragment:iconFrom";
    private static final String BUNDLE_ICON_TO = "ItineraireFragment:iconTo";
    private static final String BUNDLE_COLOR_FROM = "ItineraireFragment:colorFrom";
    private static final String BUNDLE_COLOR_TO = "ItineraireFragment:colorTo";
    private static final String BUNDLE_RESULTS = "ItineraireFragment:results";

    private static final int REQUEST_CODE_FROM = 1;
    private static final int REQUEST_CODE_TO = 2;

    private final List<ItineraryWrapper> mItineraryWrappers = new ArrayList<ItineraryWrapper>();
    private ItineraryWrapperArrayAdapter mAdapter;
    private View mProgressView;

    private DateFormat mDateFormat;
    private AddressResolverTask mAddressResolverTask;

    private final NaoLocationManager mLocationProvider;
    private final Location mFromLocation = new Location(LocationManager.GPS_PROVIDER);
    private final Location mToLocation = new Location(LocationManager.GPS_PROVIDER);
    private final MutableDateTime mDateTime = new MutableDateTime();
    private boolean mArriveBy;

    private boolean mFromCurrentLocation;
    private boolean mToCurrentLocation;

    private TextView mFromAddressTextView;
    private TextView mToAddressTextView;
    private TextView mDateAndTimeLabel;
    private Spinner mDateKindSpinner;
    private View mReverseButton;

    private ImageView mIconFrom;
    private ImageView mIconTo;
    private int mIconFromColor = Color.TRANSPARENT;
    private int mIconToColor = Color.TRANSPARENT;
    private int mIconFromResId = R.drawable.ic_directions_form_destination_notselected;
    private int mIconToResId = R.drawable.ic_directions_form_destination_notselected;

    private int mIconPadding;

    private boolean mDialogLock;

    public ItineraireFragment() {
        super(R.layout.fragment_itineraire);

        mLocationProvider = NBApplication.getLocationProvider();
    }

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mDateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
        mIconPadding = getResources().getDimensionPixelSize(R.dimen.itinerary_icon_padding);

        if (savedInstanceState != null) {
            mFromLocation.set((Location) savedInstanceState.getParcelable(BUNDLE_LOCATION_FROM));
            mToLocation.set((Location) savedInstanceState.getParcelable(BUNDLE_LOCATION_TO));

            mDateTime.setMillis(savedInstanceState.getLong(BUNDLE_DATE_TIME));
            mArriveBy = savedInstanceState.getBoolean(BUNDLE_ARRIVE_BY);
            mIconFromResId = savedInstanceState.getInt(BUNDLE_ICON_FROM);
            mIconToResId = savedInstanceState.getInt(BUNDLE_ICON_TO);
            mIconFromColor = savedInstanceState.getInt(BUNDLE_COLOR_FROM);
            mIconToColor = savedInstanceState.getInt(BUNDLE_COLOR_TO);

            final List<Parcelable> results = savedInstanceState.getParcelableArrayList(BUNDLE_RESULTS);
            for (final Parcelable parcelable : results) {
                mItineraryWrappers.add((ItineraryWrapper) parcelable);
            }

        }
    };

    @Override
    public void onStart() {
        super.onStart();
        mLocationProvider.addListener(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        mLocationProvider.removeListener(this);

        if (mAddressResolverTask != null) {
            mAddressResolverTask.cancel(false);
        }
    }

    @Override
    public void onSaveInstanceState(final Bundle outState) {
        outState.putParcelable(BUNDLE_LOCATION_FROM, mFromLocation);
        outState.putParcelable(BUNDLE_LOCATION_TO, mToLocation);
        outState.putString(BUNDLE_ADDRESS_FROM, mFromAddressTextView.getText().toString());
        outState.putString(BUNDLE_ADDRESS_TO, mToAddressTextView.getText().toString());
        outState.putLong(BUNDLE_DATE_TIME, mDateTime.getMillis());
        outState.putBoolean(BUNDLE_ARRIVE_BY, mArriveBy);
        outState.putInt(BUNDLE_ICON_FROM, mIconFromResId);
        outState.putInt(BUNDLE_ICON_TO, mIconToResId);
        outState.putInt(BUNDLE_COLOR_FROM, mIconFromColor);
        outState.putInt(BUNDLE_COLOR_TO, mIconToColor);
        outState.putParcelableArrayList(BUNDLE_RESULTS, new ArrayList<ItineraryWrapper>(mItineraryWrappers));
        super.onSaveInstanceState(outState);
    }

    @Override
    public void onListItemClick(final ListView l, final View v, final int position, final long id) {
        super.onListItemClick(l, v, position, id);

        final Bundle bundle = new Bundle();
        bundle.putString(ItineraryDetailFragment.PARAM_ITINERARY_FROM, mFromAddressTextView.getText().toString());
        bundle.putString(ItineraryDetailFragment.PARAM_ITINERARY_TO, mToAddressTextView.getText().toString());
        bundle.putParcelable(ItineraryDetailFragment.PARAM_ITINERARY_WRAPPER, mItineraryWrappers.get(position));

        final DialogFragment dialogFragment = new ItineraryDetailDialogFragment();
        dialogFragment.setArguments(bundle);
        dialogFragment.show(getChildFragmentManager(), "ItineraryDetails");
    }

    @Override
    protected void bindView(final View view, final Bundle savedInstanceState) {
        final ListView listView = (ListView) view.findViewById(android.R.id.list);
        mProgressView = view.findViewById(android.R.id.progress);

        mAdapter = new ItineraryWrapperArrayAdapter(getActivity(), mItineraryWrappers);
        listView.setAdapter(mAdapter);

        mIconFrom = (ImageView) view.findViewById(R.id.formIconFrom);
        mIconTo = (ImageView) view.findViewById(R.id.formIconTo);

        mFromAddressTextView = (TextView) view.findViewById(R.id.formFrom);
        mFromAddressTextView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                requestFromAddress();
            }
        });

        mToAddressTextView = (TextView) view.findViewById(R.id.formTo);
        mToAddressTextView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                requestToAddress();
            }
        });

        mDateAndTimeLabel = (TextView) view.findViewById(R.id.dateAndTimeLabel);
        mDateAndTimeLabel.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                showDatePicker();
            }
        });

        mDateKindSpinner = (Spinner) view.findViewById(R.id.dateKind);
        mDateKindSpinner.setAdapter(new DateKindSpinnerAdaper(getActivity()));
        mDateKindSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(final AdapterView<?> parent, final View view, final int position,
                    final long id) {
                final boolean arriveBy = position == 1;
                if (arriveBy != mArriveBy) {
                    mArriveBy = arriveBy;
                    onFormValueChange();
                }
            }

            @Override
            public void onNothingSelected(final AdapterView<?> parent) {

            }
        });

        mReverseButton = view.findViewById(R.id.formReverse);
        mReverseButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                reverse();
            }
        });

        if (savedInstanceState != null) {
            notifyIconsChanged();
        } else {
            final Location currentLocation = NBApplication.getLocationProvider().getLastLocation();
            if (currentLocation != null && currentLocation.getLatitude() != 0
                    && currentLocation.getLongitude() != 0) {
                mFromLocation.set(currentLocation);
                mFromAddressTextView.setText(R.string.itineraire_current_location);
                mFromCurrentLocation = true;

                mIconFromResId = R.drawable.ic_directions_form_mylocation;

                notifyIconsChanged();
                loadCurrentAddress(new AddressTaskListener() {
                    @Override
                    public void onAddressTaskResult(Address address) {
                        if (address != null) {
                            mFromAddressTextView.setText(FormatUtils.formatAddress(address, null));
                        }
                    }

                    @Override
                    public void onAddressTaskPreExecute() {

                    }
                });
            }
        }

        setDateValue();
    }

    @Override
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (data != null) {
            final String address = data.getStringExtra("address");
            final double latitude = data.getDoubleExtra("latitude", 0d);
            final double longitude = data.getDoubleExtra("longitude", 0d);
            final Equipement.Type type = (Type) data.getSerializableExtra("type");
            final boolean currentLocation = data.getBooleanExtra("isCurrentLocation", false);

            if (requestCode == REQUEST_CODE_FROM) {
                mFromLocation.setLatitude(latitude);
                mFromLocation.setLongitude(longitude);
                mFromAddressTextView.setText(address);
                if (type == null) {
                    mIconFromResId = currentLocation ? R.drawable.ic_action_locate_blue
                            : R.drawable.ic_directions_form_destination_notselected;
                    mIconFromColor = Color.TRANSPARENT;
                } else {
                    mIconFromResId = type.getDrawableRes();
                    mIconFromColor = getActivity().getResources().getColor(type.getBackgroundColorRes());
                }

                mFromCurrentLocation = currentLocation;
            } else {
                mToLocation.setLatitude(latitude);
                mToLocation.setLongitude(longitude);
                mToAddressTextView.setText(address);
                if (type == null) {
                    mIconFromResId = currentLocation ? R.drawable.ic_action_locate_blue
                            : R.drawable.ic_directions_form_destination_notselected;
                    mIconToColor = Color.TRANSPARENT;
                } else {
                    mIconToResId = type.getDrawableRes();
                    mIconToColor = getActivity().getResources().getColor(type.getBackgroundColorRes());
                }

                mToCurrentLocation = currentLocation;
            }

            notifyIconsChanged();
        }

        onFormValueChange();
    }

    private void requestFromAddress() {
        requestAddress(REQUEST_CODE_FROM, mFromCurrentLocation ? null : mFromAddressTextView.getText());
    }

    private void requestToAddress() {
        requestAddress(REQUEST_CODE_TO, mToCurrentLocation ? null : mToAddressTextView.getText());
    }

    private void requestAddress(final int requestCode, final CharSequence query) {
        final Intent intent = new Intent(getActivity(), AddressSearchActivity.class);
        if (query != null) {
            intent.putExtra(AddressSearchFragment.PARAM_QUERY, query);
        }

        startActivityForResult(intent, requestCode);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
            getActivity().overridePendingTransition(R.anim.slide_in_from_right, R.anim.half_fade_out);
    }

    private void showDatePicker() {
        final DatePickerDialog dialog = new DatePickerDialog(getActivity(), this, mDateTime.getYear(),
                mDateTime.getMonthOfYear() - 1, mDateTime.getDayOfMonth());
        dialog.show();
    }

    private void showTimePicker() {
        final TimePickerDialog dialog = new TimePickerDialog(getActivity(), this, mDateTime.getHourOfDay(),
                mDateTime.getMinuteOfHour(), true);
        dialog.show();
    }

    private void reverse() {
        final CharSequence fromText = mFromAddressTextView.getText();
        final CharSequence toText = mToAddressTextView.getText();
        final Location temp = new Location(LocationManager.GPS_PROVIDER);

        mToAddressTextView.setText(fromText);
        mFromAddressTextView.setText(toText);

        temp.set(mFromLocation);
        mFromLocation.set(mToLocation);
        mToLocation.set(temp);

        int t = mIconToResId;
        mIconToResId = mIconFromResId;
        mIconFromResId = t;

        t = mIconFromColor;
        mIconFromColor = mIconToColor;
        mIconToColor = t;

        boolean tempB = mFromCurrentLocation;
        mFromCurrentLocation = mToCurrentLocation;
        mToCurrentLocation = tempB;

        notifyIconsChanged();
        onFormValueChange();

        final Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.rotation_full);
        mReverseButton.startAnimation(animation);
    }

    private void notifyIconsChanged() {
        setIcon(mIconFrom, mIconFromResId, mIconFromColor);
        setIcon(mIconTo, mIconToResId, mIconToColor);
    }

    private void setIcon(final ImageView imageView, final int icoRes, final int color) {
        imageView.setImageResource(icoRes);
        if (color == Color.TRANSPARENT) {
            imageView.setBackgroundDrawable(null);
            imageView.setPadding(0, 0, 0, 0);
        } else {
            imageView.setBackgroundDrawable(ColorUtils.getCircle(color));
            imageView.setPadding(mIconPadding, mIconPadding, mIconPadding, mIconPadding);
        }
    }

    @Override
    public void onDateSet(final DatePicker view, final int year, final int monthOfYear, final int dayOfMonth) {
        mDateTime.setYear(year);
        mDateTime.setMonthOfYear(monthOfYear + 1);
        mDateTime.setDayOfMonth(dayOfMonth);

        if (!mDialogLock) {
            showTimePicker();
            mDialogLock = true;
        }
    }

    @Override
    public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
        mDateTime.setHourOfDay(hourOfDay);
        mDateTime.setMinuteOfHour(minute);

        mDateAndTimeLabel.setText(mDateFormat.format(mDateTime.toDate()));

        onFormValueChange();
        mDialogLock = false;
    }

    private void onFormValueChange() {
        final boolean hasLocations = mFromLocation.getLatitude() != 0 && mToLocation.getLatitude() != 0;
        if (hasLocations) {
            showProgress();
            sendRequest();
        }
    }

    private void setDateValue() {
        mDateAndTimeLabel.setText(mDateFormat.format(mDateTime.toDate()));
    }

    private void sendRequest() {
        if (mFromLocation.bearingTo(mToLocation) == 0.0f) {
            hideProgress();
            mItineraryWrappers.add(ItineraryWrapper.getUnicornItinerary());
            mAdapter.notifyDataSetChanged();
        } else {
            final Bundle bundle = new Bundle();
            bundle.putDouble(ItineraryLoader.PARAM_FROM_LATITUDE, mFromLocation.getLatitude());
            bundle.putDouble(ItineraryLoader.PARAM_FROM_LONGITUDE, mFromLocation.getLongitude());
            bundle.putDouble(ItineraryLoader.PARAM_TO_LATITUDE, mToLocation.getLatitude());
            bundle.putDouble(ItineraryLoader.PARAM_TO_LONGITUDE, mToLocation.getLongitude());
            bundle.putLong(ItineraryLoader.PARAM_TIME, mDateTime.getMillis());
            bundle.putBoolean(ItineraryLoader.PARAM_ARRIVE_BY, mArriveBy);

            getLoaderManager().restartLoader(0, bundle, this);
        }
    }

    private void showProgress() {
        mProgressView.setVisibility(View.VISIBLE);
        mAdapter.clear();
    }

    private void hideProgress() {
        mProgressView.setVisibility(View.GONE);
    }

    private void loadCurrentAddress(AddressTaskListener listener) {
        if (mAddressResolverTask != null) {
            mAddressResolverTask.cancel(true);
        }
        mAddressResolverTask = (AddressResolverTask) new AddressResolverTask(listener).execute();
    }

    @Override
    public Loader<AsyncResult<List<ItineraryWrapper>>> onCreateLoader(final int loaderId, final Bundle bundle) {
        return new ItineraryLoader(getActivity(), bundle);
    }

    @Override
    public void onLoadFinished(final Loader<AsyncResult<List<ItineraryWrapper>>> loader,
            final AsyncResult<List<ItineraryWrapper>> result) {

        hideProgress();
        if (result.getException() == null) {
            mItineraryWrappers.clear();
            if (result.getResult() == null) {
                mItineraryWrappers.add(ItineraryWrapper.getEmptyItinerary());
            } else {
                mItineraryWrappers.addAll(result.getResult());
            }
        } else {
            mItineraryWrappers.add(ItineraryWrapper.getErrorItinerary());
            BugSenseHandler.sendExceptionMessage("Erreur de calcul d'itinraire.", null, result.getException());
        }

        mAdapter.notifyDataSetChanged();
        getListView().smoothScrollToPosition(1);

    }

    @Override
    public void onLoaderReset(final Loader<AsyncResult<List<ItineraryWrapper>>> arg0) {

    }

    @Override
    public void onConnecting() {

    }

    @Override
    public void onLocationChanged(Location location) {

    }

    @Override
    public void onDisconnected() {

    }

    @Override
    public void onLocationTimeout() {

    }

}