Fix result overlap, clear logic, display bugs, etc.

Adjust result padding to prevent overlapping with options menu,
resulting in inability to access options menu.

Reset state correctly after clear, preventing occasional crashes.
Do this at end of animation to prevent animation glitches.
Have clear but the display in a state in which COPY does
nothing interesting.

Treat a not-known-to-be-exact zero result better.  Before this
we displayed it as just "0", giving the mistaken impression of
exactness.  It is unclear whether we should display it as "0.00000000"
or add an exponent to indicate the real evaluation precision.
The former probably works better for beginners; the latter for
experts.  We now do the former, which is probably right.

Also correctly save and restore not-yet analyzed characters.

Change-Id: Iac46d0d3b5a06f61beb6af7d4f0910e43284f52b
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index 0d4ab2d..9def2a7 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -168,6 +168,7 @@
 
     private static final String NAME = Calculator.class.getName();
     private static final String KEY_DISPLAY_STATE = NAME + "_display_state";
+    private static final String KEY_UNPROCESSED_CHARS = NAME + "_unprocessed_chars";
     private static final String KEY_EVAL_STATE = NAME + "_eval_state";
                 // Associated value is a byte array holding both mCalculatorState
                 // and the (much more complex) evaluator state.
@@ -224,8 +225,11 @@
             setState(CalculatorState.values()[
                 savedInstanceState.getInt(KEY_DISPLAY_STATE,
                                           CalculatorState.INPUT.ordinal())]);
-            byte[] state =
-                    savedInstanceState.getByteArray(KEY_EVAL_STATE);
+            CharSequence unprocessed = savedInstanceState.getCharSequence(KEY_UNPROCESSED_CHARS);
+            if (unprocessed != null) {
+                mUnprocessedChars = unprocessed.toString();
+            }
+            byte[] state = savedInstanceState.getByteArray(KEY_EVAL_STATE);
             if (state != null) {
                 try (ObjectInput in = new ObjectInputStream(new ByteArrayInputStream(state))) {
                     mEvaluator.restoreInstanceState(in);
@@ -268,6 +272,7 @@
 
         super.onSaveInstanceState(outState);
         outState.putInt(KEY_DISPLAY_STATE, mCurrentState.ordinal());
+        outState.putCharSequence(KEY_UNPROCESSED_CHARS, mUnprocessedChars);
         ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
         try (ObjectOutput out = new ObjectOutputStream(byteArrayStream)) {
             mEvaluator.saveInstanceState(out);
@@ -588,12 +593,13 @@
         if (mEvaluator.getExpr().isEmpty()) {
             return;
         }
-        mUnprocessedChars = null;
-        mResult.clear();
-        mEvaluator.clear();
         reveal(mCurrentButton, R.color.calculator_accent_color, new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
+                mUnprocessedChars = null;
+                mResult.clear();
+                mEvaluator.clear();
+                setState(CalculatorState.INPUT);
                 redisplayFormula();
             }
         });
@@ -639,7 +645,7 @@
         // This is how much we want to move the bottom.
         // Now compensate for the fact that we're
         // simultaenously expanding it around its center by half its height
-        resultTranslationY += mResult.getHeight() * (resultScale-1)/2;
+        resultTranslationY += mResult.getHeight() * (resultScale - 1)/2;
         final float formulaTranslationY = -mFormulaEditText.getBottom();
 
         // TODO: Reintroduce textColorAnimator?