summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJustin Klaassen <justinklaassen@google.com>2015-05-28 11:13:17 -0700
committerJustin Klaassen <justinklaassen@google.com>2015-05-28 11:13:17 -0700
commite2711cbb1569ab6c7a7c4506505ec403286d5ab4 (patch)
tree6ca153bc6740161b51e874695eb3a0c0fc5bc57e /src
parent4af8dbed0dd2d1df47da6fc98a43ca34d6f7b351 (diff)
downloadandroid_packages_apps_ExactCalculator-e2711cbb1569ab6c7a7c4506505ec403286d5ab4.tar.gz
android_packages_apps_ExactCalculator-e2711cbb1569ab6c7a7c4506505ec403286d5ab4.tar.bz2
android_packages_apps_ExactCalculator-e2711cbb1569ab6c7a7c4506505ec403286d5ab4.zip
Update advanced pad layout
Bug: 7263319 Bug: 20841915 - Switch to using GridLayout instead of custom ViewGroup. - Added '%' operator button (Note: evaluation support WIP). Change-Id: I0d07f01fe4224c43e53c916b034362d906bea405
Diffstat (limited to 'src')
-rw-r--r--src/com/android/calculator2/Calculator.java91
-rw-r--r--src/com/android/calculator2/CalculatorExpr.java5
-rw-r--r--src/com/android/calculator2/CalculatorPadLayout.java126
-rw-r--r--src/com/android/calculator2/Evaluator.java14
-rw-r--r--src/com/android/calculator2/KeyMaps.java79
5 files changed, 122 insertions, 193 deletions
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index e2c006c..0c96958 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -174,7 +174,12 @@ public class Calculator extends Activity
private View mDeleteButton;
private View mClearButton;
private View mEqualButton;
- private TextView mModeButton;
+
+ private TextView mInverseToggle;
+ private TextView mModeToggle;
+
+ private View[] mInvertableButtons;
+ private View[] mInverseButtons;
private View mCurrentButton;
private Animator mCurrentAnimator;
@@ -193,7 +198,7 @@ public class Calculator extends Activity
getActionBar().setDisplayOptions(0);
mDisplayView = findViewById(R.id.display);
- mModeView = (TextView) findViewById(R.id.deg_rad);
+ mModeView = (TextView) findViewById(R.id.mode);
mFormulaText = (CalculatorText) findViewById(R.id.formula);
mResult = (CalculatorResult) findViewById(R.id.result);
@@ -204,7 +209,20 @@ public class Calculator extends Activity
if (mEqualButton == null || mEqualButton.getVisibility() != View.VISIBLE) {
mEqualButton = findViewById(R.id.pad_operator).findViewById(R.id.eq);
}
- mModeButton = (TextView) findViewById(R.id.mode_deg_rad);
+
+ mInverseToggle = (TextView) findViewById(R.id.toggle_inv);
+ mModeToggle = (TextView) findViewById(R.id.toggle_mode);
+
+ mInvertableButtons = new View[] {
+ findViewById(R.id.fun_sin),
+ findViewById(R.id.fun_cos),
+ findViewById(R.id.fun_tan)
+ };
+ mInverseButtons = new View[] {
+ findViewById(R.id.fun_arcsin),
+ findViewById(R.id.fun_arccos),
+ findViewById(R.id.fun_arctan)
+ };
mEvaluator = new Evaluator(this, mResult);
mResult.setEvaluator(mEvaluator);
@@ -232,11 +250,15 @@ public class Calculator extends Activity
mCurrentState = CalculatorState.INPUT;
mEvaluator.clear();
}
+
mFormulaText.setOnKeyListener(mFormulaOnKeyListener);
mFormulaText.setOnTextSizeChangeListener(this);
mFormulaText.setPasteListener(this);
mDeleteButton.setOnLongClickListener(this);
- updateDegreeMode(mEvaluator.getDegreeMode());
+
+ onInverseToggled(mInverseToggle.isSelected());
+ onModeChanged(mEvaluator.getDegreeMode());
+
if (mCurrentState != CalculatorState.INPUT) {
// Just reevaluate.
redisplayFormula();
@@ -344,18 +366,49 @@ public class Calculator extends Activity
}
}
- // Update the top corner degree/radian display and mode button
- // to reflect the indicated current degree mode (true = degrees)
- // TODO: Hide the top corner display until the advanced panel is exposed.
- private void updateDegreeMode(boolean dm) {
- if (dm) {
+ /**
+ * Invoked whenever the inverse button is toggled to update the UI.
+ *
+ * @param showInverse {@code true} if inverse functions should be shown
+ */
+ private void onInverseToggled(boolean showInverse) {
+ if (showInverse) {
+ mInverseToggle.setContentDescription(getString(R.string.desc_inv_on));
+ for (View invertableButton : mInvertableButtons) {
+ invertableButton.setVisibility(View.GONE);
+ }
+ for (View inverseButton : mInverseButtons) {
+ inverseButton.setVisibility(View.VISIBLE);
+ }
+ } else {
+ mInverseToggle.setContentDescription(getString(R.string.desc_inv_off));
+ for (View invertableButton : mInvertableButtons) {
+ invertableButton.setVisibility(View.VISIBLE);
+ }
+ for (View inverseButton : mInverseButtons) {
+ inverseButton.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ /**
+ * Invoked whenever the deg/rad mode may have changed to update the UI.
+ *
+ * @param degreeMode {@code true} if in degree mode
+ */
+ private void onModeChanged(boolean degreeMode) {
+ if (degreeMode) {
mModeView.setText(R.string.mode_deg);
- mModeButton.setText(R.string.mode_rad);
- mModeButton.setContentDescription(getString(R.string.desc_mode_rad));
+ mModeView.setContentDescription(getString(R.string.desc_mode_deg));
+
+ mModeToggle.setText(R.string.mode_rad);
+ mModeToggle.setContentDescription(getString(R.string.desc_switch_rad));
} else {
mModeView.setText(R.string.mode_rad);
- mModeButton.setText(R.string.mode_deg);
- mModeButton.setContentDescription(getString(R.string.desc_mode_deg));
+ mModeView.setContentDescription(getString(R.string.desc_mode_rad));
+
+ mModeToggle.setText(R.string.mode_deg);
+ mModeToggle.setContentDescription(getString(R.string.desc_switch_deg));
}
}
@@ -413,15 +466,21 @@ public class Calculator extends Activity
case R.id.clr:
onClear();
break;
- case R.id.mode_deg_rad:
- boolean mode = !mEvaluator.getDegreeMode();
- updateDegreeMode(mode);
+ case R.id.toggle_inv:
+ final boolean selected = !mInverseToggle.isSelected();
+ mInverseToggle.setSelected(selected);
+ onInverseToggled(selected);
+ break;
+ case R.id.toggle_mode:
+ final boolean mode = !mEvaluator.getDegreeMode();
if (mCurrentState == CalculatorState.RESULT) {
mEvaluator.collapse(); // Capture result evaluated in old mode
redisplayFormula();
}
// In input mode, we reinterpret already entered trig functions.
mEvaluator.setDegreeMode(mode);
+ onModeChanged(mode);
+
setState(CalculatorState.INPUT);
mResult.clear();
if (mEvaluator.getExpr().hasInterestingOps()) {
diff --git a/src/com/android/calculator2/CalculatorExpr.java b/src/com/android/calculator2/CalculatorExpr.java
index 05afb49..e5be4b9 100644
--- a/src/com/android/calculator2/CalculatorExpr.java
+++ b/src/com/android/calculator2/CalculatorExpr.java
@@ -19,8 +19,6 @@ package com.android.calculator2;
import com.hp.creals.CR;
import com.hp.creals.UnaryCRFunction;
-import com.hp.creals.PrecisionOverflowError;
-import com.hp.creals.AbortedError;
import android.content.Context;
import android.util.Log;
@@ -29,7 +27,6 @@ import java.math.BigInteger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
-import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
@@ -72,7 +69,7 @@ class CalculatorExpr {
}
@Override
public String toString(Context context) {
- return KeyMaps.toString(mId, context);
+ return KeyMaps.toString(context, mId);
}
@Override
TokenKind kind() { return TokenKind.OPERATOR; }
diff --git a/src/com/android/calculator2/CalculatorPadLayout.java b/src/com/android/calculator2/CalculatorPadLayout.java
deleted file mode 100644
index 3ee6339..0000000
--- a/src/com/android/calculator2/CalculatorPadLayout.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.calculator2;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * A layout that places children in an evenly distributed grid based on the specified
- * {@link android.R.attr#columnCount} and {@link android.R.attr#rowCount} attributes.
- */
-public class CalculatorPadLayout extends ViewGroup {
-
- private int mRowCount;
- private int mColumnCount;
-
- public CalculatorPadLayout(Context context) {
- this(context, null);
- }
-
- public CalculatorPadLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public CalculatorPadLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- final TypedArray a = context.obtainStyledAttributes(attrs,
- new int[] { android.R.attr.rowCount, android.R.attr.columnCount }, defStyle, 0);
- mRowCount = a.getInt(0, 1);
- mColumnCount = a.getInt(1, 1);
-
- a.recycle();
- }
-
- @Override
- public boolean shouldDelayChildPressedState() {
- return false;
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- final int paddingLeft = getPaddingLeft();
- final int paddingRight = getPaddingRight();
- final int paddingTop = getPaddingTop();
- final int paddingBottom = getPaddingBottom();
-
- final boolean isRTL = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
- int columnCount = mColumnCount;
- int columnWidth = (right - left - paddingLeft - paddingRight) / columnCount;
- final int rowHeight = (bottom - top - paddingTop - paddingBottom) / mRowCount;
-
- int rowIndex = 0, columnIndex = 0;
- for (int childIndex = 0; childIndex < getChildCount(); ++childIndex) {
- final View childView = getChildAt(childIndex);
- if (childView.getVisibility() == View.GONE) {
- continue;
- }
-
- final MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
-
- final int childTop = paddingTop + lp.topMargin + rowIndex * rowHeight;
- final int childBottom = childTop - lp.topMargin - lp.bottomMargin + rowHeight;
- final int childLeft = paddingLeft + lp.leftMargin +
- (isRTL ? (columnCount - 1) - columnIndex : columnIndex) * columnWidth;
- final int childRight = childLeft - lp.leftMargin - lp.rightMargin + columnWidth;
-
- final int childWidth = childRight - childLeft;
- final int childHeight = childBottom - childTop;
- if (childWidth != childView.getMeasuredWidth() ||
- childHeight != childView.getMeasuredHeight()) {
- childView.measure(
- MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
- }
- childView.layout(childLeft, childTop, childRight, childBottom);
-
- columnIndex = (columnIndex + 1) % columnCount;
- if (columnIndex == 0 && rowIndex + 1 < mRowCount) {
- rowIndex++;
- if (rowIndex + 1 == mRowCount) {
- // Distribute the remainder evenly in the last row.
- columnCount = getChildCount() - childIndex - 1;
- columnWidth = (right - left - paddingLeft - paddingRight) / columnCount;
- }
- }
- }
- }
-
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new MarginLayoutParams(getContext(), attrs);
- }
-
- @Override
- protected LayoutParams generateDefaultLayoutParams() {
- return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- }
-
- @Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new MarginLayoutParams(p);
- }
-
- @Override
- protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
- return p instanceof MarginLayoutParams;
- }
-}
diff --git a/src/com/android/calculator2/Evaluator.java b/src/com/android/calculator2/Evaluator.java
index 9e0c7da..6362efe 100644
--- a/src/com/android/calculator2/Evaluator.java
+++ b/src/com/android/calculator2/Evaluator.java
@@ -80,33 +80,23 @@ package com.android.calculator2;
import android.app.AlertDialog;
import android.content.DialogInterface;
-import android.content.Context;
-import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
-import android.text.TextUtils;
import android.util.Log;
-import android.view.KeyEvent;
-import android.widget.EditText;
+import com.hp.creals.AbortedError;
import com.hp.creals.CR;
import com.hp.creals.PrecisionOverflowError;
-import com.hp.creals.AbortedError;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
+import java.math.BigInteger;
import java.text.DateFormat;
-import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
-import java.math.BigInteger;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map.Entry;
import java.util.Random;
-import java.util.Set;
import java.util.TimeZone;
class Evaluator {
diff --git a/src/com/android/calculator2/KeyMaps.java b/src/com/android/calculator2/KeyMaps.java
index 9a84612..e3b84e7 100644
--- a/src/com/android/calculator2/KeyMaps.java
+++ b/src/com/android/calculator2/KeyMaps.java
@@ -29,7 +29,7 @@ import java.util.Locale;
/**
* Collection of mapping functions between key ids, characters, internationalized
- * and noninternationalized characters, etc.
+ * and non-internationalized characters, etc.
* <p>
* 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.
@@ -39,71 +39,72 @@ public class KeyMaps {
* Map key id to corresponding (internationalized) display string.
* Pure function.
*/
- public static String toString(int id, Context context) {
- Resources res = context.getResources();
+ public static String toString(Context context, int id) {
switch(id) {
case R.id.const_pi:
- return res.getString(R.string.const_pi);
+ return context.getString(R.string.const_pi);
case R.id.const_e:
- return res.getString(R.string.const_e);
+ return context.getString(R.string.const_e);
case R.id.op_sqrt:
- return res.getString(R.string.op_sqrt);
+ return context.getString(R.string.op_sqrt);
case R.id.op_fact:
- return res.getString(R.string.op_fact);
+ return context.getString(R.string.op_fact);
+ case R.id.op_pct:
+ return context.getString(R.string.op_pct);
case R.id.fun_sin:
- return res.getString(R.string.fun_sin) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_sin) + context.getString(R.string.lparen);
case R.id.fun_cos:
- return res.getString(R.string.fun_cos) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_cos) + context.getString(R.string.lparen);
case R.id.fun_tan:
- return res.getString(R.string.fun_tan) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_tan) + context.getString(R.string.lparen);
case R.id.fun_arcsin:
- return res.getString(R.string.fun_arcsin) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_arcsin) + context.getString(R.string.lparen);
case R.id.fun_arccos:
- return res.getString(R.string.fun_arccos) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_arccos) + context.getString(R.string.lparen);
case R.id.fun_arctan:
- return res.getString(R.string.fun_arctan) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_arctan) + context.getString(R.string.lparen);
case R.id.fun_ln:
- return res.getString(R.string.fun_ln) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_ln) + context.getString(R.string.lparen);
case R.id.fun_log:
- return res.getString(R.string.fun_log) + res.getString(R.string.lparen);
+ return context.getString(R.string.fun_log) + context.getString(R.string.lparen);
case R.id.lparen:
- return res.getString(R.string.lparen);
+ return context.getString(R.string.lparen);
case R.id.rparen:
- return res.getString(R.string.rparen);
+ return context.getString(R.string.rparen);
case R.id.op_pow:
- return res.getString(R.string.op_pow);
+ return context.getString(R.string.op_pow);
case R.id.op_mul:
- return res.getString(R.string.op_mul);
+ return context.getString(R.string.op_mul);
case R.id.op_div:
- return res.getString(R.string.op_div);
+ return context.getString(R.string.op_div);
case R.id.op_add:
- return res.getString(R.string.op_add);
+ return context.getString(R.string.op_add);
case R.id.op_sub:
- return res.getString(R.string.op_sub);
+ return context.getString(R.string.op_sub);
case R.id.dec_point:
- return res.getString(R.string.dec_point);
+ return context.getString(R.string.dec_point);
case R.id.digit_0:
- return res.getString(R.string.digit_0);
+ return context.getString(R.string.digit_0);
case R.id.digit_1:
- return res.getString(R.string.digit_1);
+ return context.getString(R.string.digit_1);
case R.id.digit_2:
- return res.getString(R.string.digit_2);
+ return context.getString(R.string.digit_2);
case R.id.digit_3:
- return res.getString(R.string.digit_3);
+ return context.getString(R.string.digit_3);
case R.id.digit_4:
- return res.getString(R.string.digit_4);
+ return context.getString(R.string.digit_4);
case R.id.digit_5:
- return res.getString(R.string.digit_5);
+ return context.getString(R.string.digit_5);
case R.id.digit_6:
- return res.getString(R.string.digit_6);
+ return context.getString(R.string.digit_6);
case R.id.digit_7:
- return res.getString(R.string.digit_7);
+ return context.getString(R.string.digit_7);
case R.id.digit_8:
- return res.getString(R.string.digit_8);
+ return context.getString(R.string.digit_8);
case R.id.digit_9:
- return res.getString(R.string.digit_9);
+ return context.getString(R.string.digit_9);
default:
- return "?oops?";
+ return "";
}
}
@@ -128,7 +129,13 @@ public class KeyMaps {
* Does a button id correspond to a suffix operator?
*/
public static boolean isSuffix(int id) {
- return id == R.id.op_fact;
+ switch (id) {
+ case R.id.op_fact:
+ case R.id.op_pct:
+ return true;
+ default:
+ return false;
+ }
}
public static final int NOT_DIGIT = 10;
@@ -278,6 +285,8 @@ public class KeyMaps {
return R.id.op_pow;
case '!':
return R.id.op_fact;
+ case '%':
+ return R.id.op_pct;
case '(':
return R.id.lparen;
case ')':