/*
|
* 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 androidx.recyclerview.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;
|
}
|
}
|
}
|