Android Open Source - budget-envelopes Envelope Details Fragment






From Project

Back to project page budget-envelopes.

License

The source code is released under:

GNU General Public License

If you think the Android project budget-envelopes listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * This file is a part of Budget with Envelopes.
 * Copyright 2013 Michael Howell <michael@notriddle.com>
 */*from w ww.java  2  s . co m*/
 * Budget 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.
 *
 * Budget 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 Budget. If not, see <http://www.gnu.org/licenses/>.
 */

package com.notriddle.budget;

import android.app.ActionBar;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentValues;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.SparseBooleanArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.database.sqlite.SQLiteDatabase;

public class EnvelopeDetailsFragment extends Fragment
                                     implements LoaderCallbacks<Cursor>,
                                                TextWatcher,
                                                DeleteAdapter.Deleter,
                                                AdapterView.OnItemClickListener,
                                                TitleFragment,
                                                ColorFragment,
                                                CustomActionBarFragment {
    EditTextDefaultFocus mName;
    int mId;
    int mShowTransactionId;
    SQLiteDatabase mDatabase;
    LogAdapter mLogAdapter;
    DeleteAdapter mDeleteAdapter;
    ListView mLogView;
    SimpleEnvelopesAdapter mNavAdapter;
    ListView mNavView;
    TextView mAmount;
    TextView mAmountName;
    TextView mProjected;
    Cursor mEnvelopeData;
    Cursor mLogData;
    int mColor;

    public EnvelopeDetailsFragment() {
        setHasOptionsMenu(true);
    }

    @Override public View onCreateActionBarView(LayoutInflater inflater) {
        mName = new EditTextDefaultFocus(getActivity());
        mName.setHint(getActivity().getText(R.string.envelopeName_hint));
        mName.setInputType(InputType.TYPE_CLASS_TEXT|InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
        mName.setLayoutParams(new ActionBar.LayoutParams(
            ActionBar.LayoutParams.MATCH_PARENT,
            ActionBar.LayoutParams.WRAP_CONTENT
        ));
        mName.setSingleLine(true);

        mName.addTextChangedListener(this);

        return mName;
    }

    @Override public View onCreateView(LayoutInflater inflater, ViewGroup cont,
                                       Bundle state) {
        View retVal = inflater.inflate(R.layout.envelopedetailsactivity, cont, false);
        mId = state != null && state.containsKey("com.notriddle.budget.envelope")
            ? state.getInt("com.notriddle.budget.envelope")
            : getArguments().getInt("com.notriddle.budget.envelope", -1);
        mShowTransactionId = state == null
            ? getArguments().getInt("com.notriddle.budget.transaction", -1)
            : -1;
        mEnvelopeData = null;
        mLogData = null;

        final ListView nV = mNavView = (ListView) retVal.findViewById(R.id.nav);
        if (nV != null) {
            mNavAdapter = new SimpleEnvelopesAdapter(getActivity(), null, R.layout.card_just_text);
            mNavAdapter.setExpanded(true);
            nV.setAdapter(mNavAdapter);
            nV.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            nV.setOnItemClickListener(this);
        }

        getLoaderManager().initLoader(0, null, this);
        getLoaderManager().initLoader(1, null, this);
        mLogAdapter = new LogAdapter(getActivity(), null);
        final ListView lV = mLogView = (ListView) retVal.findViewById(android.R.id.list);
        //lV.setOverScrollMode(lV.OVER_SCROLL_NEVER);
        final View head = inflater.inflate(
            R.layout.totalamount,
            lV,
            false
        );
        final int basePadding = head.getPaddingTop();
        mAmount = (TextView) head.findViewById(R.id.value);
        mAmountName = (TextView) head.findViewById(R.id.name);
        mProjected = (TextView) head.findViewById(R.id.projectedValue);
        lV.addHeaderView(head);
        mDeleteAdapter = new DeleteAdapter(
            getActivity(), this, mLogAdapter, 0
        );
        lV.setAdapter(mDeleteAdapter);

        lV.setOnScrollListener(new AbsListView.OnScrollListener() {
            public void onScroll(AbsListView lV, int first, int count, int total) {
                View c = lV.getChildAt(0);
                if (c == head) {
                    int move = (head.getTop()*-2)/3;
                    mAmount.setTranslationY(move);
                    mAmountName.setTranslationY(move);
                    mProjected.setTranslationY(move);
                }
            }
            public void onScrollStateChanged(AbsListView lV, int state) {
                // Do nothing.
            }
        });
        lV.setOnItemClickListener(this);
        lV.setSelector(android.R.color.transparent);
        lV.setDivider(getResources().getDrawable(R.color.cardDivider));
        lV.setDividerHeight((int)TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()
        ));
        lV.setOverscrollFooter(getResources().getDrawable(
            R.color.cardBackground
        ));
        lV.setOverscrollHeader(getResources().getDrawable(
            R.color.windowBackground
        ));

        return retVal;
    }

    @Override public void onSaveInstanceState(Bundle state) {
        super.onSaveInstanceState(state);
        state.putInt("com.notriddle.budget.envelope", mId);
    }

    @Override public void onPause() {
        super.onPause();
        mDeleteAdapter.performDelete();
        if (mDatabase != null) {
            mDatabase.close();
            mDatabase = null;
        }
    }

    @Override public void onDestroy() {
        super.onDestroy();
        ActionBar ab = getActivity().getActionBar();
        ab.setDisplayShowTitleEnabled(true);
        ab.setDisplayShowCustomEnabled(false);
        ab.setCustomView(null);
        if (mName.getText().length() == 0 && mLogAdapter.getCount() == 0 && mEnvelopeData != null && mLogData != null) {
            deleteThis();
            mDatabase.close();
            mDatabase = null;
        }
    }

    @Override public void performDelete(long id) {
        deleteTransaction((int)id);
    }
    @Override public void onDelete(long id) {
        loadLogData(mLogData);
    }
    @Override public void undoDelete(long id) {
        loadEnvelopeData(mEnvelopeData);
    }

    private void deleteTransaction(int id) {
        needDatabase();
        mDatabase.beginTransaction();
        try {
            mDatabase.execSQL("DELETE FROM log WHERE _id = ?",
                              new String[] {Integer.toString(id)});
            EnvelopesOpenHelper.playLog(mDatabase);
            mDatabase.setTransactionSuccessful();
            getActivity().getContentResolver().notifyChange(EnvelopesOpenHelper.URI, null);
        } finally {
            mDatabase.endTransaction();
        }
    }

    private SQLiteDatabase needDatabase() {
        if (mDatabase == null) {
            mDatabase = (new EnvelopesOpenHelper(getActivity())).getWritableDatabase();
        }
        return mDatabase;
    }

    @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        String table     = id == 0
                           ? "envelopes"
                           : "log";
        String[] columns = id == 0
                           ? new String[] { "name", "cents", "projectedCents",
                                            "color", "_id" }
                           : new String[] { "description", "cents", "time",
                                            "_id" };
        String where     = id == 0
                           ? (mNavAdapter == null ? "_id = ?" : null)
                           : "envelope = ?";
        String[] wArgs   = id == 0 && mNavAdapter != null
                           ? null
                           : new String[] {Integer.toString(mId)};
        String sort      = id == 0
                           ? "name"
                           : "time * -1";
        SQLiteLoader retVal = new SQLiteLoader(
            getActivity(),
            new EnvelopesOpenHelper(getActivity()),
            table,
            columns,
            where,
            wArgs,
            null,
            null,
            sort
        );
        retVal.setNotificationUri(EnvelopesOpenHelper.URI);
        return retVal;
    }

    private void loadEnvelopeData(Cursor data) {
        mEnvelopeData = data;
        if (data.getCount() == 0) {
            throw new RuntimeException("Invalid envelope ID: "+Integer.toString(mId));
        } else {
            data.moveToFirst();
            while (data.getInt(data.getColumnIndexOrThrow("_id")) != mId) {
                data.moveToNext();
            }
            String name = data.getString(data.getColumnIndexOrThrow("name"));
            if (!mName.hasFocus()) {
                if (!mName.getText().toString().equals(name)) {
                    mName.setText(name);
                }
                mName.setDefaultFocus(name.equals(""));
            }
            if (mDeleteAdapter.getDeletedId() == -1) {
                long cents = data.getLong(data.getColumnIndexOrThrow("cents"));
                mAmount.setText(EditMoney.toColoredMoney(getActivity(), cents));
                long projected = data.getLong(
                    data.getColumnIndexOrThrow("projectedCents")
                );
                if (projected == cents) {
                    mProjected.setVisibility(View.GONE);
                } else {
                    mProjected.setVisibility(View.VISIBLE);
                    mProjected.setText(
                        EditMoney.toColoredMoney(getActivity(), projected)
                    );
                }
            }
            mColor = data.getInt(data.getColumnIndexOrThrow("color"));
            notifyColor();

            if (getActivity() instanceof OnColorChangeListener) {
            }
            if (mNavAdapter != null) {
                mNavAdapter.changeCursor(data);
                if (mNavView != null) {
                    int l = mNavAdapter.getCount();
                    for (int i = 0; i != l; ++i) {
                        if (mNavAdapter.getItemId(i) == mId) {
                            mNavView.setItemChecked(i, true);
                            break;
                        }
                    }
                }
            }
            if (Build.VERSION.SDK_INT < 18) {
                getActivity().invalidateOptionsMenu();
            }
        }
    }

    private void loadLogData(Cursor data) {
        mLogData = data;
        if (mDeleteAdapter.getDeletedId() != -1) {
            int l = data.getCount();
            long total = 0;
            long projected = 0;
            long now = System.currentTimeMillis();
            data.moveToFirst();
            for (int i = 0; i != l; ++i) {
                int id = data.getInt(data.getColumnIndexOrThrow("_id"));
                if (id != mDeleteAdapter.getDeletedId()) {
                    long cents = data.getLong(data.getColumnIndexOrThrow("cents"));
                    long time = data.getLong(data.getColumnIndexOrThrow("time"));
                    if (time <= now) {
                        total += cents;
                    }
                    projected += cents;
                }
                data.moveToNext();
            }
            mAmount.setText(EditMoney.toColoredMoney(getActivity(), total));
            if (projected == total) {
                mProjected.setVisibility(View.GONE);
            } else {
                mProjected.setVisibility(View.VISIBLE);
                mProjected.setText(
                    EditMoney.toColoredMoney(getActivity(), projected)
                );
            }
        }
        mLogAdapter.changeCursor(data);
        final ListView lV = mLogView;
        if (mShowTransactionId != -1) {
            int l = mDeleteAdapter.getCount();
            for (int i = 0; i != l; ++i) {
                if (mDeleteAdapter.getItemId(i) == mShowTransactionId) {
                    mLogView.smoothScrollToPosition(i == l-1 ? i : i+1);
                    break;
                }
            }
            mShowTransactionId = -1;
        }
    }

    @Override public void onLoadFinished(Loader<Cursor> ldr, Cursor data) {
        if (ldr.getId() == 0) {
            loadEnvelopeData(data);
        } else {
            loadLogData(data);
        }
    }

    @Override public void onLoaderReset(Loader<Cursor> ldr) {
        //finish();
    }

    @Override public void afterTextChanged(Editable s) {
        // Do nothing.
    }

    @Override public void beforeTextChanged(CharSequence s, int start,
                                            int count, int end) {
        // Do nothing.
    }

    @Override public void onTextChanged(CharSequence s, int start,
                                        int count, int end) {
        ContentValues values = new ContentValues();
        values.put("name", s.toString());
        needDatabase().update("envelopes", values, "_id = ?", new String[] {Integer.toString(mId)});
        getActivity().getContentResolver().notifyChange(EnvelopesOpenHelper.URI, null);
    }

    @Override public void onItemClick(AdapterView a, View v, int pos, long id) {
        final int iId = (int)id;
        if (a == mLogView) {
            editLogEntry(iId);
        } else if (a == mNavView) {
            switchEnvelope(iId);
        }
    }

    private void editLogEntry(int id) {
        Cursor csr = mLogAdapter.getCursor();
        int oldPos = csr.getPosition();
        csr.moveToFirst();
        int l = csr.getCount();
        for (int i = 0; i != l; ++i) {
            if (csr.getInt(csr.getColumnIndexOrThrow("_id")) == id) {
                EditTransactionFragment f = EditTransactionFragment.newInstance(
                    id,
                    csr.getString(csr.getColumnIndexOrThrow("description")),
                    csr.getLong(csr.getColumnIndexOrThrow("cents"))
                );
                f.show(getFragmentManager(), "dialog");
                break;
            }
            csr.moveToNext();
        }
        csr.moveToPosition(oldPos);
    }

    private void switchEnvelope(final int id) {
        if (!mDeleteAdapter.performDelete()) {
            mId = id;
            getLoaderManager().restartLoader(
                    0, null, EnvelopeDetailsFragment.this
            );
            getLoaderManager().restartLoader(
                1, null, EnvelopeDetailsFragment.this
            );
        } else {
            final DataSetObserver obs = new DataSetObserver() {
                @Override public void onChanged() {
                    // You can't unregister yourself in onChanged().
                    final DataSetObserver that = this;
                    mLogView.post(new Runnable() {
                        public void run() {
                            mDeleteAdapter.unregisterDataSetObserver(that);
                            switchEnvelope(id);
                        }
                    });
                }
                @Override public void onInvalidated() {
                    onChanged();
                }
            };
            mDeleteAdapter.registerDataSetObserver(obs);
        }
    }

    private void changeColor() {
        if (mColor == 0) {
            mColor = 0xFFFFC1C1;
        } else if (mColor == 0xFFFFC1C1) {
            mColor = 0xFFFF1F8F;
        } else if (mColor == 0xFFFF1F8F) {
            mColor = 0xFFFF4444;
        } else if (mColor == 0xFFFF4444) {
            mColor = 0xFFAA66CC;
        } else if (mColor == 0xFFAA66CC) {
            mColor = 0xFF33B5E5;
        } else if (mColor == 0xFF33B5E5) {
            mColor = 0xFF33E5B5;
        } else if (mColor == 0xFF33E5B5) {
            mColor = 0xFF005FDE;
        } else if (mColor == 0xFF005FDE) {
            mColor = 0xFFCE6F00;
        } else if (mColor == 0xFFCE6F00) {
            mColor = 0xFFFFBB33;
        } else {
            mColor = 0;
        }
        notifyColor();
        ContentValues values = new ContentValues();
        values.put("color", mColor);
        needDatabase().update("envelopes", values, "_id = ?", new String[] {Integer.toString(mId)});
        getActivity().getContentResolver().notifyChange(EnvelopesOpenHelper.URI, null);
    }

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

    @Override public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.earn_menuItem:
                SpendFragment sF = SpendFragment.newInstance(mId, SpendFragment.EARN);
                sF.show(getFragmentManager(), "dialog");
                return true;
            case R.id.spend_menuItem:
                sF = SpendFragment.newInstance(mId, SpendFragment.SPEND);
                sF.show(getFragmentManager(), "dialog");
                return true;
            case R.id.color_menuItem:
                changeColor();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void deleteThis() {
        needDatabase().delete("envelopes", "_id = ?",
                              new String[] {Integer.toString(mId)});
        needDatabase().delete("log", "envelope = ?",
                              new String[] {Integer.toString(mId)});
        getActivity().getContentResolver().notifyChange(EnvelopesOpenHelper.URI, null);
    }

    private void notifyColor() {
        if (getActivity() instanceof OnColorChangeListener) {
            OnColorChangeListener l = (OnColorChangeListener) getActivity();
            l.onColorChange(mColor);
        }
    }

    @Override public int getColor() {
        return mColor;
    }

    @Override public String getTitle() {
        return getActivity().getString(R.string.envelopeDetails_name);
    }
}




Java Source Code List

com.notriddle.budget.AboutFragment.java
com.notriddle.budget.AllTransactionsFragment.java
com.notriddle.budget.CheckableLinearLayout.java
com.notriddle.budget.CheckableRelativeLayout.java
com.notriddle.budget.ColorFragment.java
com.notriddle.budget.CustomActionBarFragment.java
com.notriddle.budget.DeleteAdapter.java
com.notriddle.budget.DeleteView.java
com.notriddle.budget.EditMoney.java
com.notriddle.budget.EditTextDefaultFocus.java
com.notriddle.budget.EditTransactionFragment.java
com.notriddle.budget.EnvelopeDetailsFragment.java
com.notriddle.budget.EnvelopesActivity.java
com.notriddle.budget.EnvelopesAdapter.java
com.notriddle.budget.EnvelopesFragment.java
com.notriddle.budget.EnvelopesOpenHelper.java
com.notriddle.budget.ExportFragment.java
com.notriddle.budget.FileCreatorFragment.java
com.notriddle.budget.GraphFragment.java
com.notriddle.budget.ImportFragment.java
com.notriddle.budget.LockedActivity.java
com.notriddle.budget.LogAdapter.java
com.notriddle.budget.MonitorScrollView.java
com.notriddle.budget.NavAdapter.java
com.notriddle.budget.OkFragment.java
com.notriddle.budget.PaycheckEnvelopesAdapter.java
com.notriddle.budget.PaycheckFragment.java
com.notriddle.budget.PinActivity.java
com.notriddle.budget.SQLiteLoader.java
com.notriddle.budget.SettingsFragment.java
com.notriddle.budget.SimpleEnvelopesAdapter.java
com.notriddle.budget.SimpleLogAdapter.java
com.notriddle.budget.SpendFragment.java
com.notriddle.budget.TACGridView.java
com.notriddle.budget.TitleFragment.java
com.notriddle.budget.TransferFragment.java
com.notriddle.budget.Util.java
com.notriddle.budget.WidgetProvider.java
com.notriddle.budget.WidgetService.java
com.notriddle.budget.csv.CSVReader.java
com.notriddle.budget.csv.CSVWriter.java