/*******************************************************************************
* Copyright (c) 2010 Denis Solonenko.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v2.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* Denis Solonenko - initial API and implementation
* Abdsandryk - menu option to call Credit Card Bill functionality
******************************************************************************/
package ru.orangesoftware.financisto2.activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import greendroid.widget.QuickAction;
import greendroid.widget.QuickActionGrid;
import greendroid.widget.QuickActionWidget;
import ru.orangesoftware.financisto2.R;
import ru.orangesoftware.financisto2.adapter.BlotterListAdapter_;
import ru.orangesoftware.financisto2.adapter.TransactionsListAdapter;
import ru.orangesoftware.financisto2.adapter.TransactionsListAdapter_;
import ru.orangesoftware.financisto2.blotter.AccountTotalCalculationTask;
import ru.orangesoftware.financisto2.blotter.BlotterTotalCalculationTask;
import ru.orangesoftware.financisto2.blotter.TotalCalculationTask;
import ru.orangesoftware.financisto2.bus.GreenRobotBus;
import ru.orangesoftware.financisto2.bus.GreenRobotBus_;
import ru.orangesoftware.financisto2.dialog.TransactionInfoDialog;
import ru.orangesoftware.financisto2.filter.WhereFilter;
import ru.orangesoftware.financisto2.model.Account;
import ru.orangesoftware.financisto2.model.AccountType;
import ru.orangesoftware.financisto2.model.Transaction;
import ru.orangesoftware.financisto2.utils.ExecutableEntityEnum;
import ru.orangesoftware.financisto2.utils.MenuItemInfo;
import ru.orangesoftware.financisto2.utils.MyPreferences;
import ru.orangesoftware.financisto2.view.NodeInflater;
import static ru.orangesoftware.financisto2.utils.AndroidUtils.isGreenDroidSupported;
import static ru.orangesoftware.financisto2.utils.EnumUtils.showPickOneDialog;
import static ru.orangesoftware.financisto2.utils.MyPreferences.isQuickMenuEnabledForTransaction;
public class BlotterActivity extends AbstractListActivity {
public static final String SAVE_FILTER = "saveFilter";
public static final String EXTRA_FILTER_ACCOUNTS = "filterAccounts";
private static final int NEW_TRANSACTION_REQUEST = 1;
private static final int NEW_TRANSFER_REQUEST = 3;
private static final int NEW_TRANSACTION_FROM_TEMPLATE_REQUEST = 5;
private static final int MONTHLY_VIEW_REQUEST = 6;
private static final int BILL_PREVIEW_REQUEST = 7;
protected static final int FILTER_REQUEST = 6;
private static final int MENU_DUPLICATE = MENU_ADD+1;
private static final int MENU_SAVE_AS_TEMPLATE = MENU_ADD+2;
protected TextView totalText;
protected ImageButton bFilter;
protected ImageButton bTransfer;
protected ImageButton bTemplate;
private QuickActionWidget transactionActionGrid;
private QuickActionWidget addButtonActionGrid;
private TotalCalculationTask calculationTask;
protected boolean saveFilter;
protected WhereFilter blotterFilter = WhereFilter.empty();
private boolean isAccountBlotter = false;
private boolean showAllBlotterButtons = true;
protected GreenRobotBus bus;
public BlotterActivity(int layoutId) {
super(layoutId);
}
public BlotterActivity() {
super(R.layout.blotter);
}
protected void calculateTotals() {
if (calculationTask != null) {
calculationTask.stop();
calculationTask.cancel(true);
}
calculationTask = createTotalCalculationTask();
calculationTask.execute();
}
protected TotalCalculationTask createTotalCalculationTask() {
WhereFilter filter = WhereFilter.copyOf(blotterFilter);
if (filter.getAccountId() > 0) {
return new AccountTotalCalculationTask(this, db, filter, totalText);
} else {
return new BlotterTotalCalculationTask(this, db, filter, totalText);
}
}
@Override
public void recreateCursor() {
super.recreateCursor();
calculateTotals();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater = new NodeInflater(layoutInflater);
bus = GreenRobotBus_.getInstance_(this);
integrityCheck();
}
@Override
protected void internalOnCreate(Bundle savedInstanceState) {
super.internalOnCreate(savedInstanceState);
showAllBlotterButtons = !MyPreferences.isCollapseBlotterButtons(this);
if (showAllBlotterButtons) {
bTransfer = (ImageButton)findViewById(R.id.bTransfer);
bTransfer.setVisibility(View.VISIBLE);
bTransfer.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
addItem(NEW_TRANSFER_REQUEST, TransferActivity.class);
}
});
bTemplate = (ImageButton)findViewById(R.id.bTemplate);
bTemplate.setVisibility(View.VISIBLE);
bTemplate.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
createFromTemplate();
}
});
}
bFilter = (ImageButton)findViewById(R.id.bFilter);
bFilter.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
Intent intent = new Intent(BlotterActivity.this, BlotterFilterActivity.class);
blotterFilter.toIntent(intent);
intent.putExtra(BlotterFilterActivity.IS_ACCOUNT_FILTER, isAccountBlotter && blotterFilter.getAccountId() > 0);
startActivityForResult(intent, FILTER_REQUEST);
}
});
totalText = (TextView)findViewById(R.id.total);
totalText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
showTotals();
}
});
Intent intent = getIntent();
if (intent != null) {
blotterFilter = WhereFilter.fromIntent(intent);
saveFilter = intent.getBooleanExtra(SAVE_FILTER, false);
isAccountBlotter = intent.getBooleanExtra(BlotterFilterActivity.IS_ACCOUNT_FILTER, false);
}
if (savedInstanceState != null) {
blotterFilter = WhereFilter.fromBundle(savedInstanceState);
}
if (saveFilter && blotterFilter.isEmpty()) {
blotterFilter = WhereFilter.fromSharedPreferences(getPreferences(0));
}
applyFilter();
calculateTotals();
prepareTransactionActionGrid();
prepareAddButtonActionGrid();
}
private void showTotals() {
Intent intent = new Intent(this, BlotterTotalsDetailsActivity.class);
blotterFilter.toIntent(intent);
startActivityForResult(intent, -1);
}
protected void prepareTransactionActionGrid() {
if (isGreenDroidSupported()) {
transactionActionGrid = new QuickActionGrid(this);
transactionActionGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_info, R.string.info));
transactionActionGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_edit, R.string.edit));
transactionActionGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_trashcan, R.string.delete));
transactionActionGrid.addQuickAction(new QuickAction(this, R.drawable.gd_action_bar_share, R.string.duplicate));
transactionActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_action_bar_mark, R.string.clear));
transactionActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_action_bar_double_mark, R.string.reconcile));
transactionActionGrid.setOnQuickActionClickListener(transactionActionListener);
}
}
private QuickActionWidget.OnQuickActionClickListener transactionActionListener = new QuickActionWidget.OnQuickActionClickListener() {
public void onQuickActionClicked(QuickActionWidget widget, int position) {
switch (position) {
case 0:
showTransactionInfo(selectedId);
break;
case 1:
editTransaction(selectedId);
break;
case 2:
deleteTransaction(selectedId);
break;
case 3:
duplicateTransaction(selectedId, 1);
break;
case 4:
clearTransaction(selectedId);
break;
case 5:
reconcileTransaction(selectedId);
break;
}
}
};
private void prepareAddButtonActionGrid() {
if (isGreenDroidSupported()) {
addButtonActionGrid = new QuickActionGrid(this);
addButtonActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_input_add, R.string.transaction));
addButtonActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_input_transfer, R.string.transfer));
addButtonActionGrid.addQuickAction(new QuickAction(this, R.drawable.ic_input_templates, R.string.template));
addButtonActionGrid.setOnQuickActionClickListener(addButtonActionListener);
}
}
private QuickActionWidget.OnQuickActionClickListener addButtonActionListener = new QuickActionWidget.OnQuickActionClickListener() {
public void onQuickActionClicked(QuickActionWidget widget, int position) {
switch (position) {
case 0:
addItem(NEW_TRANSACTION_REQUEST, TransactionActivity.class);
break;
case 1:
addItem(NEW_TRANSFER_REQUEST, TransferActivity.class);
break;
case 2:
createFromTemplate();
break;
}
}
};
private void clearTransaction(long selectedId) {
new BlotterOperations(this, db, selectedId, bus).clearTransaction();
recreateCursor();
}
private void reconcileTransaction(long selectedId) {
new BlotterOperations(this, db, selectedId, bus).reconcileTransaction();
recreateCursor();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
blotterFilter.toBundle(outState);
}
protected void createFromTemplate() {
Intent intent = new Intent(this, SelectTemplateActivity.class);
startActivityForResult(intent, NEW_TRANSACTION_FROM_TEMPLATE_REQUEST);
}
@Override
protected List<MenuItemInfo> createContextMenus(long id) {
if (blotterFilter.isTemplate() || blotterFilter.isSchedule()) {
return super.createContextMenus(id);
} else {
List<MenuItemInfo> menus = super.createContextMenus(id);
menus.add(new MenuItemInfo(MENU_DUPLICATE, R.string.duplicate));
menus.add(new MenuItemInfo(MENU_SAVE_AS_TEMPLATE, R.string.save_as_template));
return menus;
}
}
@Override
protected String getContextMenuHeaderTitle(int position) {
return getString(blotterFilter.isTemplate() ? R.string.template : R.string.transaction);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (!super.onContextItemSelected(item)) {
AdapterView.AdapterContextMenuInfo mi = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
switch (item.getItemId()) {
case MENU_DUPLICATE:
duplicateTransaction(mi.id, 1);
return true;
case MENU_SAVE_AS_TEMPLATE:
new BlotterOperations(this, db, mi.id, bus).duplicateAsTemplate();
Toast.makeText(this, R.string.save_as_template_success, Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
private long duplicateTransaction(long id, int multiplier) {
long newId = new BlotterOperations(this, db, id, bus).duplicateTransaction(multiplier);
String toastText;
if (multiplier > 1) {
toastText = getString(R.string.duplicate_success_with_multiplier, multiplier);
} else {
toastText = getString(R.string.duplicate_success);
}
Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();
recreateCursor();
AccountWidget.updateWidgets(BlotterActivity.this);
return newId;
}
@Override
protected void addItem() {
if (showAllBlotterButtons) {
addItem(NEW_TRANSACTION_REQUEST, TransactionActivity.class);
} else {
if (isGreenDroidSupported()) {
addButtonActionGrid.show(bAdd);
} else {
showPickOneDialog(this, R.string.add_transaction, TransactionQuickMenuEntities.values(), addButtonActionListener);
}
}
}
protected void addItem(int requestId, Class<? extends AbstractTransactionActivity> clazz) {
Intent intent = new Intent(BlotterActivity.this, clazz);
long accountId = blotterFilter.getAccountId();
if (accountId != -1) {
//intent.putExtra(TransactionActivity.ACCOUNT_ID_EXTRA, accountId);
}
//intent.putExtra(TransactionActivity.TEMPLATE_EXTRA, blotterFilter.getIsTemplate());
startActivityForResult(intent, requestId);
}
@Override
protected Cursor createCursor() {
Cursor c;
long accountId = blotterFilter.getAccountId();
if (accountId != -1) {
c = db.getBlotterForAccount(blotterFilter);
} else {
c = db.getBlotter(blotterFilter);
}
return c;
}
@Override
protected ListAdapter createAdapter(Cursor cursor) {
long accountId = blotterFilter.getAccountId();
if (accountId != -1) {
return TransactionsListAdapter_.getInstance_(this);
} else {
return BlotterListAdapter_.getInstance_(this);
}
}
@Override
protected void deleteItem(View v, int position, final long id) {
deleteTransaction(id);
}
private void deleteTransaction(long id) {
new BlotterOperations(this, db, id, bus).deleteTransaction();
}
protected void afterDeletingTransaction(long id) {
recreateCursor();
AccountWidget.updateWidgets(this);
}
@Override
public void editItem(View v, int position, long id) {
editTransaction(id);
}
private void editTransaction(long id) {
new BlotterOperations(this, db, id, bus).editTransaction();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FILTER_REQUEST) {
if (resultCode == RESULT_FIRST_USER) {
blotterFilter.clear();
} else if (resultCode == RESULT_OK) {
blotterFilter = WhereFilter.fromIntent(data);
}
if (saveFilter) {
saveFilter();
}
applyFilter();
recreateCursor();
} else if (resultCode == RESULT_OK && requestCode == NEW_TRANSACTION_FROM_TEMPLATE_REQUEST) {
createTransactionFromTemplate(data);
}
if (resultCode == RESULT_OK || resultCode == RESULT_FIRST_USER) {
calculateTotals();
}
}
private void createTransactionFromTemplate(Intent data) {
long templateId = data.getLongExtra(SelectTemplateActivity.TEMPATE_ID, -1);
int multiplier = data.getIntExtra(SelectTemplateActivity.MULTIPLIER, 1);
boolean edit = data.getBooleanExtra(SelectTemplateActivity.EDIT_AFTER_CREATION, false);
if (templateId > 0) {
long id = duplicateTransaction(templateId, multiplier);
Transaction t = db.getTransaction(id);
if (t.fromAmount == 0 || edit) {
new BlotterOperations(this, db, id, bus).asNewFromTemplate().editTransaction();
}
}
}
private void saveFilter() {
SharedPreferences preferences = getPreferences(0);
blotterFilter.toSharedPreferences(preferences);
}
protected void applyFilter() {
long accountId = blotterFilter.getAccountId();
if (accountId !=1) {
Account a = db.getAccount(accountId);
bAdd.setVisibility(a != null && a.isActive ? View.VISIBLE : View.GONE);
if (showAllBlotterButtons) {
bTransfer.setVisibility(a != null && a.isActive ? View.VISIBLE : View.GONE);
}
}
String title = blotterFilter.getTitle();
if (title != null) {
setTitle(getString(R.string.blotter)+" : "+title);
}
updateFilterImage();
}
protected void updateFilterImage() {
bFilter.setImageResource(blotterFilter.isEmpty() ? R.drawable.ic_menu_filter_off : R.drawable.ic_menu_filter_on);
}
private NodeInflater inflater;
private long selectedId = -1;
@Override
protected void onItemClick(View v, int position, long id) {
if (isQuickMenuEnabledForTransaction(this)) {
selectedId = id;
transactionActionGrid.show(v);
} else {
showTransactionInfo(id);
}
}
@Override
protected void viewItem(View v, int position, long id) {
showTransactionInfo(id);
}
private void showTransactionInfo(long id) {
TransactionInfoDialog transactionInfoView = new TransactionInfoDialog(this, db, inflater);
transactionInfoView.show(this, id);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
long accountId = blotterFilter.getAccountId();
// Funcionality available for account blotter
if (accountId != -1) {
// get account type
Account account = db.getAccount(accountId);
AccountType type = AccountType.valueOf(account.type);
if (type.isCreditCard) {
// Show menu for Credit Cards - bill
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.ccard_blotter_menu, menu);
} else {
// Show menu for other accounts - monthly view
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.blotter_menu, menu);
}
return true;
} else {
return super.onCreateOptionsMenu(menu);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
long accountId = blotterFilter.getAccountId();
Intent intent = new Intent(this, MonthlyViewActivity.class);
intent.putExtra(MonthlyViewActivity.ACCOUNT_EXTRA, accountId);
switch (item.getItemId()) {
case R.id.opt_menu_month:
// call credit card bill activity sending account id
intent.putExtra(MonthlyViewActivity.BILL_PREVIEW_EXTRA, false);
startActivityForResult(intent, MONTHLY_VIEW_REQUEST);
return true;
case R.id.opt_menu_bill:
if (accountId != -1) {
Account account = db.getAccount(accountId);
// call credit card bill activity sending account id
if (account.paymentDay>0 && account.closingDay>0) {
intent.putExtra(MonthlyViewActivity.BILL_PREVIEW_EXTRA, true);
startActivityForResult(intent, BILL_PREVIEW_REQUEST);
return true;
} else {
// display message: need payment and closing day
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage(R.string.statement_error);
dlgAlert.setTitle(R.string.ccard_statement);
dlgAlert.setPositiveButton(R.string.ok, null);
dlgAlert.setCancelable(true);
dlgAlert.create().show();
return true;
}
} else {
return true;
}
default:
return super.onOptionsItemSelected(item);
}
}
private enum TransactionQuickMenuEntities implements ExecutableEntityEnum<QuickActionWidget.OnQuickActionClickListener> {
NEW_TRANSACTION(R.string.transaction, R.drawable.ic_input_add){
@Override
public void execute(QuickActionWidget.OnQuickActionClickListener listener) {
listener.onQuickActionClicked(null, 0);
}
},
NEW_TRANSFER(R.string.transfer, R.drawable.ic_input_transfer) {
@Override
public void execute(QuickActionWidget.OnQuickActionClickListener listener) {
listener.onQuickActionClicked(null, 1);
}
},
NEW_TEMPLATE(R.string.template, R.drawable.ic_input_templates) {
@Override
public void execute(QuickActionWidget.OnQuickActionClickListener listener) {
listener.onQuickActionClicked(null, 2);
}
};
private final int titleId;
private final int iconId;
private TransactionQuickMenuEntities(int titleId, int iconId) {
this.titleId = titleId;
this.iconId = iconId;
}
@Override
public int getTitleId() {
return titleId;
}
@Override
public int getIconId() {
return iconId;
}
}
}