org.isoron.uhabits.fragments.ListHabitsFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.isoron.uhabits.fragments.ListHabitsFragment.java

Source

/*
 * Copyright (C) 2016 ?linson Santos Xavier <isoron@gmail.com>
 *
 * This file is part of Loop Habit Tracker.
 *
 * Loop Habit Tracker 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.
 *
 * Loop Habit Tracker 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 org.isoron.uhabits.fragments;

import android.app.*;
import android.content.*;
import android.net.*;
import android.os.*;
import android.preference.*;
import android.support.annotation.*;
import android.support.v4.app.Fragment;
import android.support.v7.view.ActionMode;
import android.view.*;
import android.view.ContextMenu.*;
import android.view.View.*;
import android.widget.*;
import android.widget.AdapterView.*;

import com.mobeta.android.dslv.*;
import com.mobeta.android.dslv.DragSortListView.*;

import org.isoron.uhabits.*;
import org.isoron.uhabits.R;
import org.isoron.uhabits.commands.*;
import org.isoron.uhabits.dialogs.*;
import org.isoron.uhabits.helpers.*;
import org.isoron.uhabits.helpers.UIHelper.*;
import org.isoron.uhabits.loaders.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.tasks.*;

import java.io.*;
import java.util.*;

public class ListHabitsFragment extends Fragment
        implements OnSavedListener, OnItemClickListener, OnLongClickListener, DropListener, OnClickListener,
        HabitListLoader.Listener, AdapterView.OnItemLongClickListener, HabitSelectionCallback.Listener,
        ImportDataTask.Listener, ExportCSVTask.Listener, ExportDBTask.Listener {
    long lastLongClick = 0;
    private boolean isShortToggleEnabled;
    private boolean showArchived;

    private ActionMode actionMode;
    private HabitListAdapter adapter;
    private HabitListLoader loader;
    private HintManager hintManager;
    private ListHabitsHelper helper;
    private List<Integer> selectedPositions;
    private OnHabitClickListener habitClickListener;
    private BaseActivity activity;
    private SharedPreferences prefs;

    private DragSortListView listView;
    private LinearLayout llButtonsHeader;
    private ProgressBar progressBar;
    private View llEmpty;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list_habits_fragment, container, false);
        View llHint = view.findViewById(R.id.llHint);
        TextView tvStarEmpty = (TextView) view.findViewById(R.id.tvStarEmpty);
        listView = (DragSortListView) view.findViewById(R.id.listView);
        llButtonsHeader = (LinearLayout) view.findViewById(R.id.llButtonsHeader);
        llEmpty = view.findViewById(R.id.llEmpty);

        progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
        progressBar.setVisibility(View.GONE);

        selectedPositions = new LinkedList<>();
        loader = new HabitListLoader();
        helper = new ListHabitsHelper(activity, loader);
        hintManager = new HintManager(activity, llHint);

        loader.setListener(this);
        loader.setCheckmarkCount(helper.getButtonCount());

        llHint.setOnClickListener(this);
        tvStarEmpty.setTypeface(UIHelper.getFontAwesome(activity));

        adapter = new HabitListAdapter(getActivity(), loader);
        adapter.setSelectedPositions(selectedPositions);
        adapter.setOnCheckmarkClickListener(this);
        adapter.setOnCheckmarkLongClickListener(this);

        DragSortListView.DragListener dragListener = new HabitsDragListener();
        DragSortController dragSortController = new HabitsDragSortController();

        listView.setAdapter(adapter);
        listView.setOnItemClickListener(this);
        listView.setOnItemLongClickListener(this);
        listView.setDropListener(this);
        listView.setDragListener(dragListener);
        listView.setFloatViewManager(dragSortController);
        listView.setDragEnabled(true);
        listView.setLongClickable(true);

        if (savedInstanceState != null) {
            EditHabitDialogFragment frag = (EditHabitDialogFragment) getFragmentManager()
                    .findFragmentByTag("editHabit");
            if (frag != null)
                frag.setOnSavedListener(this);
        }

        setHasOptionsMenu(true);
        return view;
    }

    @Override
    @SuppressWarnings("deprecation")
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.activity = (BaseActivity) activity;

        habitClickListener = (OnHabitClickListener) activity;
        prefs = PreferenceManager.getDefaultSharedPreferences(activity);
    }

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

        loader.updateAllHabits(true);
        helper.updateEmptyMessage(llEmpty);
        helper.updateHeader(llButtonsHeader);
        hintManager.showHintIfAppropriate();

        adapter.notifyDataSetChanged();
        isShortToggleEnabled = prefs.getBoolean("pref_short_toggle", false);
    }

    @Override
    public void onLoadFinished() {
        adapter.notifyDataSetChanged();
        helper.updateEmptyMessage(llEmpty);
    }

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

        MenuItem showArchivedItem = menu.findItem(R.id.action_show_archived);
        showArchivedItem.setChecked(showArchived);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, view, menuInfo);
        getActivity().getMenuInflater().inflate(R.menu.list_habits_context, menu);

        AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
        final Habit habit = loader.habits.get(info.id);

        if (habit.isArchived())
            menu.findItem(R.id.action_archive_habit).setVisible(false);
        else
            menu.findItem(R.id.action_unarchive_habit).setVisible(false);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_add: {
            EditHabitDialogFragment frag = EditHabitDialogFragment.createHabitFragment();
            frag.setOnSavedListener(this);
            frag.show(getFragmentManager(), "editHabit");
            return true;
        }

        case R.id.action_show_archived: {
            showArchived = !showArchived;
            loader.setIncludeArchived(showArchived);
            loader.updateAllHabits(true);
            activity.invalidateOptionsMenu();
            return true;
        }

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onItemClick(AdapterView parent, View view, int position, long id) {
        if (new Date().getTime() - lastLongClick < 1000)
            return;

        if (actionMode == null) {
            Habit habit = loader.habitsList.get(position);
            habitClickListener.onHabitClicked(habit);
        } else {
            int k = selectedPositions.indexOf(position);
            if (k < 0)
                selectedPositions.add(position);
            else
                selectedPositions.remove(k);

            if (selectedPositions.isEmpty())
                actionMode.finish();
            else
                actionMode.invalidate();

            adapter.notifyDataSetChanged();
        }
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        selectItem(position);
        return true;
    }

    private void selectItem(int position) {
        if (!selectedPositions.contains(position))
            selectedPositions.add(position);

        adapter.notifyDataSetChanged();

        if (actionMode == null) {
            HabitSelectionCallback callback = new HabitSelectionCallback(activity, loader);
            callback.setSelectedPositions(selectedPositions);
            callback.setProgressBar(progressBar);
            callback.setOnSavedListener(this);
            callback.setListener(this);

            actionMode = activity.startSupportActionMode(callback);
        }

        if (actionMode != null)
            actionMode.invalidate();
    }

    @Override
    public void onSaved(Command command, Object savedObject) {
        Habit h = (Habit) savedObject;

        if (h == null)
            activity.executeCommand(command, null);
        else
            activity.executeCommand(command, h.getId());
        adapter.notifyDataSetChanged();

        ReminderHelper.createReminderAlarms(activity);

        if (actionMode != null)
            actionMode.finish();
    }

    @Override
    public boolean onLongClick(View v) {
        lastLongClick = new Date().getTime();

        switch (v.getId()) {
        case R.id.tvCheck:
            onCheckmarkLongClick(v);
            return true;
        }

        return false;
    }

    private void onCheckmarkLongClick(View v) {
        if (isShortToggleEnabled)
            return;

        toggleCheck(v);
    }

    private void toggleCheck(View v) {
        Long id = helper.getHabitIdFromCheckmarkView(v);
        Habit habit = loader.habits.get(id);
        if (habit == null)
            return;

        float x = v.getX() + v.getWidth() / 2.0f + ((View) v.getParent()).getX();
        float y = v.getY() + v.getHeight() / 2.0f + ((View) v.getParent()).getY();
        helper.triggerRipple((View) v.getParent().getParent(), x, y);

        listView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
        helper.toggleCheckmarkView(v, habit);

        long timestamp = helper.getTimestampFromCheckmarkView(v);
        executeCommand(new ToggleRepetitionCommand(habit, timestamp), habit.getId());
    }

    private void executeCommand(Command c, Long refreshKey) {
        activity.executeCommand(c, refreshKey);
    }

    @Override
    public void drop(int from, int to) {
        if (from == to)
            return;
        if (actionMode != null)
            actionMode.finish();

        loader.reorder(from, to);
        adapter.notifyDataSetChanged();
        loader.updateAllHabits(false);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.tvCheck:
            if (isShortToggleEnabled)
                toggleCheck(v);
            else
                activity.showToast(R.string.long_press_to_toggle);
            break;

        case R.id.llHint:
            hintManager.dismissHint();
            break;
        }
    }

    public void onPostExecuteCommand(Long refreshKey) {
        if (refreshKey == null)
            loader.updateAllHabits(true);
        else
            loader.updateHabit(refreshKey);
    }

    @Override
    public void onActionModeDestroyed(ActionMode mode) {
        actionMode = null;
        selectedPositions.clear();
        adapter.notifyDataSetChanged();
        listView.setDragEnabled(true);
    }

    public interface OnHabitClickListener {
        void onHabitClicked(Habit habit);
    }

    private class HabitsDragSortController extends DragSortController {
        public HabitsDragSortController() {
            super(ListHabitsFragment.this.listView);
            setRemoveEnabled(false);
        }

        @Override
        public View onCreateFloatView(int position) {
            return adapter.getView(position, null, null);
        }

        @Override
        public void onDestroyFloatView(View floatView) {
        }
    }

    private class HabitsDragListener implements DragSortListView.DragListener {
        @Override
        public void drag(int from, int to) {
        }

        @Override
        public void startDrag(int position) {
            selectItem(position);
        }
    }

    public void showImportDialog() {
        File dir = DatabaseHelper.getFilesDir(null);
        if (dir == null) {
            activity.showToast(R.string.could_not_import);
            return;
        }

        FilePickerDialog picker = new FilePickerDialog(activity, dir);
        picker.setListener(new FilePickerDialog.OnFileSelectedListener() {
            @Override
            public void onFileSelected(File file) {
                ImportDataTask task = new ImportDataTask(file, progressBar);
                task.setListener(ListHabitsFragment.this);
                task.execute();
            }
        });

        picker.show();
    }

    @Override
    public void onImportFinished(int result) {
        switch (result) {
        case ImportDataTask.SUCCESS:
            loader.updateAllHabits(true);
            activity.showToast(R.string.habits_imported);
            break;

        case ImportDataTask.NOT_RECOGNIZED:
            activity.showToast(R.string.file_not_recognized);
            break;

        default:
            activity.showToast(R.string.could_not_import);
            break;
        }
    }

    public void exportAllHabits() {
        ExportCSVTask task = new ExportCSVTask(Habit.getAll(true), progressBar);
        task.setListener(this);
        task.execute();
    }

    @Override
    public void onExportCSVFinished(@Nullable String archiveFilename) {
        if (archiveFilename != null) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("application/zip");
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(archiveFilename)));
            activity.startActivity(intent);
        } else {
            activity.showToast(R.string.could_not_export);
        }
    }

    public void exportDB() {
        ExportDBTask task = new ExportDBTask(progressBar);
        task.setListener(this);
        task.execute();
    }

    @Override
    public void onExportDBFinished(@Nullable String filename) {
        if (filename != null) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("application/octet-stream");
            intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(filename)));
            activity.startActivity(intent);
        } else {
            activity.showToast(R.string.could_not_export);
        }
    }
}