Internationalize display again. Plus minor cleanups.
Adds code for internationalization of numeric results, both in the
result and formula displays.
Update some now obsolete TODO comments.
Change-Id: I42731bf87f5488375457f1c5c094c7f0d17b71da
diff --git a/src/com/android/calculator2/KeyMaps.java b/src/com/android/calculator2/KeyMaps.java
index a7622cb..99f4124 100644
--- a/src/com/android/calculator2/KeyMaps.java
+++ b/src/com/android/calculator2/KeyMaps.java
@@ -27,8 +27,13 @@
import java.util.HashMap;
import java.util.Locale;
+// KeyMap instances are not meaningful; everything here is static.
+// All functions are either pure, or are assumed to be called only from
+// a single UI thread.
+
public class KeyMaps {
- // Map key id to corresponding (internationalized) display string
+ // Map key id to corresponding (internationalized) display string.
+ // Pure function.
public static String toString(int id, Context context) {
Resources res = context.getResources();
switch(id) {
@@ -38,13 +43,13 @@
case R.id.op_fact: return res.getString(R.string.op_fact);
case R.id.fun_sin: return res.getString(R.string.fun_sin)
+ res.getString(R.string.lparen);
- case R.id.fun_cos: return res.getString(R.string.fun_cos)
+ case R.id.fun_cos: return res.getString(R.string.fun_cos)
+ res.getString(R.string.lparen);
case R.id.fun_tan: return res.getString(R.string.fun_tan)
+ res.getString(R.string.lparen);
case R.id.fun_arcsin: return res.getString(R.string.fun_arcsin)
+ res.getString(R.string.lparen);
- case R.id.fun_arccos: return res.getString(R.string.fun_arccos)
+ case R.id.fun_arccos: return res.getString(R.string.fun_arccos)
+ res.getString(R.string.lparen);
case R.id.fun_arctan: return res.getString(R.string.fun_arctan)
+ res.getString(R.string.lparen);
@@ -75,6 +80,7 @@
}
// Does a button id correspond to a binary operator?
+ // Pure function.
public static boolean isBinary(int id) {
switch(id) {
case R.id.op_pow:
@@ -96,6 +102,7 @@
public static final int NOT_DIGIT = 10;
// Map key id to digit or NOT_DIGIT
+ // Pure function.
public static int digVal(int id) {
switch (id) {
case R.id.digit_0:
@@ -124,6 +131,7 @@
}
// Map digit to corresponding key. Inverse of above.
+ // Pure function.
public static int keyForDigVal(int v) {
switch(v) {
case 0:
@@ -151,7 +159,7 @@
}
}
- static char decimalPt =
+ static char mDecimalPt =
DecimalFormatSymbols.getInstance().getDecimalSeparator();
static char mPiChar;
@@ -162,16 +170,30 @@
// Key value corresponding to given function name.
// We include both localized and English names.
- static String sLocaleForFunMap = "none";
- // Locale string corresponding to preceding ma and character
+ static HashMap<Character, String> sOutputForResultChar;
+ // Result string corresponding to a character in the
+ // calculator result.
+ // The string values in the map are expected to be one character
+ // long.
+
+ static String sLocaleForMaps = "none";
+ // Locale string corresponding to preceding map and character
// constants.
// We recompute the map if this is not the current locale.
+ static Activity mActivity; // Activity to use for looking up
+ // buttons.
+
+ // Called only by UI thread.
+ public static void setActivity(Activity a) {
+ mActivity = a;
+ }
+
// Return the button id corresponding to the supplied character
// or NO_ID
// Called only by UI thread.
- public static int keyForChar(char c, Activity a) {
- validateFunMap(a);
+ public static int keyForChar(char c) {
+ validateMaps();
if (Character.isDigit(c)) {
int i = Character.digit(c, 10);
return KeyMaps.keyForDigVal(i);
@@ -206,7 +228,7 @@
case ')':
return R.id.rparen;
default:
- if (c == decimalPt) return R.id.dec_point;
+ if (c == mDecimalPt) return R.id.dec_point;
if (c == mPiChar) return R.id.const_pi;
// pi is not translated, but it might be typable on
// a Greek keyboard, so we check ...
@@ -216,18 +238,24 @@
// Add information corresponding to the given button id to
// sKeyValForFun.
- static void addButton(int button_id, Activity a) {
- Button button = (Button)a.findViewById(button_id);
+ static void addButtonToFunMap(int button_id) {
+ Button button = (Button)mActivity.findViewById(button_id);
sKeyValForFun.put(button.getText().toString(), button_id);
}
+ // Ditto, but for sOutputForResultChar.
+ static void addButtonToOutputMap(char c, int button_id) {
+ Button button = (Button)mActivity.findViewById(button_id);
+ 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.
- static void validateFunMap(Activity a) {
+ static void validateMaps() {
Locale locale = Locale.getDefault();
String lname = locale.toString();
- if (lname != sLocaleForFunMap) {
+ if (lname != sLocaleForMaps) {
Log.v ("Calculator", "Setting local to: " + lname);
sKeyValForFun = new HashMap<String, Integer>();
sKeyValForFun.put("sin", R.id.fun_sin);
@@ -242,26 +270,42 @@
sKeyValForFun.put("ln", R.id.fun_ln);
sKeyValForFun.put("log", R.id.fun_log);
sKeyValForFun.put("sqrt", R.id.op_sqrt); // special treatment
- addButton(R.id.fun_sin, a);
- addButton(R.id.fun_cos, a);
- addButton(R.id.fun_tan, a);
- addButton(R.id.fun_arcsin, a);
- addButton(R.id.fun_arccos, a);
- addButton(R.id.fun_arctan, a);
- addButton(R.id.fun_ln, a);
- addButton(R.id.fun_log, a);
+ addButtonToFunMap(R.id.fun_sin);
+ addButtonToFunMap(R.id.fun_cos);
+ addButtonToFunMap(R.id.fun_tan);
+ addButtonToFunMap(R.id.fun_arcsin);
+ addButtonToFunMap(R.id.fun_arccos);
+ addButtonToFunMap(R.id.fun_arctan);
+ addButtonToFunMap(R.id.fun_ln);
+ addButtonToFunMap(R.id.fun_log);
// Set locale-dependent character "constants"
- decimalPt =
+ mDecimalPt =
DecimalFormatSymbols.getInstance().getDecimalSeparator();
- Resources res = a.getResources();
+ Resources res = mActivity.getResources();
mPiChar = mFactChar = 0;
String piString = res.getString(R.string.const_pi);
if (piString.length() == 1) mPiChar = piString.charAt(0);
String factString = res.getString(R.string.op_fact);
if (factString.length() == 1) mFactChar = factString.charAt(0);
- sLocaleForFunMap = lname;
+ sOutputForResultChar = new HashMap<Character, String>();
+ sOutputForResultChar.put('e', "E");
+ sOutputForResultChar.put('E', "E");
+ sOutputForResultChar.put('.', String.valueOf(mDecimalPt));
+ sOutputForResultChar.put(res.getString(R.string.ellipsis).charAt(0),
+ res.getString(R.string.ellipsis));
+ sOutputForResultChar.put('/', "/");
+ // Translate numbers for fraction display, but not
+ // the separating slash, which appears to be
+ // universal.
+ addButtonToOutputMap('-', R.id.op_sub);
+ for (int i = 0; i <= 9; ++i) {
+ addButtonToOutputMap((char)('0' + i), keyForDigVal(i));
+ }
+
+ sLocaleForMaps = lname;
+
}
}
@@ -271,8 +315,8 @@
// We check for both standard English names and localized
// button labels, though those don't seem to differ much.
// Called only by a single thread, namely the UI thread.
- public static int funForString(String s, int pos, Activity a) {
- validateFunMap(a);
+ public static int funForString(String s, int pos) {
+ validateMaps();
int parenPos = s.indexOf('(', pos);
if (parenPos != -1) {
String funString = s.substring(pos, parenPos);
@@ -282,4 +326,24 @@
}
return View.NO_ID;
}
+
+ // Called only by UI thread.
+ public static String translateResult(String s) {
+ StringBuilder result = new StringBuilder();
+ int len = s.length();
+ validateMaps();
+ for (int i = 0; i < len; ++i) {
+ char c = s.charAt(i);
+ String translation = sOutputForResultChar.get(c);
+ if (translation == null) {
+ // Should not get here.
+ Log.v("Calculator", "Bad character:" + c);
+ result.append(String.valueOf(c));
+ } else {
+ result.append(translation);
+ }
+ }
+ return result.toString();
+ }
+
}