com.wheelly.fragments.LocationsListFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.wheelly.fragments.LocationsListFragment.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Denis Solonenko.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Denis Solonenko - initial API and implementation
 ******************************************************************************/
package com.wheelly.fragments;

import ru.orangesoftware.financisto.activity.LocationActivity;
import ru.orangesoftware.financisto.utils.AddressGeocoder;

import com.squareup.otto.Subscribe;
import com.squareup.otto.sample.BusProvider;
import com.google.android.apps.mytracks.ContextualActionModeCallback;
import com.google.android.apps.mytracks.util.ApiAdapterFactory;
import com.google.android.gms.location.LocationListener;
import com.google.api.client.util.Strings;
import com.wheelly.R;
import com.wheelly.app.ColorInput;
import com.wheelly.app.ColorInput.OnSelectColorListener;
import com.wheelly.app.LocationViewBinder;
import com.wheelly.bus.LocationSelectedEvent;
import com.wheelly.bus.LocationsLoadedEvent;
import com.wheelly.db.LocationBroker;
import com.wheelly.db.DatabaseSchema.Locations;
import com.wheelly.util.LocationUtils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.support.v4.app.ListFragment;
import android.support.v4.view.MenuCompat;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter.ViewBinder;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

@SuppressLint({ "NewApi", "InlinedApi" })
public class LocationsListFragment extends ListFragment {

    private static final int MENU_ADD = Menu.FIRST + 1;
    private static final int MENU_EDIT = Menu.FIRST + 2;
    private static final int MENU_DELETE = Menu.FIRST + 3;
    private static final int MENU_RESOLVE = Menu.FIRST + 5;
    private static final int MENU_COLOR = Menu.FIRST + 6;

    static final int NEW_LOCATION_REQUEST = 1;
    static final int EDIT_LOCATION_REQUEST = 2;

    private ContextualActionModeCallback contextualActionModeCallback = new ContextualActionModeCallback() {
        @Override
        public boolean onClick(int itemId, int position, long id) {
            return handleContextItem(itemId, id);
        }

        @Override
        public void onPrepare(Menu menu, int position, long id) {
            BusProvider.getInstance().post(new LocationSelectedEvent(id, LocationsListFragment.this));
        }

        @Override
        public void onCreate(Menu menu) {
            menu.add(0, MENU_RESOLVE, 0, R.string.resolve_address).setIcon(android.R.drawable.ic_menu_mylocation);
            menu.add(1, MENU_EDIT, 1, R.string.edit).setIcon(android.R.drawable.ic_menu_edit);
            menu.add(1, MENU_DELETE, 2, R.string.delete).setIcon(android.R.drawable.ic_menu_delete);
            menu.add(1, MENU_COLOR, 6, R.string.color).setIcon(android.R.drawable.ic_menu_slideshow);
        }

        @Override
        public CharSequence getCaption(View view) {
            TextView textView = (TextView) view.findViewById(android.R.id.text1);
            return textView != null ? textView.getText() : null;
        }
    };

    boolean inSelectMode;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        final Intent intent = getActivity().getIntent();
        inSelectMode = intent.hasExtra(LocationActivity.LOCATION_ID_EXTRA);
        getListView().setChoiceMode(inSelectMode ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
        setListAdapter(buildAdapter());
        ApiAdapterFactory.getApiAdapter().configureListViewContextualMenu(this, contextualActionModeCallback);
        setHasOptionsMenu(true);
        BusProvider.getInstance().register(this);
    }

    private ListAdapter buildAdapter() {
        if (inSelectMode) {
            return new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_single_choice, null,
                    new String[] { "name" }, new int[] { android.R.id.text1 }, 0) {
                {
                    setViewBinder(new ViewBinder() {
                        @Override
                        public boolean setViewValue(View view, Cursor cursor, int paramInt) {
                            if (android.R.id.text1 == view.getId()) {
                                final String argb = cursor.getString(cursor.getColumnIndex("color"));
                                if (!Strings.isNullOrEmpty(argb)) {
                                    view.setBackgroundColor(Color.parseColor(argb));
                                }
                            }
                            return false;
                        }
                    });
                }
            };
        }

        final SimpleCursorAdapter adapter = new SimpleCursorAdapter(getActivity(), R.layout.location_item, null,
                new String[] { "name", "resolved_address", "name" },
                new int[] { android.R.id.text1, android.R.id.text2, R.id.text3 }, 0);

        adapter.setViewBinder(new LocationViewBinder(null));

        LocationUtils.obtainLocation(getActivity(), new LocationListener() {
            @Override
            public void onLocationChanged(Location paramLocation) {
                ((LocationViewBinder) adapter.getViewBinder()).location = paramLocation;
                adapter.notifyDataSetChanged();
            }
        });

        return adapter;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.setHeaderTitle(R.string.locations);
        contextualActionModeCallback.onCreate(menu);
        AdapterContextMenuInfo mi = (AdapterContextMenuInfo) menuInfo;
        contextualActionModeCallback.onPrepare(menu, mi.position, mi.id);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        return (handleContextItem(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).id)) ? true
                : super.onContextItemSelected(item);

    }

    private boolean handleContextItem(int itemId, final long id) {
        switch (itemId) {
        case MENU_RESOLVE:
            startGeocode(new LocationBroker(getActivity()).loadOrCreate(id));
            return true;
        case MENU_EDIT:
            onListItemClick(getListView(), null, 0, id);
            return true;
        case MENU_DELETE:
            getActivity().getContentResolver().delete(Locations.CONTENT_URI, BaseColumns._ID + " = ?",
                    new String[] { Long.toString(id) });
            return true;
        case MENU_COLOR:
            new ColorInput(new OnSelectColorListener() {
                @Override
                public void onSelect(DialogInterface dialog, int which, int color, String argb) {
                    final LocationBroker broker = new LocationBroker(getActivity());
                    final ContentValues location = broker.loadOrCreate(id);

                    if (location.size() > 0) {
                        location.put("color", argb);
                        broker.updateOrInsert(location);
                    }
                }
            }).show(getFragmentManager(), null);
            return true;
        }
        ;
        return false;
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        MenuCompat.setShowAsAction(
                menu.add(0, MENU_ADD, 0, R.string.item_add).setIcon(android.R.drawable.ic_menu_add),
                MenuItem.SHOW_AS_ACTION_ALWAYS);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (MENU_ADD == item.getItemId()) {
            startActivityForResult(new Intent(getActivity(), LocationActivity.class), NEW_LOCATION_REQUEST);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, final long id) {
        BusProvider.getInstance().post(new LocationSelectedEvent(id, LocationsListFragment.this));

        if (inSelectMode) {
            l.setItemChecked(position, true);
            final Intent intent = new Intent();
            intent.putExtra(LocationActivity.LOCATION_ID_EXTRA, id);
            getActivity().setResult(Activity.RESULT_OK, intent);
            getActivity().finish();
        } else {
            startActivityForResult(new Intent(getActivity(), LocationActivity.class) {
                {
                    putExtra(LocationActivity.LOCATION_ID_EXTRA, id);
                }
            }, EDIT_LOCATION_REQUEST);
        }
    }

    private void startGeocode(ContentValues location) {
        new GeocoderTask(location).execute(location.getAsDouble("latitude"), location.getAsDouble("longitude"));
    }

    private class GeocoderTask extends AsyncTask<Double, Void, String> {
        private final AddressGeocoder geocoder;
        private final ContentValues location;

        private GeocoderTask(ContentValues location) {
            this.geocoder = new AddressGeocoder(getActivity());
            this.location = location;
        }

        @Override
        protected String doInBackground(Double... args) {
            Log.d("Geocoder", "About to enter from doInBackground");
            // Reverse geocode using location
            return geocoder.resolveAddressFromLocation(args[0], args[1]);
        }

        @Override
        protected void onPostExecute(String found) {
            Log.d("Geocoder", "About to enter from onPostExecute");
            // Update GUI with resolved string
            if (found != null) {
                Toast.makeText(getActivity(), found, Toast.LENGTH_LONG).show();
                location.put("resolved_address", found);
                new LocationBroker(getActivity()).updateOrInsert(location);
                //            getLoaderManager().restartLoader(0, null, LocationsListFragment.this);
                //locationText.setText(found.name);
            } else if (geocoder.lastException != null) {
                Toast.makeText(getActivity(), R.string.service_is_not_available, Toast.LENGTH_LONG).show();
            }
            //setActionEnabled(true);
            Log.d("Geocoder", "About to exit from onPostExecute");
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        BusProvider.getInstance().unregister(this);
    }

    @Subscribe
    public void onLoadFinished(LocationsLoadedEvent event) {
        final CursorAdapter a = (CursorAdapter) getListAdapter();
        a.swapCursor(event.cursor);
    }

    private int getItemPositionByAdapterId(final long id) {
        final ListAdapter adapter = getListAdapter();
        int i = 0;
        while (i < adapter.getCount() && id != adapter.getItemId(i++))
            ;

        return i == adapter.getCount() && id != adapter.getItemId(i - 1) ? -1 : --i;
    }

    @Subscribe
    public void onSelectionChanged(final LocationSelectedEvent event) {
        if (this != event.sender) {
            int position = getItemPositionByAdapterId(event.id);
            getListView().setItemChecked(position, true);
            getListView().setSelection(position);
        }
    }
}