com.flowzr.budget.holo.widget.CalculatorInput.java Source code

Java tutorial

Introduction

Here is the source code for com.flowzr.budget.holo.widget.CalculatorInput.java

Source

/*******************************************************************************
 * 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
 ******************************************************************************/
package com.flowzr.budget.holo.widget;

import static com.flowzr.budget.holo.utils.Utils.checkEditText;
import static com.flowzr.budget.holo.utils.Utils.text;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Vibrator;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import com.flowzr.budget.holo.R;
import com.flowzr.budget.holo.utils.CurrencyCache;
import com.flowzr.budget.holo.utils.Utils;

import java.math.BigDecimal;
import java.util.Stack;

public class CalculatorInput extends ActionBarActivity implements OnClickListener {

    public static final int[] buttons = { R.id.b0, R.id.b1, R.id.b2, R.id.b3, R.id.b4, R.id.b5, R.id.b6, R.id.b7,
            R.id.b8, R.id.b9, R.id.bAdd, R.id.bSubtract, R.id.bDivide, R.id.bMultiply, R.id.bPercent,
            R.id.bPlusMinus, R.id.bDot, R.id.bResult, R.id.bClear, R.id.bDelete };

    private TextView tvResult;
    private TextView tvOp;

    private Vibrator vibrator;

    private final Stack<String> stack = new Stack<String>();
    private String result = "0";
    private boolean isRestart = true;
    private boolean isInEquals = false;
    private char lastOp = '\0';

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

        setContentView(R.layout.calculator);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);

        for (int id : buttons) {
            Button b = (Button) findViewById(id);
            b.setOnClickListener(this);
        }

        tvResult = (TextView) findViewById(R.id.result);
        tvOp = (TextView) findViewById(R.id.op);

        Intent intent = getIntent();
        if (intent != null) {
            String amount = intent.getStringExtra(AmountInput.EXTRA_AMOUNT);
            if (amount != null) {
                setDisplay(amount);
            }
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.ok_cancel, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_done:
            if (!isInEquals) {
                doEqualsChar();
            }
            close();

            return true;
        case R.id.action_cancel:
            setResult(RESULT_CANCELED);
            finish();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onClick(View v) {
        Button b = (Button) v;
        char c = b.getText().charAt(0);
        onButtonClick(c);
    }

    private void setDisplay(String s) {
        if (Utils.isNotEmpty(s)) {
            s = s.replaceAll(",", ".");
            result = s;
            tvResult.setText(s);
        }
    }

    private void onButtonClick(char c) {
        if (vibrator != null) {
            vibrator.vibrate(20);
        }
        switch (c) {
        case 'C':
            resetAll();
            break;
        case '<':
            doBackspace();
            break;
        default:
            doButton(c);
            break;
        }
    }

    private void resetAll() {
        setDisplay("0");
        tvOp.setText("");
        lastOp = '\0';
        isRestart = true;
        stack.clear();
    }

    private void doBackspace() {
        String s = tvResult.getText().toString();
        if ("0".equals(s) || isRestart) {
            return;
        }
        String newDisplay = s.length() > 1 ? s.substring(0, s.length() - 1) : "0";
        if ("-".equals(newDisplay)) {
            newDisplay = "0";
        }
        setDisplay(newDisplay);
    }

    private void doButton(char c) {
        if (Character.isDigit(c) || c == '.') {
            addChar(c);
        } else {
            switch (c) {
            case '+':
            case '-':
            case '/':
            case '*':
                doOpChar(c);
                break;
            case '%':
                doPercentChar();
                break;
            case '=':
            case '\r':
                doEqualsChar();
                break;
            case '\u00B1':
                setDisplay(new BigDecimal(result).negate().toPlainString());
                break;
            }
        }
    }

    private void addChar(char c) {
        String s = tvResult.getText().toString();
        if (c == '.' && s.indexOf('.') != -1 && !isRestart) {
            return;
        }
        if ("0".equals(s)) {
            s = String.valueOf(c);
        } else {
            s += c;
        }
        setDisplay(s);
        if (isRestart) {
            setDisplay(String.valueOf(c));
            isRestart = false;
        }
    }

    private void doOpChar(char op) {
        if (isInEquals) {
            stack.clear();
            isInEquals = false;
        }
        stack.push(result);
        doLastOp();
        lastOp = op;
        tvOp.setText(String.valueOf(lastOp));
    }

    private void doLastOp() {
        isRestart = true;
        if (lastOp == '\0' || stack.size() == 1) {
            return;
        }

        String valTwo = stack.pop();
        String valOne = stack.pop();
        switch (lastOp) {
        case '+':
            stack.push(new BigDecimal(valOne).add(new BigDecimal(valTwo)).toPlainString());
            break;
        case '-':
            stack.push(new BigDecimal(valOne).subtract(new BigDecimal(valTwo)).toPlainString());
            break;
        case '*':
            stack.push(new BigDecimal(valOne).multiply(new BigDecimal(valTwo)).toPlainString());
            break;
        case '/':
            BigDecimal d2 = new BigDecimal(valTwo);
            if (d2.intValue() == 0) {
                stack.push("0.0");
            } else {
                stack.push(new BigDecimal(valOne).divide(d2, 2, BigDecimal.ROUND_HALF_UP).toPlainString());
            }
            break;
        default:
            break;
        }
        setDisplay(stack.peek());
        if (isInEquals) {
            stack.push(valTwo);
        }
    }

    private void doPercentChar() {
        if (stack.size() == 0)
            return;
        setDisplay(new BigDecimal(result).divide(Utils.HUNDRED).multiply(new BigDecimal(stack.peek()))
                .toPlainString());
        tvOp.setText("");
    }

    private void doEqualsChar() {
        if (lastOp == '\0') {
            return;
        }
        if (!isInEquals) {
            isInEquals = true;
            stack.push(result);
        }
        doLastOp();
        tvOp.setText("");
    }

    private void close() {
        Intent data = new Intent();
        data.putExtra(AmountInput.EXTRA_AMOUNT, result);
        setResult(RESULT_OK, data);
        finish();
    }

}