Merge "Initialize the RecyclerView as INVISIBLE." into ub-calculator-euler
diff --git a/res/layout/history_item.xml b/res/layout/history_item.xml
index 87ef83b..f3e05c3 100644
--- a/res/layout/history_item.xml
+++ b/res/layout/history_item.xml
@@ -27,6 +27,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fontFamily="sans-serif-medium"
+ android:paddingStart="@dimen/history_item_text_padding_start"
+ android:paddingEnd="@dimen/history_item_text_padding_end"
android:text="@string/title_current_expression"
android:textColor="?android:attr/colorAccent"
android:textSize="14dp" />
diff --git a/res/layout/pad_numeric.xml b/res/layout/pad_numeric.xml
index e9f7c9b..2f301e8 100644
--- a/res/layout/pad_numeric.xml
+++ b/res/layout/pad_numeric.xml
@@ -91,7 +91,6 @@
android:id="@+id/dec_point"
style="@style/PadButtonStyle.Numeric"
android:contentDescription="@string/desc_dec_point"
- android:text="@string/dec_point"
app:layout_row="3"
app:layout_column="0" />
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index f13a9ed..2c19468 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -79,6 +79,7 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
+import java.text.DecimalFormatSymbols;
import static com.android.calculator2.CalculatorFormula.OnFormulaContextMenuClickListener;
@@ -323,10 +324,13 @@
mPadViewPager = (ViewPager) findViewById(R.id.pad_pager);
mDeleteButton = findViewById(R.id.del);
mClearButton = findViewById(R.id.clr);
- mEqualButton = findViewById(R.id.pad_numeric).findViewById(R.id.eq);
+ final View numberPad = findViewById(R.id.pad_numeric);
+ mEqualButton = numberPad.findViewById(R.id.eq);
if (mEqualButton == null || mEqualButton.getVisibility() != View.VISIBLE) {
mEqualButton = findViewById(R.id.pad_operator).findViewById(R.id.eq);
}
+ final TextView decimalPointButton = (TextView) numberPad.findViewById(R.id.dec_point);
+ decimalPointButton.setText(getDecimalSeparator());
mInverseToggle = (TextView) findViewById(R.id.toggle_inv);
mModeToggle = (TextView) findViewById(R.id.toggle_mode);
@@ -402,16 +406,15 @@
showAndMaybeHideToolbar();
}
+ redisplayFormula();
if (mCurrentState != CalculatorState.INPUT) {
// Just reevaluate.
- redisplayFormula();
setState(CalculatorState.INIT);
// Request evaluation when we know display width.
- mResultText.setShouldRequireResult(true, this);
+ mResultText.setShouldEvaluateResult(CalculatorResult.SHOULD_REQUIRE, this);
} else {
// This resultText will explicitly call evaluateAndNotify when ready.
- mResultText.setShouldRequireResult(false, null);
- redisplayAfterFormulaChange();
+ mResultText.setShouldEvaluateResult(CalculatorResult.SHOULD_EVALUATE, this);
}
// TODO: We're currently not saving and restoring scroll position.
// We probably should. Details may require care to deal with:
@@ -457,7 +460,7 @@
if (mCurrentState != state) {
if (state == CalculatorState.INPUT) {
// We'll explicitly request evaluation from now on.
- mResultText.setShouldRequireResult(false, null);
+ mResultText.setShouldEvaluateResult(CalculatorResult.SHOULD_NOT_EVALUATE, null);
restoreDisplayPositions();
}
mCurrentState = state;
@@ -722,6 +725,13 @@
addKeyToExpr(id);
}
+ public void evaluateInstantIfNecessary() {
+ if (mCurrentState == CalculatorState.INPUT
+ && mEvaluator.getExpr(Evaluator.MAIN_INDEX).hasInterestingOps()) {
+ mEvaluator.evaluateAndNotify(Evaluator.MAIN_INDEX, this, mResultText);
+ }
+ }
+
private void redisplayAfterFormulaChange() {
// TODO: Could do this more incrementally.
redisplayFormula();
@@ -731,9 +741,7 @@
// Force reevaluation when text is deleted, even if expression is unchanged.
mEvaluator.touch();
} else {
- if (mEvaluator.getExpr(Evaluator.MAIN_INDEX).hasInterestingOps()) {
- mEvaluator.evaluateAndNotify(Evaluator.MAIN_INDEX, this, mResultText);
- }
+ evaluateInstantIfNecessary();
}
}
@@ -806,9 +814,8 @@
showAndMaybeHideToolbar();
setState(CalculatorState.INPUT);
mResultText.clear();
- if (!haveUnprocessed()
- && mEvaluator.getExpr(Evaluator.MAIN_INDEX).hasInterestingOps()) {
- mEvaluator.evaluateAndNotify(mEvaluator.MAIN_INDEX, this, mResultText);
+ if (!haveUnprocessed()) {
+ evaluateInstantIfNecessary();
}
return;
default:
@@ -1352,6 +1359,15 @@
}
/**
+ * Since we only support LTR format, using the RTL comma does not make sense.
+ */
+ private String getDecimalSeparator() {
+ final char defaultSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
+ final char rtlComma = '\u066b';
+ return defaultSeparator == rtlComma ? "," : String.valueOf(defaultSeparator);
+ }
+
+ /**
* Clean up animation for context menu.
*/
@Override
diff --git a/src/com/android/calculator2/CalculatorResult.java b/src/com/android/calculator2/CalculatorResult.java
index 0b399c4..5a23c01 100644
--- a/src/com/android/calculator2/CalculatorResult.java
+++ b/src/com/android/calculator2/CalculatorResult.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
+import android.support.annotation.IntDef;
import android.support.v4.content.ContextCompat;
import android.support.v4.os.BuildCompat;
import android.text.Layout;
@@ -45,6 +46,9 @@
import android.widget.OverScroller;
import android.widget.Toast;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
// A text widget that is "infinitely" scrollable to the right,
// and obtains the text to display via a callback to Logic.
public class CalculatorResult extends AlignedTextView implements MenuItem.OnMenuItemClickListener,
@@ -114,7 +118,14 @@
private float mNoEllipsisCredit;
// Fraction of digit width saved by both replacing ellipsis with digit
// and avoiding scientific notation.
- private boolean mShouldRequireResult = true;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SHOULD_REQUIRE, SHOULD_EVALUATE, SHOULD_NOT_EVALUATE})
+ public @interface EvaluationRequest {}
+ public static final int SHOULD_REQUIRE = 2;
+ public static final int SHOULD_EVALUATE = 1;
+ public static final int SHOULD_NOT_EVALUATE = 0;
+ @EvaluationRequest private int mEvaluationRequest = SHOULD_REQUIRE;
+ // Should we evaluate when layout completes, and how?
private Evaluator.EvaluationListener mEvaluationListener = this;
// Listener to use if/when evaluation is requested.
public static final int MAX_LEADING_ZEROES = 6;
@@ -313,17 +324,26 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (mEvaluator != null && mShouldRequireResult) {
+ if (mEvaluator != null && mEvaluationRequest != SHOULD_NOT_EVALUATE) {
final CalculatorExpr expr = mEvaluator.getExpr(mIndex);
if (expr != null && expr.hasInterestingOps()) {
- mEvaluator.requireResult(mIndex, mEvaluationListener, this);
+ if (mEvaluationRequest == SHOULD_REQUIRE) {
+ mEvaluator.requireResult(mIndex, mEvaluationListener, this);
+ } else {
+ mEvaluator.evaluateAndNotify(mIndex, mEvaluationListener, this);
+ }
}
}
}
- public void setShouldRequireResult(boolean should, Evaluator.EvaluationListener listener) {
+ /**
+ * Specify whether we should evaluate result on layout.
+ * @param should one of SHOULD_REQUIRE, SHOULD_EVALUATE, SHOULD_NOT_EVALUATE
+ */
+ public void setShouldEvaluateResult(@EvaluationRequest int request,
+ Evaluator.EvaluationListener listener) {
mEvaluationListener = listener;
- mShouldRequireResult = should;
+ mEvaluationRequest = request;
}
// From Evaluator.CharMetricsInfo.
@@ -413,14 +433,14 @@
* Add the result to the value currently in memory.
*/
public void onMemoryAdd() {
- mEvaluator.addToMemory(Evaluator.MAIN_INDEX);
+ mEvaluator.addToMemory(mIndex);
}
/**
* Subtract the result from the value currently in memory.
*/
public void onMemorySubtract() {
- mEvaluator.subtractFromMemory(Evaluator.MAIN_INDEX);
+ mEvaluator.subtractFromMemory(mIndex);
}
/**
@@ -1113,4 +1133,4 @@
return false;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/calculator2/Evaluator.java b/src/com/android/calculator2/Evaluator.java
index 77c762d..df36d49 100644
--- a/src/com/android/calculator2/Evaluator.java
+++ b/src/com/android/calculator2/Evaluator.java
@@ -240,10 +240,10 @@
// The largest number of digits to the right of the decimal point to which we will evaluate to
// compute proper scientific notation for values close to zero. Chosen to ensure that we
- // always to better than IEEE double precision at identifying nonzeros.
- // This used only when we cannot a prior determine the most significant digit position, as
+ // always to better than IEEE double precision at identifying nonzeros. And then some.
+ // This is used only when we cannot a priori determine the most significant digit position, as
// we always can if we have a rational representation.
- private static final int MAX_MSD_PREC_OFFSET = 320;
+ private static final int MAX_MSD_PREC_OFFSET = 1100;
// If we can replace an exponent by this many leading zeroes, we do so. Also used in
// estimating exponent size for truncating short representation.
@@ -430,7 +430,7 @@
* Maximum result bit length for unrequested, speculative evaluations.
* Also used to bound evaluation precision for small non-zero fractions.
*/
- private static final int QUICK_MAX_RESULT_BITS = 50000;
+ private static final int QUICK_MAX_RESULT_BITS = 150000;
private void displayTimeoutMessage(boolean longTimeout) {
AlertDialogFragment.showMessageDialog(mActivity, R.string.dialog_timeout,
diff --git a/src/com/android/calculator2/HistoryFragment.java b/src/com/android/calculator2/HistoryFragment.java
index f0a5ea3..b8682ce 100644
--- a/src/com/android/calculator2/HistoryFragment.java
+++ b/src/com/android/calculator2/HistoryFragment.java
@@ -200,6 +200,9 @@
mEvaluator.cancelAll(true);
super.onDestroy();
+ // FIXME: There are probably better ways to do this. But we can end up cancelling
+ // an in-progress evaluation for the main expression that we have to restart.
+ ((Calculator)(getActivity())).evaluateInstantIfNecessary();
}
private void initializeController() {
diff --git a/src/com/android/calculator2/KeyMaps.java b/src/com/android/calculator2/KeyMaps.java
index c78cf2e..cdfe4e4 100644
--- a/src/com/android/calculator2/KeyMaps.java
+++ b/src/com/android/calculator2/KeyMaps.java
@@ -480,10 +480,10 @@
private static HashMap<Character, String> sOutputForResultChar;
/**
- * Locale string corresponding to preceding map and character constants.
+ * Locale corresponding to preceding map and character constants.
* We recompute the map if this is not the current locale.
*/
- private static String sLocaleForMaps = "none";
+ private static Locale sLocaleForMaps = null;
/**
* Activity to use for looking up buttons.
@@ -567,14 +567,14 @@
sOutputForResultChar.put(c, button.getText().toString());
}
- // Ensure that the preceding map and character constants are
- // initialized and correspond to the current locale.
- // Called only by a single thread, namely the UI thread.
+ /**
+ * Ensure that the preceding map and character constants correspond to the current locale.
+ * Called only by UI thread.
+ */
static void validateMaps() {
Locale locale = Locale.getDefault();
- String lname = locale.toString();
- if (lname != sLocaleForMaps) {
- Log.v ("Calculator", "Setting local to: " + lname);
+ if (!locale.equals(sLocaleForMaps)) {
+ Log.v ("Calculator", "Setting locale to: " + locale.toLanguageTag());
sKeyValForFun = new HashMap<String, Integer>();
sKeyValForFun.put("sin", R.id.fun_sin);
sKeyValForFun.put("cos", R.id.fun_cos);
@@ -631,7 +631,7 @@
addButtonToOutputMap((char)('0' + i), keyForDigVal(i));
}
- sLocaleForMaps = lname;
+ sLocaleForMaps = locale;
}
}