Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5ea8eb2 authored by Hans Boehm's avatar Hans Boehm
Browse files

Further calculator state cleanups

Bug: 33265653

Preserve evaluation results in history earlier.

Make the mapping from saved state to evaluation state much more
explicit. Note that we no longer map EVALUATE to INIT. It seems
to make sense to do the animation the first time, even if a
rotation intervened.

Change-Id: I8dcf41d62305debb06f3fe3eece9818b21b67bcc
parent f1c92ca9
Loading
Loading
Loading
Loading
+38 −8
Original line number Diff line number Diff line
@@ -100,7 +100,8 @@ public class Calculator extends Activity
                        // Not used for instant result evaluation.
        INIT,           // Very temporary state used as alternative to EVALUATE
                        // during reinitialization.  Do not animate on completion.
        INIT_FOR_RESULT,  // Identical to INIT, but evaluation is known to terminate.
        INIT_FOR_RESULT,  // Identical to INIT, but evaluation is known to terminate
                          // with result, and current expression has been copied to history.
        ANIMATE,        // Result computed, animation to enlarge result window in progress.
        RESULT,         // Result displayed, formula invisible.
                        // If we are in RESULT state, the formula was evaluated without
@@ -116,9 +117,12 @@ public class Calculator extends Activity
    // initially evaluate assuming we were given a well-defined problem.  If we
    // were actually asked to compute sqrt(<extremely tiny negative number>) we produce 0
    // unless we are asked for enough precision that we can distinguish the argument from zero.
    // ANIMATE, ERROR, and RESULT are translated to an INIT state if the application
    // ERROR and RESULT are translated to INIT or INIT_FOR_RESULT state if the application
    // is restarted in that state.  This leads us to recompute and redisplay the result
    // ASAP.
    // ASAP. We avoid saving the ANIMATE state or activating history in that state.
    // In INIT_FOR_RESULT, and RESULT state, a copy of the current
    // expression has been saved in the history db; in the other non-ANIMATE states,
    // it has not.
    // TODO: Possibly save a bit more information, e.g. its initial display string
    // or most significant digit position, to speed up restart.

@@ -300,6 +304,26 @@ public class Calculator extends Activity

    private HistoryFragment mHistoryFragment = new HistoryFragment();

    /**
     * Map the old saved state to a new state reflecting requested result reevaluation.
     */
    private CalculatorState mapFromSaved(CalculatorState savedState) {
        switch (savedState) {
            case RESULT:
            case INIT_FOR_RESULT:
                // Evaluation is expected to terminate normally.
                return CalculatorState.INIT_FOR_RESULT;
            case ERROR:
            case INIT:
                return CalculatorState.INIT;
            case EVALUATE:
            case INPUT:
                return savedState;
            default:  // Includes ANIMATE state.
                throw new AssertionError("Impossible saved state");
        }
    }

    /**
     * Restore Evaluator state and mCurrentState from savedInstanceState.
     * Return true if the toolbar should be visible.
@@ -346,9 +370,7 @@ public class Calculator extends Activity
            mResultText.setShouldEvaluateResult(CalculatorResult.SHOULD_EVALUATE, this);
        } else {
            // Just reevaluate.
            setState((mCurrentState == CalculatorState.RESULT
                    || mCurrentState == CalculatorState.INIT_FOR_RESULT) ?
                    CalculatorState.INIT_FOR_RESULT : CalculatorState.INIT);
            setState(mapFromSaved(mCurrentState));
            // Request evaluation when we know display width.
            mResultText.setShouldEvaluateResult(CalculatorResult.SHOULD_REQUIRE, this);
        }
@@ -540,6 +562,13 @@ public class Calculator extends Activity
        super.onDestroy();
    }

    /**
     * Destroy the evaluator and close the underlying database.
     */
    public void destroyEvaluator() {
        mEvaluator.destroyEvaluator();
    }

    @Override
    public void onActionModeStarted(ActionMode mode) {
        super.onActionModeStarted(mode);
@@ -1140,6 +1169,9 @@ public class Calculator extends Activity
        final int formulaTextColor = mFormulaText.getCurrentTextColor();

        if (animate) {
            // Add current result to history.
            mEvaluator.preserve(true);

            mResultText.announceForAccessibility(getResources().getString(R.string.desc_eq));
            mResultText.announceForAccessibility(mResultText.getText());
            setState(CalculatorState.ANIMATE);
@@ -1157,8 +1189,6 @@ public class Calculator extends Activity
            animatorSet.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    // Add current result to history.
                    mEvaluator.preserve(true);
                    setState(CalculatorState.RESULT);
                    mCurrentAnimator = null;
                }
+10 −0
Original line number Diff line number Diff line
@@ -1864,4 +1864,14 @@ public class Evaluator implements CalculatorExpr.ExprResolver {
        sb.append(" Saved index = ").append(getSavedIndex()).append("\n");
        return sb.toString();
    }

    /**
     * Destroy the current evaluator, forcing getEvaluator to allocate a new one.
     * This is needed for testing, since Robolectric apparently doesn't let us preserve
     * an open databse across tests. Cf. https://github.com/robolectric/robolectric/issues/1890 .
     */
    public void destroyEvaluator() {
        mExprDB.close();
        evaluator = null;
    }
}