com.androzic.waypoint.WaypointList.java Source code

Java tutorial

Introduction

Here is the source code for com.androzic.waypoint.WaypointList.java

Source

/*
 * Androzic - android navigation client that uses OziExplorer maps (ozf2, ozfx3).
 * Copyright (C) 2010-2014 Andrey Novikov <http://andreynovikov.info/>
 * 
 * This file is part of Androzic application.
 * 
 * Androzic 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.
 * 
 * Androzic 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 Androzic. If not, see <http://www.gnu.org/licenses/>.
 */

package com.androzic.waypoint;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.ListFragment;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.androzic.Androzic;
import com.androzic.R;
import com.androzic.data.Waypoint;
import com.androzic.data.WaypointSet;
import com.androzic.ui.FileListDialog;
import com.androzic.ui.MarkerFactory;
import com.androzic.ui.TooltipManager;
import com.androzic.util.Geo;
import com.androzic.util.StringFormatter;
import com.daimajia.swipe.adapters.BaseSwipeAdapter;
import com.daimajia.swipe.util.Attributes;

public class WaypointList extends ListFragment implements FileListDialog.OnFileListDialogListener {
    public static final String TAG = "WaypointList";

    private static final int DIALOG_WAYPOINT_PROJECT = 1;

    private OnWaypointActionListener waypointActionsCallback;

    private WaypointListAdapter adapter;

    private int mSortMode = -1;

    private Handler tooltipCallback = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.list_with_empty_view_and_fab, container, false);
    }

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

        TextView emptyView = (TextView) getListView().getEmptyView();
        if (emptyView != null)
            emptyView.setText(R.string.msg_empty_waypoint_list);

        FloatingActionButton fab = (FloatingActionButton) getView().findViewById(R.id.actionButton);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                waypointActionsCallback.onWaypointEdit(new Waypoint());
            }
        });

        adapter = new WaypointListAdapter(getActivity());
        setListAdapter(adapter);
        adapter.setMode(Attributes.Mode.Single);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            waypointActionsCallback = (OnWaypointActionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnWaypointActionListener");
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        Androzic application = Androzic.getApplication();
        application.saveWaypoints();

        application.registerReceiver(broadcastReceiver, new IntentFilter(Androzic.BROADCAST_WAYPOINT_ADDED));
        application.registerReceiver(broadcastReceiver, new IntentFilter(Androzic.BROADCAST_WAYPOINT_REMOVED));

        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(application);
        mSortMode = settings.getInt(getString(R.string.wpt_sort), 0);
        adapter.sort(mSortMode);
    }

    @Override
    public void onResume() {
        super.onResume();
        adapter.notifyDataSetChanged();
        tooltipCallback.postDelayed(showTooltip, TooltipManager.TOOLTIP_DELAY);
    }

    @Override
    public void onPause() {
        super.onPause();
        // Stop showing tooltips
        tooltipCallback.removeCallbacks(showTooltip);
        TooltipManager.dismiss();
    }

    @Override
    public void onStop() {
        super.onStop();

        Androzic application = Androzic.getApplication();
        application.unregisterReceiver(broadcastReceiver);
    }

    @Override
    public void onListItemClick(ListView lv, View v, int position, long id) {
        Androzic application = Androzic.getApplication();
        Waypoint waypoint = application.getWaypoint(position);
        waypointActionsCallback.onWaypointDetails(waypoint);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.waypointlist_menu, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public void onPrepareOptionsMenu(final Menu menu) {
        Androzic application = Androzic.getApplication();

        MenuItem sortItem = menu.findItem(mSortMode == 0 ? R.id.action_sort_alpha : R.id.action_sort_size);
        sortItem.setChecked(true);
        Editor editor = PreferenceManager.getDefaultSharedPreferences(application).edit();
        editor.putInt(getString(R.string.wpt_sort), mSortMode);
        editor.commit();

        List<WaypointSet> sets = application.getWaypointSets();
        if (sets.size() > 1) {
            menu.setGroupVisible(R.id.group_sets, true);
            menu.removeGroup(R.id.group_sets);
            for (int i = 1; i < sets.size(); i++)
                menu.add(R.id.group_sets, i, Menu.NONE, sets.get(i).name).setChecked(true);
            menu.setGroupCheckable(R.id.group_sets, true, false);
        }
    }

    @SuppressLint("InflateParams")
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        final FragmentActivity activity = getActivity();
        switch (item.getItemId()) {
        case R.id.action_sort_alpha:
            adapter.sort(0);
            mSortMode = 0;
            activity.supportInvalidateOptionsMenu();
            return true;
        case R.id.action_sort_size:
            adapter.sort(1);
            mSortMode = 1;
            activity.supportInvalidateOptionsMenu();
            return true;
        case R.id.action_load_waypoints:
            WaypointFileList fileListDialog = new WaypointFileList(this);
            fileListDialog.show(getFragmentManager(), "dialog");
            return true;
        case R.id.action_new_waypoint_set:
            View view = getActivity().getLayoutInflater().inflate(R.layout.dlg_filename, null);
            final EditText textEntryView = (EditText) view.findViewById(R.id.name_text);
            new AlertDialog.Builder(activity).setTitle(R.string.waypointset).setView(view)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            String name = textEntryView.getText().toString();
                            if (!"".equals(name)) {
                                WaypointSet set = new WaypointSet(name);
                                Androzic application = Androzic.getApplication();
                                application.addWaypointSet(set);
                                activity.supportInvalidateOptionsMenu();
                                adapter.notifyDataSetChanged();
                            }
                        }
                    }).setNegativeButton(R.string.cancel, null).create().show();
            return true;
        case R.id.action_project_waypoint:
            WaypointProject waypointProjectDialog = new WaypointProject();
            waypointProjectDialog.setTargetFragment(this, DIALOG_WAYPOINT_PROJECT);
            waypointProjectDialog.show(getFragmentManager(), "dialog");
            return true;
        default:
            Androzic application = Androzic.getApplication();
            try {
                application.getWaypointSets().get(item.getItemId());
                application.removeWaypointSet(item.getItemId());
                activity.supportInvalidateOptionsMenu();
                adapter.notifyDataSetChanged();
            } catch (IndexOutOfBoundsException e) {
                return super.onOptionsItemSelected(item);
            }
            return true;
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
        case DIALOG_WAYPOINT_PROJECT:
            adapter.notifyDataSetChanged();
            break;
        }
    }

    final private Runnable showTooltip = new Runnable() {
        @Override
        public void run() {
            long tooltip = TooltipManager.getTooltip(TAG);
            if (tooltip == 0L)
                return;
            if (tooltip == TooltipManager.TOOLTIP_DATA_LIST && !adapter.isEmpty())
                TooltipManager.showTooltip(tooltip, getListView().getChildAt(0));
            tooltipCallback.postDelayed(this, TooltipManager.TOOLTIP_PERIOD);
        }
    };

    @Override
    public void onFileLoaded(int count) {
        adapter.notifyDataSetChanged();
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            adapter.sort(mSortMode);
            adapter.notifyDataSetChanged();
        }
    };

    public class WaypointListAdapter extends BaseSwipeAdapter implements View.OnClickListener {
        private LayoutInflater mInflater;
        private int mItemLayout;
        private float mDensity;
        private Paint mBorderPaint;
        private Paint mFillPaint;
        private int mPointWidth;
        private Androzic application;
        private double[] loc;

        public WaypointListAdapter(Context context) {
            mItemLayout = R.layout.list_item_waypoint_swipe;
            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            mDensity = context.getResources().getDisplayMetrics().density;

            SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);

            mPointWidth = settings.getInt(context.getString(R.string.pref_waypoint_width),
                    context.getResources().getInteger(R.integer.def_waypoint_width));
            mFillPaint = new Paint();
            mFillPaint.setAntiAlias(false);
            mFillPaint.setStrokeWidth(1);
            mFillPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mFillPaint.setColor(settings.getInt(context.getString(R.string.pref_waypoint_color),
                    context.getResources().getColor(R.color.waypoint)));
            mBorderPaint = new Paint();
            mBorderPaint.setAntiAlias(false);
            mBorderPaint.setStrokeWidth(1);
            mBorderPaint.setStyle(Paint.Style.STROKE);
            mBorderPaint.setColor(context.getResources().getColor(R.color.waypointtext));
            mBorderPaint.setColor(settings.getInt(context.getString(R.string.pref_waypoint_namecolor),
                    context.getResources().getColor(R.color.waypointtext)));

            application = Androzic.getApplication();
            loc = application.getLocation();
        }

        @Override
        public Waypoint getItem(int position) {
            return application.getWaypoint(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public int getCount() {
            return application.getWaypoints().size();
        }

        @Override
        public int getSwipeLayoutResourceId(int position) {
            return R.id.swipe;
        }

        @Override
        public View generateView(int position, ViewGroup parent) {
            View convertView = mInflater.inflate(mItemLayout, parent, false);
            return convertView;
        }

        @Override
        public void fillValues(int position, View convertView) {
            WaypointItemHolder waypointHolder = null;
            Waypoint wpt = (Waypoint) getItem(position);

            waypointHolder = (WaypointItemHolder) convertView.getTag();

            if (waypointHolder == null) {
                waypointHolder = new WaypointItemHolder();
                waypointHolder.icon = (ImageView) convertView.findViewById(R.id.icon);
                waypointHolder.actionView = convertView.findViewById(R.id.action_view);
                waypointHolder.actionNavigate = convertView.findViewById(R.id.action_navigate);
                waypointHolder.actionEdit = convertView.findViewById(R.id.action_edit);
                waypointHolder.actionShare = convertView.findViewById(R.id.action_share);
                waypointHolder.actionDelete = convertView.findViewById(R.id.action_delete);
                waypointHolder.name = (TextView) convertView.findViewById(R.id.name);
                waypointHolder.coordinates = (TextView) convertView.findViewById(R.id.coordinates);
                waypointHolder.distance = (TextView) convertView.findViewById(R.id.distance);
                convertView.setTag(waypointHolder);
            }

            waypointHolder.actionView.setOnClickListener(this);
            waypointHolder.actionNavigate.setOnClickListener(this);
            waypointHolder.actionEdit.setOnClickListener(this);
            waypointHolder.actionShare.setOnClickListener(this);
            waypointHolder.actionDelete.setOnClickListener(this);
            waypointHolder.name.setText(wpt.name);

            String coordinates = StringFormatter.coordinates(" ", wpt.latitude, wpt.longitude);
            waypointHolder.coordinates.setText(coordinates);

            double dist = Geo.distance(loc[0], loc[1], wpt.latitude, wpt.longitude);
            double bearing = Geo.bearing(loc[0], loc[1], wpt.latitude, wpt.longitude);
            String distance = StringFormatter.distanceH(dist) + " " + StringFormatter.bearingSimpleH(bearing);
            waypointHolder.distance.setText(distance);

            Bitmap b = null;
            if (wpt.drawImage) {
                b = MarkerFactory.getIcon(application, wpt.marker);
            }

            int border = (int) (8 * mDensity);
            int sizeX = (int) (24 * mDensity);
            int sizeY = (int) (18 * mDensity);
            Bitmap bm = Bitmap.createBitmap(sizeX + border * 2, sizeY + border * 2, Config.ARGB_8888);
            bm.eraseColor(Color.TRANSPARENT);
            Canvas bc = new Canvas(bm);
            if (b != null) {
                int iconWidth = b.getWidth();
                int iconHeight = b.getHeight();

                Matrix matrix = new Matrix();
                if (iconWidth > sizeX || iconHeight > sizeY) {
                    float scaleX = (float) (1. * sizeX / iconWidth);
                    float scaleY = (float) (1. * sizeY / iconHeight);
                    float scale = scaleX > scaleY ? scaleX : scaleY;
                    matrix.postScale(scale, scale);
                    iconWidth = (int) (iconWidth * scale);
                    iconHeight = (int) (iconHeight * scale);
                }

                matrix.postTranslate(border + (sizeX - iconWidth) / 2, border + (sizeY - iconHeight) / 2);
                bc.drawBitmap(b, matrix, null);
                b.recycle();
            } else {
                int tc = 0, bgc = 0;
                if (wpt.textcolor != Integer.MIN_VALUE) {
                    tc = mBorderPaint.getColor();
                    mBorderPaint.setColor(wpt.textcolor);
                }
                if (wpt.backcolor != Integer.MIN_VALUE) {
                    bgc = mFillPaint.getColor();
                    mFillPaint.setColor(wpt.backcolor);
                }
                Rect rect = new Rect(0, 0, mPointWidth, mPointWidth);
                bc.translate(border + (sizeX - mPointWidth) / 2, border + (sizeY - mPointWidth) / 2);
                bc.drawRect(rect, mBorderPaint);
                rect.inset(1, 1);
                bc.drawRect(rect, mFillPaint);
                if (wpt.textcolor != Integer.MIN_VALUE) {
                    mBorderPaint.setColor(tc);
                }
                if (wpt.backcolor != Integer.MIN_VALUE) {
                    mFillPaint.setColor(bgc);
                }
            }
            BitmapDrawable drawable = (BitmapDrawable) waypointHolder.icon.getDrawable();
            if (drawable != null) {
                b = drawable.getBitmap();
                if (b != null)
                    b.recycle();
            }
            waypointHolder.icon.setImageBitmap(bm);
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        public void sort(final int type) {
            Collections.sort(application.getWaypoints(), new Comparator<Waypoint>() {
                @Override
                public int compare(Waypoint o1, Waypoint o2) {
                    if (type == 1) {
                        // TODO cache distances
                        double dist1 = Geo.distance(loc[0], loc[1], o1.latitude, o1.longitude);
                        double dist2 = Geo.distance(loc[0], loc[1], o2.latitude, o2.longitude);
                        return (Double.compare(dist1, dist2));
                    } else {
                        return (o1.name.compareToIgnoreCase(o2.name));
                    }
                }
            });
            notifyDataSetChanged();
        }

        @Override
        public void onClick(View v) {
            ListView lv = getListView();
            int position = lv.getPositionForView((View) v.getParent());
            closeItem(position);
            Waypoint waypoint = getItem(position);

            switch (v.getId()) {
            case R.id.action_view:
                waypointActionsCallback.onWaypointView(waypoint);
                break;
            case R.id.action_navigate:
                waypointActionsCallback.onWaypointNavigate(waypoint);
                break;
            case R.id.action_edit:
                waypointActionsCallback.onWaypointEdit(waypoint);
                break;
            case R.id.action_share:
                waypointActionsCallback.onWaypointShare(waypoint);
                break;
            case R.id.action_delete:
                waypointActionsCallback.onWaypointRemove(waypoint);
                adapter.notifyDataSetChanged();
                break;
            }
        }
    }

    private static class WaypointItemHolder {
        ImageView icon;
        TextView name;
        TextView coordinates;
        TextView distance;
        View actionView;
        View actionNavigate;
        View actionEdit;
        View actionShare;
        View actionDelete;
    }
}