From e2711cbb1569ab6c7a7c4506505ec403286d5ab4 Mon Sep 17 00:00:00 2001 From: Justin Klaassen Date: Thu, 28 May 2015 11:13:17 -0700 Subject: 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 --- src/com/android/calculator2/Calculator.java | 91 ++++++++++++--- src/com/android/calculator2/CalculatorExpr.java | 5 +- .../android/calculator2/CalculatorPadLayout.java | 126 --------------------- src/com/android/calculator2/Evaluator.java | 14 +-- src/com/android/calculator2/KeyMaps.java | 79 +++++++------ 5 files changed, 122 insertions(+), 193 deletions(-) delete mode 100644 src/com/android/calculator2/CalculatorPadLayout.java (limited to 'src') 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. *

* 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 ')': -- cgit v1.2.3