org.totschnig.myexpenses.fragment.SplitPartList.java Source code

Java tutorial

Introduction

Here is the source code for org.totschnig.myexpenses.fragment.SplitPartList.java

Source

/*   This file is part of My Expenses.
 *   My Expenses 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.
 *
 *   My Expenses 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 My Expenses.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.totschnig.myexpenses.fragment;

import static org.totschnig.myexpenses.provider.DatabaseConstants.*;

import org.totschnig.myexpenses.R;
import org.totschnig.myexpenses.activity.ExpenseEdit;
import org.totschnig.myexpenses.activity.MyExpenses;
import org.totschnig.myexpenses.activity.ProtectedFragmentActivity;
import org.totschnig.myexpenses.adapter.SplitPartAdapter;
import org.totschnig.myexpenses.model.Account;
import org.totschnig.myexpenses.model.Money;
import org.totschnig.myexpenses.provider.TransactionProvider;
import org.totschnig.myexpenses.task.TaskExecutionFragment;
import org.totschnig.myexpenses.util.Utils;

import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;

import icepick.Icepick;
import icepick.State;

//TODO: consider moving to ListFragment
public class SplitPartList extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
    //
    SplitPartAdapter mAdapter;
    private TextView balanceTv;
    private long transactionSum = 0;
    private Money unsplitAmount;
    private FloatingActionButton fab;

    @State
    long parentId;

    @State
    long accountId;

    public static SplitPartList newInstance(Long parentId, Long accountId) {
        SplitPartList f = new SplitPartList();
        Bundle bundle = new Bundle();
        bundle.putLong(KEY_PARENTID, parentId);
        bundle.putLong(KEY_ACCOUNTID, accountId);
        f.setArguments(bundle);
        return f;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        setRetainInstance(true);
        if (savedInstanceState == null) {
            parentId = getArguments().getLong(KEY_PARENTID);
            accountId = getArguments().getLong(KEY_ACCOUNTID);
        } else {
            Icepick.restoreInstanceState(this, savedInstanceState);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Icepick.saveInstanceState(this, outState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final FragmentActivity ctx = getActivity();
        View v = inflater.inflate(R.layout.split_parts_list, container, false);
        View emptyView = v.findViewById(R.id.empty);
        balanceTv = (TextView) v.findViewById(R.id.end);

        ListView lv = (ListView) v.findViewById(R.id.list);
        // Create an array to specify the fields we want to display in the list
        String[] from = new String[] { KEY_LABEL_MAIN, KEY_AMOUNT };

        // and an array of the fields we want to bind those fields to 
        int[] to = new int[] { R.id.category, R.id.amount };

        requireLoaders();
        // Now create a simple cursor adapter and set it to display
        final Account account = Account.getInstanceFromDb(accountId);
        mAdapter = new SplitPartAdapter(ctx, R.layout.split_part_row, null, from, to, 0, account.currency);
        lv.setAdapter(mAdapter);
        lv.setEmptyView(emptyView);
        lv.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> a, View v, int position, long id) {
                Intent i = new Intent(ctx, ExpenseEdit.class);
                i.putExtra(KEY_ROWID, id);
                //i.putExtra("operationType", operationType);
                startActivityForResult(i, MyExpenses.EDIT_TRANSACTION_REQUEST);
            }
        });
        registerForContextMenu(lv);
        fab = ((FloatingActionButton) v.findViewById(R.id.CREATE_COMMAND));
        fab.setContentDescription(Utils.concatResStrings(getActivity(), ". ",
                R.string.menu_create_split_part_category, R.string.menu_create_split_part_transfer));
        updateFabColor(account.color);
        return v;
    }

    public void updateFabColor(int color) {
        Utils.setBackgroundTintListOnFab(fab, color);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(0, R.id.DELETE_COMMAND, 0, R.string.menu_delete);
    }

    @Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) {
        case R.id.DELETE_COMMAND:
            ((ProtectedFragmentActivity) getActivity()).startTaskExecution(
                    TaskExecutionFragment.TASK_DELETE_TRANSACTION, new Long[] { info.id }, Boolean.valueOf(false),
                    0);
            return true;
        }
        return super.onContextItemSelected(item);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String[] selectionArgs = new String[] { String.valueOf(parentId) };
        CursorLoader cursorLoader = null;
        Uri uri = TransactionProvider.UNCOMMITTED_URI;
        switch (id) {
        case ExpenseEdit.TRANSACTION_CURSOR:
            cursorLoader = new CursorLoader(getActivity(), uri, null, "parent_id = ?", selectionArgs, null);
            return cursorLoader;
        case ExpenseEdit.SUM_CURSOR:
            cursorLoader = new CursorLoader(getActivity(), uri, new String[] { "sum(" + KEY_AMOUNT + ")" },
                    "parent_id = ?", selectionArgs, null);
        }
        return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor c) {
        switch (arg0.getId()) {
        case ExpenseEdit.TRANSACTION_CURSOR:
            mAdapter.swapCursor(c);
            break;
        case ExpenseEdit.SUM_CURSOR:
            c.moveToFirst();
            transactionSum = c.getLong(0);
            updateBalance();
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        switch (arg0.getId()) {
        case ExpenseEdit.TRANSACTION_CURSOR:
            mAdapter.swapCursor(null);
            break;
        }
    }

    public void updateBalance() {
        ExpenseEdit ctx = (ExpenseEdit) getActivity();
        if (ctx == null)
            return;
        unsplitAmount = ctx.getAmount();
        //when we are called before transaction is loaded in parent activity
        if (unsplitAmount == null)
            return;
        unsplitAmount.setAmountMinor(unsplitAmount.getAmountMinor() - transactionSum);
        if (balanceTv != null)
            balanceTv.setText(Utils.formatCurrency(unsplitAmount));
    }

    public boolean splitComplete() {
        return unsplitAmount != null && unsplitAmount.getAmountMinor() == 0L;
    }

    public int getSplitCount() {
        return mAdapter.getCount();
    }

    public void updateAccount(Account account) {
        accountId = account.getId();
        mAdapter.setCurrency(account.currency);
        mAdapter.notifyDataSetChanged();
        updateBalance();
        updateFabColor(account.color);
    }

    public void updateParent(long parentId) {
        this.parentId = parentId;
        requireLoaders();
    }

    private void requireLoaders() {
        Utils.requireLoader(getActivity().getSupportLoaderManager(), ExpenseEdit.TRANSACTION_CURSOR, null, this);
        Utils.requireLoader(getActivity().getSupportLoaderManager(), ExpenseEdit.SUM_CURSOR, null, this);
    }
}