Fix strings, stability bug, easy UI & correctness issues
Bug: 20625562
Bug: 20649711
Bug: 20561890
Bug: 20561528
Bug: 20442590
Bug: 15473140
Bug: 20503008
Bug: 20503007
- Improve timeout text.
- Recalculate when Calculator is rotated, e.g. in error state, thus
reproducing message. It's unclear this is good enough, but it's
better.
- Fix square root parsing.
- Fix concatenation of numbers when pasting by adding explicit
multiplication.
- Display divide by zero error differently from other domain errors.
- Improved advanced keypad layout of portrait-mode tablet calculator.
- Improved overflow menu order. (More to be done.)
- Report zero division as zero division when we can recognize it.
- Switch to floating menus for copy/paste.
Change-Id: I3875414f293e62a59b0e41f0de822f29bd5ac6a6
diff --git a/src/com/android/calculator2/CalculatorExpr.java b/src/com/android/calculator2/CalculatorExpr.java
index 955fd7b..631be01 100644
--- a/src/com/android/calculator2/CalculatorExpr.java
+++ b/src/com/android/calculator2/CalculatorExpr.java
@@ -396,7 +396,23 @@
// TODO: We probably only need this for expressions consisting of
// a single PreEval "token", and may want to check that.
void append(CalculatorExpr expr2) {
+ // Check that we're not concatenating Constant or PreEval
+ // tokens, since the result would look like a single constant
+ int s = mExpr.size();
int s2 = expr2.mExpr.size();
+ // Check that we're not concatenating Constant or PreEval
+ // tokens, since the result would look like a single constant,
+ // with very mysterious results for the user.
+ if (s != 0 && s2 != 0) {
+ Token last = mExpr.get(s-1);
+ Token first = expr2.mExpr.get(0);
+ if (!(first instanceof Operator) && !(last instanceof Operator)) {
+ // Fudge it by adding an explicit multiplication.
+ // We would have interpreted it as such anyway, and this
+ // makes it recognizable to the user.
+ mExpr.add(new Operator(R.id.op_mul));
+ }
+ }
for (int i = 0; i < s2; ++i) {
mExpr.add(expr2.mExpr.get(i));
}
@@ -558,12 +574,22 @@
case R.id.const_e:
return new EvalRet(i+1, CR.valueOf(1).exp(), null);
case R.id.op_sqrt:
- // Seems to have highest precedence
- // Does not add implicit paren
- argVal = evalUnary(i+1, ec);
- ratVal = BoundedRational.sqrt(argVal.mRatVal);
- if (ratVal != null) break;
- return new EvalRet(argVal.mPos, argVal.mVal.sqrt(), null);
+ // Seems to have highest precedence.
+ // Does not add implicit paren.
+ // Does seem to accept a leading minus.
+ if (isOperator(i+1, R.id.op_sub)) {
+ argVal = evalUnary(i+2, ec);
+ ratVal = BoundedRational.sqrt(
+ BoundedRational.negate(argVal.mRatVal));
+ if (ratVal != null) break;
+ return new EvalRet(argVal.mPos,
+ argVal.mVal.negate().sqrt(), null);
+ } else {
+ argVal = evalUnary(i+1, ec);
+ ratVal = BoundedRational.sqrt(argVal.mRatVal);
+ if (ratVal != null) break;
+ return new EvalRet(argVal.mPos, argVal.mVal.sqrt(), null);
+ }
case R.id.lparen:
argVal = evalExpr(i+1, ec);
if (isOperator(argVal.mPos, R.id.rparen)) argVal.mPos++;
@@ -832,7 +858,9 @@
try {
EvalContext ec = new EvalContext(degreeMode);
EvalRet res = evalExpr(0, ec);
- if (res.mPos != mExpr.size()) return null;
+ if (res.mPos != mExpr.size()) {
+ throw new SyntaxError("Failed to parse full expression");
+ }
return new EvalResult(res.mVal, res.mRatVal);
} catch (IndexOutOfBoundsException e) {
throw new SyntaxError("Unexpected expression end");