diff options
author | Annie Chin <afchin@google.com> | 2016-11-07 16:04:33 -0800 |
---|---|---|
committer | Annie Chin <afchin@google.com> | 2016-11-17 09:55:58 -0800 |
commit | 06fd3cf86f20a8b927c8b57ef9e94ee48bee46ff (patch) | |
tree | 4621e51e2c506f6824854e4fc8dcf827751b7818 /src | |
parent | ab657d463740bfc4322f1c06da80bea9c14e993c (diff) | |
download | android_packages_apps_ExactCalculator-06fd3cf86f20a8b927c8b57ef9e94ee48bee46ff.tar.gz android_packages_apps_ExactCalculator-06fd3cf86f20a8b927c8b57ef9e94ee48bee46ff.tar.bz2 android_packages_apps_ExactCalculator-06fd3cf86f20a8b927c8b57ef9e94ee48bee46ff.zip |
Integrate database with history.
Bug: 31623549
Note: This CL operates under the assumption that there is something
in the current expression field (handling for various states of
CalculatorDisplay in ag/1613446)
Change-Id: I70992067ddc9c5eec079f00604549727787e26fe
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/calculator2/AlertDialogFragment.java | 7 | ||||
-rw-r--r-- | src/com/android/calculator2/Calculator.java | 19 | ||||
-rw-r--r-- | src/com/android/calculator2/CalculatorExpr.java | 5 | ||||
-rw-r--r-- | src/com/android/calculator2/CalculatorResult.java | 12 | ||||
-rw-r--r-- | src/com/android/calculator2/Evaluator.java | 20 | ||||
-rw-r--r-- | src/com/android/calculator2/HistoryAdapter.java | 61 | ||||
-rw-r--r-- | src/com/android/calculator2/HistoryFragment.java | 47 | ||||
-rw-r--r-- | src/com/android/calculator2/HistoryItem.java | 19 |
8 files changed, 137 insertions, 53 deletions
diff --git a/src/com/android/calculator2/AlertDialogFragment.java b/src/com/android/calculator2/AlertDialogFragment.java index e098022..12840ae 100644 --- a/src/com/android/calculator2/AlertDialogFragment.java +++ b/src/com/android/calculator2/AlertDialogFragment.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; +import android.app.FragmentManager; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.Nullable; @@ -78,6 +79,10 @@ public class AlertDialogFragment extends DialogFragment implements DialogInterfa */ public static void showMessageDialog(Activity activity, @Nullable CharSequence title, CharSequence message, @Nullable CharSequence positiveButtonLabel) { + final FragmentManager manager = activity.getFragmentManager(); + if (manager == null || manager.isDestroyed()) { + return; + } final AlertDialogFragment dialogFragment = new AlertDialogFragment(); final Bundle args = new Bundle(); args.putCharSequence(KEY_MESSAGE, message); @@ -87,7 +92,7 @@ public class AlertDialogFragment extends DialogFragment implements DialogInterfa } args.putCharSequence(KEY_TITLE, title); dialogFragment.setArguments(args); - dialogFragment.show(activity.getFragmentManager(), null /* tag */); + dialogFragment.show(manager, null /* tag */); } public AlertDialogFragment() { diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java index 8aac061..a5d2e92 100644 --- a/src/com/android/calculator2/Calculator.java +++ b/src/com/android/calculator2/Calculator.java @@ -33,6 +33,7 @@ import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.app.ActionBar; import android.app.Activity; +import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.ClipData; import android.content.DialogInterface; @@ -189,7 +190,7 @@ public class Calculator extends Activity @Override public void onClosed() { - getFragmentManager().popBackStack(); + popFragmentBackstack(); } @Override @@ -308,7 +309,7 @@ public class Calculator extends Activity findViewById(R.id.op_sqr) }; - mEvaluator = new Evaluator(this); + mEvaluator = Evaluator.getInstance(this); mResultText.setEvaluator(mEvaluator, Evaluator.MAIN_INDEX); KeyMaps.setActivity(this); @@ -500,7 +501,7 @@ public class Calculator extends Activity if (mDragLayout.isOpen()) { // Close the layout and remove the fragment. mDragLayout.setClosed(); - getFragmentManager().popBackStack(); + popFragmentBackstack(); return; } if (mPadViewPager != null && mPadViewPager.getCurrentItem() != 0) { @@ -623,6 +624,13 @@ public class Calculator extends Activity } } + private void popFragmentBackstack() { + final FragmentManager manager = getFragmentManager(); + if (manager == null || manager.isDestroyed()) { + return; + } + manager.popBackStack(); + } /** * Switch to INPUT from RESULT state in response to input of the specified button_id. * View.NO_ID is treated as an incomplete function id. @@ -1176,6 +1184,10 @@ public class Calculator extends Activity } private void showHistoryFragment(int transit) { + final FragmentManager manager = getFragmentManager(); + if (manager == null || manager.isDestroyed()) { + return; + } if (!mDragLayout.isOpen()) { getFragmentManager().beginTransaction() .replace(R.id.history_frame, mHistoryFragment, HistoryFragment.TAG) @@ -1183,6 +1195,7 @@ public class Calculator extends Activity .addToBackStack(HistoryFragment.TAG) .commit(); } + // TODO: pass current scroll position of result } private void displayMessage(String title, String message) { diff --git a/src/com/android/calculator2/CalculatorExpr.java b/src/com/android/calculator2/CalculatorExpr.java index f20d2bf..c6eb9af 100644 --- a/src/com/android/calculator2/CalculatorExpr.java +++ b/src/com/android/calculator2/CalculatorExpr.java @@ -21,15 +21,12 @@ import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.TtsSpan; -import android.text.style.TtsSpan.TextBuilder; -import java.math.BigInteger; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import java.math.BigInteger; import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; /** * A mathematical expression represented as a sequence of "tokens". diff --git a/src/com/android/calculator2/CalculatorResult.java b/src/com/android/calculator2/CalculatorResult.java index caf72fe..29c20f7 100644 --- a/src/com/android/calculator2/CalculatorResult.java +++ b/src/com/android/calculator2/CalculatorResult.java @@ -303,6 +303,18 @@ public class CalculatorResult extends AlignedTextView implements MenuItem.OnMenu super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (mEvaluator != null) { + final CalculatorExpr expr = mEvaluator.getExpr(mIndex); + if (expr != null && expr.hasInterestingOps()) { + mEvaluator.requireResult(mIndex, this, this); + } + } + } + // From Evaluator.CharMetricsInfo. @Override public float separatorChars(String s, int len) { diff --git a/src/com/android/calculator2/Evaluator.java b/src/com/android/calculator2/Evaluator.java index d73534f..8f12ce1 100644 --- a/src/com/android/calculator2/Evaluator.java +++ b/src/com/android/calculator2/Evaluator.java @@ -17,14 +17,13 @@ package com.android.calculator2; import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.net.Uri; import android.os.AsyncTask; import android.os.Handler; import android.preference.PreferenceManager; import android.support.annotation.VisibleForTesting; +import android.text.Spannable; import android.util.Log; import com.hp.creals.CR; @@ -38,11 +37,11 @@ import java.io.DataOutputStream; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.ConcurrentHashMap; import java.util.Date; import java.util.Random; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; /** * This implements the calculator evaluation logic. @@ -98,6 +97,15 @@ import java.util.TimeZone; */ public class Evaluator implements CalculatorExpr.ExprResolver { + private static Evaluator evaluator; + + public static Evaluator getInstance(Calculator calculator) { + if (evaluator == null) { + evaluator = new Evaluator(calculator); + } + return evaluator; + } + public interface EvaluationListener { /** * Called if evaluation was explicitly cancelled or evaluation timed out. @@ -1731,6 +1739,10 @@ public class Evaluator implements CalculatorExpr.ExprResolver { return getExpr(index).toSpannableStringBuilder(mActivity).toString(); } + public Spannable getExprAsSpannable(long index) { + return getExpr(index).toSpannableStringBuilder(mActivity); + } + /** * Generate a String representation of all expressions in the database. * Debugging only. diff --git a/src/com/android/calculator2/HistoryAdapter.java b/src/com/android/calculator2/HistoryAdapter.java index 25c7044..19aa05b 100644 --- a/src/com/android/calculator2/HistoryAdapter.java +++ b/src/com/android/calculator2/HistoryAdapter.java @@ -23,7 +23,6 @@ import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; /** @@ -34,20 +33,17 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold private static final int EMPTY_VIEW_TYPE = 0; private static final int HISTORY_VIEW_TYPE = 1; - private final List<HistoryItem> mDataSet = new ArrayList<>(); - private String mCurrentExpression; - - public HistoryAdapter(int[] dataset, String currentExpression) { - mCurrentExpression = currentExpression; - // Temporary dataset - final Calendar calendar = Calendar.getInstance(); - for (int i: dataset) { - calendar.set(2016, 10, i); - mDataSet.add(new HistoryItem(calendar.getTimeInMillis(), Integer.toString(i) + "+1", - Integer.toString(i+1))); - } - // Temporary: just testing the empty view placeholder - mDataSet.add(new HistoryItem()); + private final Evaluator mEvaluator; + /* Text/accessibility descriptor for the current expression item. */ + private final String mCurrentExpressionDescription; + + private List<HistoryItem> mDataSet; + + public HistoryAdapter(Calculator calculator, ArrayList<HistoryItem> dataSet, + String currentExpressionDescription) { + mEvaluator = Evaluator.getInstance(calculator); + mDataSet = dataSet; + mCurrentExpressionDescription = currentExpressionDescription; } @Override @@ -64,21 +60,23 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold } @Override - public void onBindViewHolder(HistoryAdapter.ViewHolder holder, int position) { + public void onBindViewHolder(final HistoryAdapter.ViewHolder holder, int position) { final HistoryItem item = mDataSet.get(position); if (item.isEmptyView()) { return; } - if (!isCurrentExpressionItem(position)) { + + holder.mFormula.setText(item.getFormula()); + // Note: HistoryItems that are not the current expression will always have interesting ops. + holder.mResult.setEvaluator(mEvaluator, item.getId()); + if (isCurrentExpressionItem(position)) { + holder.mDate.setText(mCurrentExpressionDescription); + holder.mDate.setContentDescription(mCurrentExpressionDescription); + } else { holder.mDate.setText(item.getDateString()); holder.mDate.setContentDescription(item.getDateDescription()); - } else { - holder.mDate.setText(mCurrentExpression); - holder.mDate.setContentDescription(mCurrentExpression); } - holder.mFormula.setText(item.getFormula()); - holder.mResult.setText(item.getResult()); } @Override @@ -88,12 +86,23 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold holder.mFormula.setText(null); holder.mResult.setText(null); + // TODO: Only cancel the calculation for the recycled view + mEvaluator.cancelAll(true); + super.onViewRecycled(holder); } @Override public int getItemViewType(int position) { - return mDataSet.get(position).isEmptyView() ? EMPTY_VIEW_TYPE : HISTORY_VIEW_TYPE; + HistoryItem item = mDataSet.get(position); + + // lazy-fill the data set + if (item == null) { + item = new HistoryItem(position, mEvaluator.getTimeStamp(position), + mEvaluator.getExprAsSpannable(position)); + mDataSet.add(position, item); + } + return item.isEmptyView() ? EMPTY_VIEW_TYPE : HISTORY_VIEW_TYPE; } @Override @@ -102,7 +111,11 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold } private boolean isCurrentExpressionItem(int position) { - return position == mDataSet.size() - 1; + return position == 0; + } + + public void setDataSet(ArrayList<HistoryItem> dataSet) { + mDataSet = dataSet; } public static class ViewHolder extends RecyclerView.ViewHolder { diff --git a/src/com/android/calculator2/HistoryFragment.java b/src/com/android/calculator2/HistoryFragment.java index 984ee82..15bf161 100644 --- a/src/com/android/calculator2/HistoryFragment.java +++ b/src/com/android/calculator2/HistoryFragment.java @@ -30,6 +30,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.Toolbar; +import java.util.ArrayList; + public class HistoryFragment extends Fragment { public static final String TAG = "HistoryFragment"; @@ -48,6 +50,9 @@ public class HistoryFragment extends Fragment { @Override public void onClosed() { + // TODO: only cancel historical evaluations + mEvaluator.cancelAll(true); + mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1); } @@ -78,13 +83,15 @@ public class HistoryFragment extends Fragment { private RecyclerView mRecyclerView; private HistoryAdapter mAdapter; + private Evaluator mEvaluator; + + private ArrayList<HistoryItem> mDataSet = new ArrayList<>(); + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Temporary data - final int[] testArray = {7}; - mAdapter = new HistoryAdapter(testArray, + mAdapter = new HistoryAdapter((Calculator) getActivity(), mDataSet, getContext().getResources().getString(R.string.title_current_expression)); } @@ -117,7 +124,6 @@ public class HistoryFragment extends Fragment { getActivity().onBackPressed(); } }); - return view; } @@ -129,6 +135,33 @@ public class HistoryFragment extends Fragment { final DragLayout dragLayout = (DragLayout) getActivity().findViewById(R.id.drag_layout); dragLayout.removeDragCallback(mDragCallback); dragLayout.addDragCallback(mDragCallback); + + mEvaluator = Evaluator.getInstance((Calculator) getActivity()); + + if (mEvaluator != null) { + final long maxIndex = mEvaluator.getMaxIndex(); + + final ArrayList<HistoryItem> newDataSet = new ArrayList<>(); + // Add the current expression as the first element in the list (the layout is reversed + // and we want the current expression to be the last one in the recyclerview). + newDataSet.add(new HistoryItem(Evaluator.MAIN_INDEX, 0 /* millis*/, + mEvaluator.getExprAsSpannable(0))); + // We retrieve the current expression separately, so it's excluded from this loop. + for (long i = maxIndex; i > 0; --i ) { + newDataSet.add(null); + } + if (maxIndex == 0) { + newDataSet.add(new HistoryItem()); + } + + mDataSet = newDataSet; + mAdapter.setDataSet(mDataSet); + mAdapter.notifyDataSetChanged(); + +// // Initialize the current expression element to dimensions that match the display to avoid +// // flickering and scrolling when elements expand on drag start. +// mDragController.animateViews(1.0f, mRecyclerView, mAdapter.getItemCount()); + } } @Override @@ -149,6 +182,8 @@ public class HistoryFragment extends Fragment { if (dragLayout != null) { dragLayout.removeDragCallback(mDragCallback); } + + mEvaluator.cancelAll(true); super.onDestroy(); } @@ -160,10 +195,6 @@ public class HistoryFragment extends Fragment { (CalculatorResult) getActivity().findViewById(R.id.result)); mDragController.setToolbar(getActivity().findViewById(R.id.toolbar)); - - // Initialize the current expression element to dimensions that match the display to avoid - // flickering and scrolling when elements expand on drag start. - mDragController.animateViews(1.0f, mRecyclerView, mAdapter.getItemCount()); } private void clearHistory() { diff --git a/src/com/android/calculator2/HistoryItem.java b/src/com/android/calculator2/HistoryItem.java index 17f009f..63f46e9 100644 --- a/src/com/android/calculator2/HistoryItem.java +++ b/src/com/android/calculator2/HistoryItem.java @@ -16,6 +16,7 @@ package com.android.calculator2; +import android.text.Spannable; import android.text.format.DateFormat; import java.text.SimpleDateFormat; @@ -27,20 +28,24 @@ public class HistoryItem { private static final String dateFormat = "EEEMMMd"; private static final String descriptionFormat = "EEEEMMMMd"; + private long mId; private Date mDate; - private String mFormula; - private String mResult; + private Spannable mFormula; // This is true only for the "empty history" view. private final boolean mIsEmpty; - public HistoryItem(long millis, String formula, String result) { + public HistoryItem(long id, long millis, Spannable formula) { + mId = id; mDate = new Date(millis); mFormula = formula; - mResult = result; mIsEmpty = false; } + public long getId() { + return mId; + } + public HistoryItem() { mIsEmpty = true; } @@ -62,11 +67,7 @@ public class HistoryItem { return new SimpleDateFormat(descriptionPattern, l).format(mDate); } - public String getFormula() { + public Spannable getFormula() { return mFormula; } - - public String getResult() { - return mResult; - } }
\ No newline at end of file |