com.money.manager.ex.recurring.transactions.RecurringTransactionListFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.money.manager.ex.recurring.transactions.RecurringTransactionListFragment.java

Source

/*
 * Copyright (C) 2012-2016 The Android Money Manager Ex Project Team
 *
 * This program 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.
 *
 * This program 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 com.money.manager.ex.recurring.transactions;

import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.mikepenz.mmex_icon_font_typeface_library.MMXIconFont;
import com.money.manager.ex.MoneyManagerApplication;
import com.money.manager.ex.common.MmxCursorLoader;
import com.money.manager.ex.datalayer.Select;
import com.money.manager.ex.log.ExceptionHandler;
import com.money.manager.ex.core.UIHelper;
import com.money.manager.ex.datalayer.RecurringTransactionRepository;
import com.money.manager.ex.domainmodel.Account;
import com.money.manager.ex.domainmodel.RecurringTransaction;
import com.money.manager.ex.transactions.CheckingTransactionEditActivity;
import com.money.manager.ex.R;
import com.money.manager.ex.adapter.AllDataAdapter;
import com.money.manager.ex.servicelayer.RecurringTransactionService;
import com.money.manager.ex.transactions.EditTransactionActivityConstants;
import com.money.manager.ex.database.QueryBillDeposits;
import com.money.manager.ex.common.BaseListFragment;
import com.money.manager.ex.utils.MmxDateTimeUtils;
import com.roomorama.caldroid.CaldroidFragment;
import com.roomorama.caldroid.CaldroidListener;
import com.shamanland.fonticon.FontIconDrawable;

import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import javax.inject.Inject;

import dagger.Lazy;

/**
 * The recurring transactions list fragment.
 * Includes floating action button.
 */
public class RecurringTransactionListFragment extends BaseListFragment
        implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final int REQUEST_ADD_REPEATING_TRANSACTION = 1001;
    private static final int REQUEST_ADD_TRANSACTION = 1002;
    private static final int REQUEST_EDIT_REPEATING_TRANSACTION = 1003;

    private static final int ID_LOADER_REPEATING = 0;

    private static QueryBillDeposits mBillDeposits;

    @Inject
    Lazy<MmxDateTimeUtils> dateTimeUtilsLazy;

    // filter
    private String mCurFilter;

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

        // create a object query
        mBillDeposits = new QueryBillDeposits(getActivity());
        // set list view
        setEmptyText(getActivity().getResources().getString(R.string.repeating_empty_transaction));
        setHasOptionsMenu(true);
        registerForContextMenu(getListView());
        getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
        UIHelper uiHelper = new UIHelper(getActivity());
        getListView().setDivider(new ColorDrawable(uiHelper.resolveAttribute(R.attr.theme_background_color)));

        setListShown(false);

        getLoaderManager().initLoader(ID_LOADER_REPEATING, null, this);

        // show floating button.
        setFloatingActionButtonVisible(true);
        attachFloatingActionButtonToListView();
    }

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

        MoneyManagerApplication.getApp().iocComponent.inject(this);

        setHasOptionsMenu(true);
    }

    @Override
    public void onFloatingActionButtonClicked() {
        // create new recurring transaction.
        startRecurringTransactionEditActivity(null, REQUEST_ADD_REPEATING_TRANSACTION);
    }

    // Menu

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

        //        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_item_calendar, menu);
        MenuItem calendar = menu.findItem(R.id.menuCalendar);
        if (calendar != null) {
            Drawable icon = new UIHelper(getActivity()).getIcon(MMXIconFont.Icon.mmx_calendar);
            calendar.setIcon(icon);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // handle calendar
        switch (item.getItemId()) {
        case R.id.menuCalendar:
            showCaldroidFragment();
            break;
        }
        return super.onOptionsItemSelected(item);
    }

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

        // show context menu here.
        getActivity().openContextMenu(v);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        // take a cursor and move to position
        Cursor cursor = ((AllDataAdapter) getListAdapter()).getCursor();
        if (cursor != null) {
            cursor.moveToPosition(info.position);
            // set title and inflate menu
            menu.setHeaderTitle(getActivity().getTitle());
            getActivity().getMenuInflater().inflate(R.menu.contextmenu_repeating_transactions, menu);
        }
    }

    @Override
    public boolean onContextItemSelected(android.view.MenuItem item) {

        ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo();
        if (menuInfo == null) {
            String errorMessage = "no context menu info";
            Log.w(this.getClass().getSimpleName(), errorMessage);
            ExceptionHandler handler = new ExceptionHandler(getActivity(), this);
            handler.showMessage("no context menu info");
            return false;
        }
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;

        int menuItemId = item.getItemId();
        int transactionId = (int) info.id;

        switch (menuItemId) {
        case R.id.menu_enter_next_occurrence:
            showCreateTransactionActivity(transactionId);
            break;

        case R.id.menu_skip_next_occurrence:
            confirmSkip(transactionId);
            break;

        case R.id.menu_edit:
            startRecurringTransactionEditActivity(transactionId, REQUEST_EDIT_REPEATING_TRANSACTION);
            break;

        case R.id.menu_delete:
            confirmDelete(transactionId);
            break;
        }

        return false;
    }

    // Loader callbacks.

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        switch (id) {
        case ID_LOADER_REPEATING:
            String select = null;
            if (!TextUtils.isEmpty(mCurFilter)) {
                select = Account.ACCOUNTNAME + " LIKE '" + mCurFilter + "%'";
            }
            Select query = new Select(mBillDeposits.getAllColumns()).where(select)
                    .orderBy(QueryBillDeposits.NEXTOCCURRENCEDATE);

            return new MmxCursorLoader(getActivity(), mBillDeposits.getUri(), query);
        }

        return null;
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        switch (loader.getId()) {
        case ID_LOADER_REPEATING:
            AllDataAdapter adapter = (AllDataAdapter) getListAdapter();
            if (adapter != null) {
                //                    adapter.swapCursor(null);
                adapter.changeCursor(null);
            }
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        switch (loader.getId()) {
        case ID_LOADER_REPEATING:
            if (data == null)
                return;

            AllDataAdapter adapter = new AllDataAdapter(getActivity(), data,
                    AllDataAdapter.TypeCursor.RECURRINGTRANSACTION);
            setListAdapter(adapter);

            if (isResumed()) {
                setListShown(true);
                if (data.getCount() <= 0 && getFloatingActionButton() != null)
                    getFloatingActionButton().show(true);
            } else {
                setListShownNoAnimation(true);
            }
        }
    }

    // Other

    @Override
    public boolean onQueryTextChange(String newText) {
        // Called when the action bar search text has changed. Update
        // the search filter, and restart the loader to do a new query
        // with this filter.
        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(ID_LOADER_REPEATING, null, this);
        return true;
    }

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

        if (resultCode == RecurringTransactionListActivity.RESULT_OK) {
            //                switch (requestCode) {
            //                    case REQUEST_ADD_REPEATING_TRANSACTION:
            //                        break;
            //                    case REQUEST_ADD_TRANSACTION:
            //                        break;
            //                    case REQUEST_EDIT_REPEATING_TRANSACTION:
            //                        break;
            //                }
            // Always reload the activity?
            getLoaderManager().restartLoader(ID_LOADER_REPEATING, null, this);
        }
    }

    @Override
    public String getSubTitle() {
        return getString(R.string.recurring_transactions);
    }

    // private

    private void confirmDelete(final int id) {
        // create alert binaryDialog
        new MaterialDialog.Builder(getContext()).title(R.string.delete_repeating_transaction)
                .icon(FontIconDrawable.inflate(getContext(), R.xml.ic_question)).content(R.string.confirmDelete)
                .positiveText(android.R.string.ok).onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        RecurringTransactionService recurringTransaction = new RecurringTransactionService(id,
                                getActivity());
                        recurringTransaction.delete();

                        // restart loader
                        getLoaderManager().restartLoader(ID_LOADER_REPEATING, null,
                                RecurringTransactionListFragment.this);
                    }
                }).negativeText(android.R.string.cancel).onNegative(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        dialog.cancel();
                    }
                }).build().show();
    }

    private void confirmSkip(final int id) {
        new MaterialDialog.Builder(getContext()).title(R.string.skip_next_occurrence)
                .icon(FontIconDrawable.inflate(getContext(), R.xml.ic_question))
                .content(R.string.skip_next_occurrence_confirmation).positiveText(android.R.string.ok)
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        RecurringTransactionService recurringTransaction = new RecurringTransactionService(id,
                                getActivity());
                        recurringTransaction.moveNextOccurrence();
                        getLoaderManager().restartLoader(ID_LOADER_REPEATING, null,
                                RecurringTransactionListFragment.this);
                    }
                }).negativeText(android.R.string.cancel).onNegative(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        dialog.cancel();
                    }
                }).build().show();
    }

    private void showCaldroidFragment() {
        Locale appLocale = MoneyManagerApplication.getApp().getAppLocale();
        CaldroidFragment caldroidFragment = new CaldroidFragment();

        // Customization
        Bundle args = new Bundle();
        Calendar cal = Calendar.getInstance(appLocale);
        args.putInt(CaldroidFragment.MONTH, cal.get(Calendar.MONTH) + 1);
        args.putInt(CaldroidFragment.YEAR, cal.get(Calendar.YEAR));
        args.putInt(CaldroidFragment.START_DAY_OF_WEEK, dateTimeUtilsLazy.get().getFirstDayOfWeek());
        if (new UIHelper(getActivity()).isUsingDarkTheme()) {
            args.putInt(CaldroidFragment.THEME_RESOURCE, com.caldroid.R.style.CaldroidDefaultDark);
        }
        // disable switching month for now.
        args.putBoolean(CaldroidFragment.SHOW_NAVIGATION_ARROWS, Boolean.FALSE);
        args.putBoolean(CaldroidFragment.ENABLE_SWIPE, Boolean.FALSE);
        caldroidFragment.setArguments(args);

        // add different background for dates with events.
        showDatesWithEvents(caldroidFragment);

        // behaviour
        caldroidFragment.setCaldroidListener(getCalendarListener());

        android.support.v4.app.FragmentTransaction t = getActivity().getSupportFragmentManager().beginTransaction();
        t.replace(R.id.fragmentMain, caldroidFragment);
        t.addToBackStack(null);
        t.commit();
    }

    private CaldroidListener getCalendarListener() {
        return new CaldroidListener() {

            @Override
            public void onSelectDate(Date date, View view) {
                //                fragment.setCalendarDate(date);
                // todo show the recurring transactions on this date.
            }

            @Override
            public void onChangeMonth(int month, int year) {
            }

            @Override
            public void onLongClickDate(Date date, View view) {
            }

            @Override
            public void onCaldroidViewCreated() {
            }

        };
    }

    private void showDatesWithEvents(CaldroidFragment caldroid) {
        ListAdapter adapter = getListAdapter();
        int count = adapter.getCount();
        ColorDrawable orange = new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.holo_orange_dark));
        RecurringTransaction tx = RecurringTransaction.createInstance();

        for (int i = 0; i < count; i++) {
            Cursor cursor = (Cursor) adapter.getItem(i);
            tx.loadFromCursor(cursor);

            caldroid.setBackgroundDrawableForDate(orange, tx.getPaymentDate());
        }
    }

    private void showCreateTransactionActivity(int recurringTransactionId) {
        RecurringTransactionRepository repo = new RecurringTransactionRepository(getActivity());
        RecurringTransaction tx = repo.load(recurringTransactionId);
        if (tx == null)
            return;

        Intent intent = new Intent(getActivity(), CheckingTransactionEditActivity.class);
        intent.setAction(Intent.ACTION_INSERT);
        intent.putExtra(EditTransactionActivityConstants.KEY_BDID_ID, recurringTransactionId);
        // start for insert new transaction
        startActivityForResult(intent, REQUEST_ADD_TRANSACTION);
    }

    /**
     * start RepeatingTransaction for insert or edit transaction
     *
     * @param billDepositsId Id of the recurring transaction.
     * @param purposeCode       Code that indicates why we are opening the editor.
     *                          example: REQUEST_ADD_REPEATING_TRANSACTION
     */
    private void startRecurringTransactionEditActivity(Integer billDepositsId, int purposeCode) {
        // create intent, set Bill Deposits ID
        Intent intent = new Intent(getActivity(), RecurringTransactionEditActivity.class);
        // check transId not null
        if (billDepositsId != null) {
            intent.putExtra(RecurringTransactionEditActivity.KEY_BILL_DEPOSITS_ID, billDepositsId);
            intent.setAction(Intent.ACTION_EDIT);
        } else {
            intent.setAction(Intent.ACTION_INSERT);
        }
        // launch activity
        startActivityForResult(intent, purposeCode);
    }
}