KeyMaps.java revision 08e8f322b0d93e06aaa2a15acc869dfd70791461
184614957604253d51296e06c97daced699a0a9deHans Boehm/*
284614957604253d51296e06c97daced699a0a9deHans Boehm * Copyright (C) 2015 The Android Open Source Project
384614957604253d51296e06c97daced699a0a9deHans Boehm *
484614957604253d51296e06c97daced699a0a9deHans Boehm * Licensed under the Apache License, Version 2.0 (the "License");
584614957604253d51296e06c97daced699a0a9deHans Boehm * you may not use this file except in compliance with the License.
684614957604253d51296e06c97daced699a0a9deHans Boehm * You may obtain a copy of the License at
784614957604253d51296e06c97daced699a0a9deHans Boehm *
884614957604253d51296e06c97daced699a0a9deHans Boehm *   http://www.apache.org/licenses/LICENSE-2.0
984614957604253d51296e06c97daced699a0a9deHans Boehm *
1084614957604253d51296e06c97daced699a0a9deHans Boehm * Unless required by applicable law or agreed to in writing, software
1184614957604253d51296e06c97daced699a0a9deHans Boehm * distributed under the License is distributed on an "AS IS" BASIS,
1284614957604253d51296e06c97daced699a0a9deHans Boehm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384614957604253d51296e06c97daced699a0a9deHans Boehm * See the License for the specific language governing permissions and
1484614957604253d51296e06c97daced699a0a9deHans Boehm * limitations under the License.
1584614957604253d51296e06c97daced699a0a9deHans Boehm */
1684614957604253d51296e06c97daced699a0a9deHans Boehm
1784614957604253d51296e06c97daced699a0a9deHans Boehmpackage com.android.calculator2;
1884614957604253d51296e06c97daced699a0a9deHans Boehm
1984614957604253d51296e06c97daced699a0a9deHans Boehmimport android.content.res.Resources;
2084614957604253d51296e06c97daced699a0a9deHans Boehmimport android.content.Context;
214a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport android.app.Activity;
224a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport android.util.Log;
2384614957604253d51296e06c97daced699a0a9deHans Boehmimport android.view.View;
244a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport android.widget.Button;
254a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
2684614957604253d51296e06c97daced699a0a9deHans Boehmimport java.text.DecimalFormatSymbols;
274a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport java.util.HashMap;
284a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport java.util.Locale;
2984614957604253d51296e06c97daced699a0a9deHans Boehm
30013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm// KeyMap instances are not meaningful; everything here is static.
31013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm// All functions are either pure, or are assumed to be called only from
32013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm// a single UI thread.
33013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
3484614957604253d51296e06c97daced699a0a9deHans Boehmpublic class KeyMaps {
35013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Map key id to corresponding (internationalized) display string.
36013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Pure function.
3784614957604253d51296e06c97daced699a0a9deHans Boehm    public static String toString(int id, Context context) {
3884614957604253d51296e06c97daced699a0a9deHans Boehm        Resources res = context.getResources();
3984614957604253d51296e06c97daced699a0a9deHans Boehm        switch(id) {
4084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.const_pi:         return res.getString(R.string.const_pi);
4184614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.const_e:          return res.getString(R.string.const_e);
4284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_sqrt:    	    return res.getString(R.string.op_sqrt);
4384614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_fact:          return res.getString(R.string.op_fact);
4484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.fun_sin:          return res.getString(R.string.fun_sin)
4584614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
46013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        case R.id.fun_cos:          return res.getString(R.string.fun_cos)
4784614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
4884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.fun_tan:          return res.getString(R.string.fun_tan)
4984614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
5084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.fun_arcsin:       return res.getString(R.string.fun_arcsin)
5184614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
52013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        case R.id.fun_arccos:       return res.getString(R.string.fun_arccos)
5384614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
5484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.fun_arctan:       return res.getString(R.string.fun_arctan)
5584614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
5684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.fun_ln:           return res.getString(R.string.fun_ln)
5784614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
5884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.fun_log:          return res.getString(R.string.fun_log)
5984614957604253d51296e06c97daced699a0a9deHans Boehm                                            + res.getString(R.string.lparen);
6084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.lparen:           return res.getString(R.string.lparen);
6184614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.rparen:           return res.getString(R.string.rparen);
6284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_pow:           return res.getString(R.string.op_pow);
6384614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_mul:           return res.getString(R.string.op_mul);
6484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_div:           return res.getString(R.string.op_div);
6584614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_add:	    return res.getString(R.string.op_add);
6684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_sub:           return res.getString(R.string.op_sub);
6784614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.dec_point:        return res.getString(R.string.dec_point);
6884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_0:          return res.getString(R.string.digit_0);
6984614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_1:          return res.getString(R.string.digit_1);
7084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_2:          return res.getString(R.string.digit_2);
7184614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_3:          return res.getString(R.string.digit_3);
7284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_4:          return res.getString(R.string.digit_4);
7384614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_5:          return res.getString(R.string.digit_5);
7484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_6:          return res.getString(R.string.digit_6);
7584614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_7:          return res.getString(R.string.digit_7);
7684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_8:          return res.getString(R.string.digit_8);
7784614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_9:          return res.getString(R.string.digit_9);
7884614957604253d51296e06c97daced699a0a9deHans Boehm        default:                    return "?oops?";
7984614957604253d51296e06c97daced699a0a9deHans Boehm        }
8084614957604253d51296e06c97daced699a0a9deHans Boehm    }
8184614957604253d51296e06c97daced699a0a9deHans Boehm
8284614957604253d51296e06c97daced699a0a9deHans Boehm    // Does a button id correspond to a binary operator?
83013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Pure function.
8484614957604253d51296e06c97daced699a0a9deHans Boehm    public static boolean isBinary(int id) {
8584614957604253d51296e06c97daced699a0a9deHans Boehm        switch(id) {
8684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_pow:
8784614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_mul:
8884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_div:
8984614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_add:
9084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.op_sub:
9184614957604253d51296e06c97daced699a0a9deHans Boehm            return true;
9284614957604253d51296e06c97daced699a0a9deHans Boehm        default:
9384614957604253d51296e06c97daced699a0a9deHans Boehm            return false;
9484614957604253d51296e06c97daced699a0a9deHans Boehm        }
9584614957604253d51296e06c97daced699a0a9deHans Boehm    }
9684614957604253d51296e06c97daced699a0a9deHans Boehm
9784614957604253d51296e06c97daced699a0a9deHans Boehm    // Does a button id correspond to a suffix operator?
9884614957604253d51296e06c97daced699a0a9deHans Boehm    public static boolean isSuffix(int id) {
9984614957604253d51296e06c97daced699a0a9deHans Boehm        return id == R.id.op_fact;
10084614957604253d51296e06c97daced699a0a9deHans Boehm    }
10184614957604253d51296e06c97daced699a0a9deHans Boehm
10284614957604253d51296e06c97daced699a0a9deHans Boehm    public static final int NOT_DIGIT = 10;
10384614957604253d51296e06c97daced699a0a9deHans Boehm
10408e8f322b0d93e06aaa2a15acc869dfd70791461Hans Boehm    public static final String ELLIPSIS = "\u2026";
10508e8f322b0d93e06aaa2a15acc869dfd70791461Hans Boehm
10684614957604253d51296e06c97daced699a0a9deHans Boehm    // Map key id to digit or NOT_DIGIT
107013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Pure function.
10884614957604253d51296e06c97daced699a0a9deHans Boehm    public static int digVal(int id) {
10984614957604253d51296e06c97daced699a0a9deHans Boehm        switch (id) {
11084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_0:
11184614957604253d51296e06c97daced699a0a9deHans Boehm            return 0;
11284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_1:
11384614957604253d51296e06c97daced699a0a9deHans Boehm            return 1;
11484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_2:
11584614957604253d51296e06c97daced699a0a9deHans Boehm            return 2;
11684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_3:
11784614957604253d51296e06c97daced699a0a9deHans Boehm            return 3;
11884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_4:
11984614957604253d51296e06c97daced699a0a9deHans Boehm            return 4;
12084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_5:
12184614957604253d51296e06c97daced699a0a9deHans Boehm            return 5;
12284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_6:
12384614957604253d51296e06c97daced699a0a9deHans Boehm            return 6;
12484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_7:
12584614957604253d51296e06c97daced699a0a9deHans Boehm            return 7;
12684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_8:
12784614957604253d51296e06c97daced699a0a9deHans Boehm            return 8;
12884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_9:
12984614957604253d51296e06c97daced699a0a9deHans Boehm            return 9;
13084614957604253d51296e06c97daced699a0a9deHans Boehm        default:
13184614957604253d51296e06c97daced699a0a9deHans Boehm            return NOT_DIGIT;
13284614957604253d51296e06c97daced699a0a9deHans Boehm        }
13384614957604253d51296e06c97daced699a0a9deHans Boehm    }
13484614957604253d51296e06c97daced699a0a9deHans Boehm
13584614957604253d51296e06c97daced699a0a9deHans Boehm    // Map digit to corresponding key.  Inverse of above.
136013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Pure function.
13784614957604253d51296e06c97daced699a0a9deHans Boehm    public static int keyForDigVal(int v) {
13884614957604253d51296e06c97daced699a0a9deHans Boehm        switch(v) {
13984614957604253d51296e06c97daced699a0a9deHans Boehm        case 0:
14084614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_0;
14184614957604253d51296e06c97daced699a0a9deHans Boehm        case 1:
14284614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_1;
14384614957604253d51296e06c97daced699a0a9deHans Boehm        case 2:
14484614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_2;
14584614957604253d51296e06c97daced699a0a9deHans Boehm        case 3:
14684614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_3;
14784614957604253d51296e06c97daced699a0a9deHans Boehm        case 4:
14884614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_4;
14984614957604253d51296e06c97daced699a0a9deHans Boehm        case 5:
15084614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_5;
15184614957604253d51296e06c97daced699a0a9deHans Boehm        case 6:
15284614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_6;
15384614957604253d51296e06c97daced699a0a9deHans Boehm        case 7:
15484614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_7;
15584614957604253d51296e06c97daced699a0a9deHans Boehm        case 8:
15684614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_8;
15784614957604253d51296e06c97daced699a0a9deHans Boehm        case 9:
15884614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_9;
15984614957604253d51296e06c97daced699a0a9deHans Boehm        default:
16084614957604253d51296e06c97daced699a0a9deHans Boehm            return View.NO_ID;
16184614957604253d51296e06c97daced699a0a9deHans Boehm        }
16284614957604253d51296e06c97daced699a0a9deHans Boehm    }
16384614957604253d51296e06c97daced699a0a9deHans Boehm
164013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static char mDecimalPt =
16584614957604253d51296e06c97daced699a0a9deHans Boehm                DecimalFormatSymbols.getInstance().getDecimalSeparator();
16684614957604253d51296e06c97daced699a0a9deHans Boehm
1674a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    static char mPiChar;
1684a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
1694a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    static char mFactChar;
1704a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
1714a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    static HashMap<String, Integer> sKeyValForFun;
1724a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // Key value corresponding to given function name.
1734a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // We include both localized and English names.
1744a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
175013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static HashMap<Character, String> sOutputForResultChar;
176013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        // Result string corresponding to a character in the
177013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        // calculator result.
178013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        // The string values in the map are expected to be one character
179013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        // long.
180013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
181013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static String sLocaleForMaps = "none";
182013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        // Locale string corresponding to preceding map and character
1834a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // constants.
1844a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // We recompute the map if this is not the current locale.
1854a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
186013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static Activity mActivity;  // Activity to use for looking up
187013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                                // buttons.
188013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
189013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Called only by UI thread.
190013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static void setActivity(Activity a) {
191013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        mActivity = a;
192013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    }
193013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
19484614957604253d51296e06c97daced699a0a9deHans Boehm    // Return the button id corresponding to the supplied character
19584614957604253d51296e06c97daced699a0a9deHans Boehm    // or NO_ID
1964a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Called only by UI thread.
197013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static int keyForChar(char c) {
198013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        validateMaps();
19984614957604253d51296e06c97daced699a0a9deHans Boehm        if (Character.isDigit(c)) {
20084614957604253d51296e06c97daced699a0a9deHans Boehm            int i = Character.digit(c, 10);
20184614957604253d51296e06c97daced699a0a9deHans Boehm            return KeyMaps.keyForDigVal(i);
20284614957604253d51296e06c97daced699a0a9deHans Boehm        }
20384614957604253d51296e06c97daced699a0a9deHans Boehm        switch (c) {
20484614957604253d51296e06c97daced699a0a9deHans Boehm        case '.':
20584614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.dec_point;
20684614957604253d51296e06c97daced699a0a9deHans Boehm        case '-':
20784614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.op_sub;
20884614957604253d51296e06c97daced699a0a9deHans Boehm        case '+':
20984614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.op_add;
21084614957604253d51296e06c97daced699a0a9deHans Boehm        case '*':
21184614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.op_mul;
21284614957604253d51296e06c97daced699a0a9deHans Boehm        case '/':
21384614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.op_div;
2144a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // TODO: We have an issue if any of the localized function
2154a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // names start with 'e' or 'p'.  That doesn't currently appear
2164a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // to be the case.  In fact the first letters of the Latin
2174a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        // allphabet ones seem rather predictable.
21884614957604253d51296e06c97daced699a0a9deHans Boehm        case 'e':
2194a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        case 'E':
22084614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.const_e;
2214a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        case 'p':
2224a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        case 'P':
2234a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            return R.id.const_pi;
22484614957604253d51296e06c97daced699a0a9deHans Boehm        case '^':
22584614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.op_pow;
2264a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        case '!':
2274a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            return R.id.op_fact;
2284a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        case '(':
2294a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            return R.id.lparen;
2304a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        case ')':
2314a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            return R.id.rparen;
23284614957604253d51296e06c97daced699a0a9deHans Boehm        default:
233013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            if (c == mDecimalPt) return R.id.dec_point;
2344a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            if (c == mPiChar) return R.id.const_pi;
2354a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm                // pi is not translated, but it might be typable on
2364a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm                // a Greek keyboard, so we check ...
23784614957604253d51296e06c97daced699a0a9deHans Boehm            return View.NO_ID;
23884614957604253d51296e06c97daced699a0a9deHans Boehm        }
23984614957604253d51296e06c97daced699a0a9deHans Boehm    }
2404a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
2414a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Add information corresponding to the given button id to
2424a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // sKeyValForFun.
243013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static void addButtonToFunMap(int button_id) {
244013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        Button button = (Button)mActivity.findViewById(button_id);
2454a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        sKeyValForFun.put(button.getText().toString(), button_id);
2464a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    }
2474a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
248013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Ditto, but for sOutputForResultChar.
249013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static void addButtonToOutputMap(char c, int button_id) {
250013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        Button button = (Button)mActivity.findViewById(button_id);
251013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        sOutputForResultChar.put(c, button.getText().toString());
252013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    }
253013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
2544a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Ensure that the preceding map and character constants are
2554a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // initialized and correspond to the current locale.
2564a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Called only by a single thread, namely the UI thread.
257013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static void validateMaps() {
2584a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        Locale locale = Locale.getDefault();
2594a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        String lname = locale.toString();
260013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        if (lname != sLocaleForMaps) {
2614a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            Log.v ("Calculator", "Setting local to: " + lname);
2624a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun = new HashMap<String, Integer>();
2634a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("sin", R.id.fun_sin);
2644a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("cos", R.id.fun_cos);
2654a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("tan", R.id.fun_tan);
2664a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("arcsin", R.id.fun_arcsin);
2674a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("arccos", R.id.fun_arccos);
2684a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("arctan", R.id.fun_arctan);
2694a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("asin", R.id.fun_arcsin);
2704a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("acos", R.id.fun_arccos);
2714a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("atan", R.id.fun_arctan);
2724a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("ln", R.id.fun_ln);
2734a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("log", R.id.fun_log);
2744a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("sqrt", R.id.op_sqrt); // special treatment
275013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_sin);
276013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_cos);
277013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_tan);
278013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_arcsin);
279013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_arccos);
280013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_arctan);
281013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_ln);
282013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_log);
2834a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
2844a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            // Set locale-dependent character "constants"
285013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            mDecimalPt =
2864a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm                DecimalFormatSymbols.getInstance().getDecimalSeparator();
287013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            Resources res = mActivity.getResources();
2884a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            mPiChar = mFactChar = 0;
2894a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            String piString = res.getString(R.string.const_pi);
2904a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            if (piString.length() == 1) mPiChar = piString.charAt(0);
2914a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            String factString = res.getString(R.string.op_fact);
2924a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            if (factString.length() == 1) mFactChar = factString.charAt(0);
2934a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
294013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar = new HashMap<Character, String>();
295013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('e', "E");
296013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('E', "E");
297013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('.', String.valueOf(mDecimalPt));
29808e8f322b0d93e06aaa2a15acc869dfd70791461Hans Boehm            sOutputForResultChar.put(ELLIPSIS.charAt(0), ELLIPSIS);
299013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('/', "/");
300013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                        // Translate numbers for fraction display, but not
301013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                        // the separating slash, which appears to be
302013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                        // universal.
303013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToOutputMap('-', R.id.op_sub);
304013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            for (int i = 0; i <= 9; ++i) {
305013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                addButtonToOutputMap((char)('0' + i), keyForDigVal(i));
306013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            }
307013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
308013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sLocaleForMaps = lname;
309013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
3104a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        }
3114a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    }
3124a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
3134a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Return function button id for the substring of s starting
3144a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // at pos and ending with the next "(".
3154a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Return NO_ID if there is none.
3164a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // We check for both standard English names and localized
3174a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // button labels, though those don't seem to differ much.
3184a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Called only by a single thread, namely the UI thread.
319013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static int funForString(String s, int pos) {
320013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        validateMaps();
3214a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        int parenPos = s.indexOf('(', pos);
3224a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        if (parenPos != -1) {
3234a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            String funString = s.substring(pos, parenPos);
3244a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            Integer keyValue = sKeyValForFun.get(funString);
3254a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            if (keyValue == null) return View.NO_ID;
3264a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            return keyValue;
3274a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        }
3284a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        return View.NO_ID;
3294a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    }
330013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
331013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    // Called only by UI thread.
332013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static String translateResult(String s) {
333013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        StringBuilder result = new StringBuilder();
334013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        int len = s.length();
335013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        validateMaps();
336013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        for (int i = 0; i < len; ++i) {
337013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            char c = s.charAt(i);
338013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            String translation = sOutputForResultChar.get(c);
339013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            if (translation == null) {
340013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                // Should not get here.
341013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                Log.v("Calculator", "Bad character:" + c);
342013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                result.append(String.valueOf(c));
343013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            } else {
344013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                result.append(translation);
345013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            }
346013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        }
347013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        return result.toString();
348013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    }
349013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
35084614957604253d51296e06c97daced699a0a9deHans Boehm}
351