blob: f0a5ea35cbeb5e106885dab66c158fbd1b5ef885 [file] [log] [blame]
Annie Chinabd202f2016-10-14 14:23:45 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.calculator2;
18
19import android.animation.Animator;
20import android.animation.ObjectAnimator;
21import android.app.Fragment;
Annie Chin1ff328d2016-11-22 12:57:46 -080022import android.app.FragmentTransaction;
Annie Chinabd202f2016-10-14 14:23:45 -070023import android.os.Bundle;
Annie Chind0f87d22016-10-24 09:04:12 -070024import android.support.v7.widget.RecyclerView;
Annie Chinabd202f2016-10-14 14:23:45 -070025import android.view.LayoutInflater;
26import android.view.MenuItem;
Annie Chind0f87d22016-10-24 09:04:12 -070027import android.view.MotionEvent;
Annie Chinabd202f2016-10-14 14:23:45 -070028import android.view.View;
29import android.view.ViewGroup;
30import android.widget.Toolbar;
31
Annie Chin06fd3cf2016-11-07 16:04:33 -080032import java.util.ArrayList;
33
Annie Chinabd202f2016-10-14 14:23:45 -070034public class HistoryFragment extends Fragment {
35
36 public static final String TAG = "HistoryFragment";
37
Annie Chind0f87d22016-10-24 09:04:12 -070038 private final DragLayout.DragCallback mDragCallback =
39 new DragLayout.DragCallback() {
40 @Override
41 public void onStartDragging() {
42 // no-op
43 }
44
45 @Override
46 public void whileDragging(float yFraction) {
47 mDragController.animateViews(yFraction, mRecyclerView, mAdapter.getItemCount());
48 }
49
50 @Override
51 public void onClosed() {
Annie Chin06fd3cf2016-11-07 16:04:33 -080052 // TODO: only cancel historical evaluations
53 mEvaluator.cancelAll(true);
Annie Chind0f87d22016-10-24 09:04:12 -070054 }
55
56 @Override
57 public boolean allowDrag(MotionEvent event) {
58 // Do not allow drag if the recycler view can move down more
59 return !mRecyclerView.canScrollVertically(1);
60 }
61
62 @Override
63 public boolean shouldInterceptTouchEvent(MotionEvent event) {
64 return true;
65 }
66
67 @Override
68 public int getDisplayHeight() {
69 return 0;
70 }
71
72 @Override
73 public void onLayout(int translation) {
74 // no-op
75 }
76 };
77
78 private final DragController mDragController = new DragController();
79
80 private RecyclerView mRecyclerView;
81 private HistoryAdapter mAdapter;
82
Annie Chin06fd3cf2016-11-07 16:04:33 -080083 private Evaluator mEvaluator;
84
85 private ArrayList<HistoryItem> mDataSet = new ArrayList<>();
86
Annie Chind0f87d22016-10-24 09:04:12 -070087 @Override
88 public void onCreate(Bundle savedInstanceState) {
89 super.onCreate(savedInstanceState);
90
Annie Chin06fd3cf2016-11-07 16:04:33 -080091 mAdapter = new HistoryAdapter((Calculator) getActivity(), mDataSet,
Annie Chind0f87d22016-10-24 09:04:12 -070092 getContext().getResources().getString(R.string.title_current_expression));
93 }
94
Annie Chinabd202f2016-10-14 14:23:45 -070095 @Override
96 public View onCreateView(LayoutInflater inflater, ViewGroup container,
97 Bundle savedInstanceState) {
98 final View view = inflater.inflate(
99 R.layout.fragment_history, container, false /* attachToRoot */);
100
Annie Chind0f87d22016-10-24 09:04:12 -0700101 mRecyclerView = (RecyclerView) view.findViewById(R.id.history_recycler_view);
102
103 // The size of the RecyclerView is not affected by the adapter's contents.
Annie Chind0f87d22016-10-24 09:04:12 -0700104 mRecyclerView.setAdapter(mAdapter);
105
Annie Chinabd202f2016-10-14 14:23:45 -0700106 final Toolbar toolbar = (Toolbar) view.findViewById(R.id.history_toolbar);
107 toolbar.inflateMenu(R.menu.fragment_history);
108 toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
109 @Override
110 public boolean onMenuItemClick(MenuItem item) {
111 if (item.getItemId() == R.id.menu_clear_history) {
112 clearHistory();
113 return true;
114 }
115 return onOptionsItemSelected(item);
116 }
117 });
118 toolbar.setNavigationOnClickListener(new View.OnClickListener() {
119 @Override
120 public void onClick(View v) {
Annie Chin09547532016-10-14 10:59:07 -0700121 getActivity().onBackPressed();
Annie Chinabd202f2016-10-14 14:23:45 -0700122 }
123 });
Annie Chinbc001882016-11-09 19:41:21 -0800124
Annie Chinabd202f2016-10-14 14:23:45 -0700125 return view;
126 }
127
128 @Override
Annie Chind0f87d22016-10-24 09:04:12 -0700129 public void onActivityCreated(Bundle savedInstanceState) {
130 super.onActivityCreated(savedInstanceState);
131
Annie Chind0f87d22016-10-24 09:04:12 -0700132 final DragLayout dragLayout = (DragLayout) getActivity().findViewById(R.id.drag_layout);
133 dragLayout.removeDragCallback(mDragCallback);
134 dragLayout.addDragCallback(mDragCallback);
Annie Chin06fd3cf2016-11-07 16:04:33 -0800135
Annie Chin70ac8ea2016-11-18 14:43:56 -0800136 final Calculator activity = (Calculator) getActivity();
137 final boolean isResultState = activity.isResultState();
138
139 mEvaluator = Evaluator.getInstance(activity);
Annie Chin06fd3cf2016-11-07 16:04:33 -0800140
141 if (mEvaluator != null) {
Annie Chinbc001882016-11-09 19:41:21 -0800142 initializeController();
143
Annie Chin06fd3cf2016-11-07 16:04:33 -0800144 final long maxIndex = mEvaluator.getMaxIndex();
145
146 final ArrayList<HistoryItem> newDataSet = new ArrayList<>();
Annie Chinbc001882016-11-09 19:41:21 -0800147
Annie Chin70ac8ea2016-11-18 14:43:56 -0800148 if (!EvaluatorStateUtils.isDisplayEmpty(mEvaluator) && !isResultState) {
149 // Add the current expression as the first element in the list (the layout is
150 // reversed and we want the current expression to be the last one in the
151 // recyclerview).
152 // If we are in the result state, the result will animate to the last history
153 // element in the list and there will be no "Current Expression."
Annie Chin91796232016-11-16 17:27:36 -0800154 newDataSet.add(new HistoryItem(Evaluator.MAIN_INDEX, System.currentTimeMillis(),
Annie Chinbc001882016-11-09 19:41:21 -0800155 mEvaluator.getExprAsSpannable(0)));
156 }
Annie Chin91796232016-11-16 17:27:36 -0800157 for (long i = 0; i < maxIndex; ++i) {
Annie Chin06fd3cf2016-11-07 16:04:33 -0800158 newDataSet.add(null);
159 }
160 if (maxIndex == 0) {
161 newDataSet.add(new HistoryItem());
162 }
Annie Chin06fd3cf2016-11-07 16:04:33 -0800163 mDataSet = newDataSet;
164 mAdapter.setDataSet(mDataSet);
Annie Chin70ac8ea2016-11-18 14:43:56 -0800165 mAdapter.setIsResultState(isResultState);
Annie Chin06fd3cf2016-11-07 16:04:33 -0800166 }
Annie Chinbc001882016-11-09 19:41:21 -0800167
168 mAdapter.notifyDataSetChanged();
Annie Chinefa259a2016-11-23 14:15:15 -0800169 }
Annie Chinbc001882016-11-09 19:41:21 -0800170
Annie Chinefa259a2016-11-23 14:15:15 -0800171 @Override
172 public void onStart() {
173 super.onStart();
174
175 // The orientation may have changed.
176 mDragController.initializeAnimation(mRecyclerView);
Annie Chind0f87d22016-10-24 09:04:12 -0700177 }
178
179 @Override
Annie Chinabd202f2016-10-14 14:23:45 -0700180 public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
181 final View view = getView();
182 final int height = getResources().getDisplayMetrics().heightPixels;
Annie Chin91796232016-11-16 17:27:36 -0800183 if (enter) {
Annie Chin1ff328d2016-11-22 12:57:46 -0800184 if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) {
185 return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, -height, 0f);
186 } else {
187 return null;
188 }
Annie Chin91796232016-11-16 17:27:36 -0800189 } else {
190 return ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, -height);
Annie Chinabd202f2016-10-14 14:23:45 -0700191 }
Annie Chinabd202f2016-10-14 14:23:45 -0700192 }
193
Annie Chind0f87d22016-10-24 09:04:12 -0700194 @Override
195 public void onDestroyView() {
196 final DragLayout dragLayout = (DragLayout) getActivity().findViewById(R.id.drag_layout);
197 if (dragLayout != null) {
198 dragLayout.removeDragCallback(mDragCallback);
199 }
Annie Chin06fd3cf2016-11-07 16:04:33 -0800200
201 mEvaluator.cancelAll(true);
Annie Chind0f87d22016-10-24 09:04:12 -0700202 super.onDestroy();
203 }
204
205 private void initializeController() {
206 mDragController.setDisplayFormula(
207 (CalculatorFormula) getActivity().findViewById(R.id.formula));
208
209 mDragController.setDisplayResult(
210 (CalculatorResult) getActivity().findViewById(R.id.result));
211
212 mDragController.setToolbar(getActivity().findViewById(R.id.toolbar));
Annie Chinbc001882016-11-09 19:41:21 -0800213
214 mDragController.setEvaluator(mEvaluator);
Annie Chind0f87d22016-10-24 09:04:12 -0700215 }
216
Annie Chinabd202f2016-10-14 14:23:45 -0700217 private void clearHistory() {
Hans Boehm9db3ee22016-11-18 10:09:47 -0800218 // TODO: Try to preserve the current, saved, and memory expressions. How should we
219 // handle expressions to which they refer?
220 // FIXME: This should clearly happen on a background thread.
221 mEvaluator.clearEverything();
222 // TODO: It's not clear what we should really do here. This is an initial hack.
223 // May want to make onClearAnimationEnd() private if/when we fix this.
224 Calculator calculator = (Calculator) getActivity();
225 calculator.onClearAnimationEnd();
226 calculator.onBackPressed();
Annie Chinabd202f2016-10-14 14:23:45 -0700227 }
228}