diff options
Diffstat (limited to 'src/com/android/calculator2/HistoryAdapter.java')
-rw-r--r-- | src/com/android/calculator2/HistoryAdapter.java | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/com/android/calculator2/HistoryAdapter.java b/src/com/android/calculator2/HistoryAdapter.java new file mode 100644 index 0000000..629abe9 --- /dev/null +++ b/src/com/android/calculator2/HistoryAdapter.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2016 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.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * Adapter for RecyclerView of HistoryItems. + */ +public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHolder> { + + private static final String TAG = "HistoryAdapter"; + + private static final int EMPTY_VIEW_TYPE = 0; + public static final int HISTORY_VIEW_TYPE = 1; + + private Evaluator mEvaluator; + + private final Calendar mCalendar = Calendar.getInstance(); + + private List<HistoryItem> mDataSet; + + private boolean mIsResultLayout; + private boolean mIsOneLine; + private boolean mIsDisplayEmpty; + + public HistoryAdapter(ArrayList<HistoryItem> dataSet) { + mDataSet = dataSet; + setHasStableIds(true); + } + + @Override + public HistoryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + final View v; + if (viewType == HISTORY_VIEW_TYPE) { + v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.history_item, parent, false); + } else { + v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.empty_history_view, parent, false); + } + return new ViewHolder(v, viewType); + } + + @Override + public void onBindViewHolder(final HistoryAdapter.ViewHolder holder, int position) { + final HistoryItem item = getItem(position); + + if (item.isEmptyView()) { + return; + } + + holder.mFormula.setText(item.getFormula()); + // Note: HistoryItems that are not the current expression will always have interesting ops. + holder.mResult.setEvaluator(mEvaluator, item.getEvaluatorIndex()); + if (item.getEvaluatorIndex() == Evaluator.HISTORY_MAIN_INDEX) { + holder.mDate.setText(R.string.title_current_expression); + holder.mResult.setVisibility(mIsOneLine ? View.GONE : View.VISIBLE); + } else { + // If the previous item occurred on the same date, the current item does not need + // a date header. + if (shouldShowHeader(position, item)) { + holder.mDate.setText(item.getDateString()); + // Special case -- very first item should not have a divider above it. + holder.mDivider.setVisibility(position == getItemCount() - 1 + ? View.GONE : View.VISIBLE); + } else { + holder.mDate.setVisibility(View.GONE); + holder.mDivider.setVisibility(View.INVISIBLE); + } + } + } + + @Override + public void onViewRecycled(ViewHolder holder) { + if (holder.getItemViewType() == EMPTY_VIEW_TYPE) { + return; + } + mEvaluator.cancel(holder.getItemId(), true); + + holder.mDate.setVisibility(View.VISIBLE); + holder.mDivider.setVisibility(View.VISIBLE); + holder.mDate.setText(null); + holder.mFormula.setText(null); + holder.mResult.setText(null); + + super.onViewRecycled(holder); + } + + @Override + public long getItemId(int position) { + return getItem(position).getEvaluatorIndex(); + } + + @Override + public int getItemViewType(int position) { + return getItem(position).isEmptyView() ? EMPTY_VIEW_TYPE : HISTORY_VIEW_TYPE; + } + + @Override + public int getItemCount() { + return mDataSet.size(); + } + + public void setDataSet(ArrayList<HistoryItem> dataSet) { + mDataSet = dataSet; + } + + public void setIsResultLayout(boolean isResult) { + mIsResultLayout = isResult; + } + + public void setIsOneLine(boolean isOneLine) { + mIsOneLine = isOneLine; + } + + public void setIsDisplayEmpty(boolean isDisplayEmpty) { + mIsDisplayEmpty = isDisplayEmpty; + } + + public void setEvaluator(Evaluator evaluator) { + mEvaluator = evaluator; + } + + private int getEvaluatorIndex(int position) { + if (mIsDisplayEmpty || mIsResultLayout) { + return (int) (mEvaluator.getMaxIndex() - position); + } else { + // Account for the additional "Current Expression" with the +1. + return (int) (mEvaluator.getMaxIndex() - position + 1); + } + } + + private boolean shouldShowHeader(int position, HistoryItem item) { + if (position == getItemCount() - 1) { + // First/oldest element should always show the header. + return true; + } + final HistoryItem prevItem = getItem(position + 1); + // We need to use Calendars to determine this because of Daylight Savings. + mCalendar.setTimeInMillis(item.getTimeInMillis()); + final int year = mCalendar.get(Calendar.YEAR); + final int day = mCalendar.get(Calendar.DAY_OF_YEAR); + mCalendar.setTimeInMillis(prevItem.getTimeInMillis()); + final int prevYear = mCalendar.get(Calendar.YEAR); + final int prevDay = mCalendar.get(Calendar.DAY_OF_YEAR); + return year != prevYear || day != prevDay; + } + + /** + * Gets the HistoryItem from mDataSet, lazy-filling the dataSet if necessary. + */ + private HistoryItem getItem(int position) { + HistoryItem item = mDataSet.get(position); + // Lazy-fill the data set. + if (item == null) { + final int evaluatorIndex = getEvaluatorIndex(position); + item = new HistoryItem(evaluatorIndex, + mEvaluator.getTimeStamp(evaluatorIndex), + mEvaluator.getExprAsSpannable(evaluatorIndex)); + mDataSet.set(position, item); + } + return item; + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + + private TextView mDate; + private AlignedTextView mFormula; + private CalculatorResult mResult; + private View mDivider; + + public ViewHolder(View v, int viewType) { + super(v); + if (viewType == EMPTY_VIEW_TYPE) { + return; + } + mDate = (TextView) v.findViewById(R.id.history_date); + mFormula = (AlignedTextView) v.findViewById(R.id.history_formula); + mResult = (CalculatorResult) v.findViewById(R.id.history_result); + mDivider = v.findViewById(R.id.history_divider); + } + + public AlignedTextView getFormula() { + return mFormula; + } + + public CalculatorResult getResult() { + return mResult; + } + + public TextView getDate() { + return mDate; + } + + public View getDivider() { + return mDivider; + } + } +}
\ No newline at end of file |