blob: 6847cc97adfa43b8f80ee68c5f93d82acd43e1b7 [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
Justin Klaassen39297782016-12-19 09:11:38 -080019import android.animation.Animator;
Annie Chinabd202f2016-10-14 14:23:45 -070020import android.app.Fragment;
Justin Klaassen39297782016-12-19 09:11:38 -080021import android.app.FragmentTransaction;
Annie Chinabd202f2016-10-14 14:23:45 -070022import android.os.Bundle;
Annie Chin36147982016-12-01 15:07:34 -080023import android.support.v4.content.ContextCompat;
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;
27import android.view.View;
28import android.view.ViewGroup;
29import android.widget.Toolbar;
30
Annie Chin06fd3cf2016-11-07 16:04:33 -080031import java.util.ArrayList;
32
Christine Franks7485df52016-12-01 13:18:45 -080033import static android.support.v7.widget.RecyclerView.SCROLL_STATE_DRAGGING;
34
Annie Chin52eed7a2017-01-04 15:06:05 -080035public class HistoryFragment extends Fragment implements DragLayout.DragCallback {
Annie Chinabd202f2016-10-14 14:23:45 -070036
37 public static final String TAG = "HistoryFragment";
Annie Chin532b77e2016-12-06 13:30:35 -080038 public static final String CLEAR_DIALOG_TAG = "clear";
Annie Chinabd202f2016-10-14 14:23:45 -070039
Annie Chind0f87d22016-10-24 09:04:12 -070040 private final DragController mDragController = new DragController();
41
42 private RecyclerView mRecyclerView;
43 private HistoryAdapter mAdapter;
Annie Chinb2e96182016-11-28 13:14:54 -080044 private DragLayout mDragLayout;
Annie Chind0f87d22016-10-24 09:04:12 -070045
Annie Chin06fd3cf2016-11-07 16:04:33 -080046 private Evaluator mEvaluator;
47
48 private ArrayList<HistoryItem> mDataSet = new ArrayList<>();
49
Annie Chinbfffafd2017-01-25 15:51:11 -080050 private boolean mIsDisplayEmpty;
51
Annie Chind0f87d22016-10-24 09:04:12 -070052 @Override
53 public void onCreate(Bundle savedInstanceState) {
54 super.onCreate(savedInstanceState);
Annie Chin7d039632016-12-08 15:23:39 -080055 mAdapter = new HistoryAdapter(mDataSet);
Annie Chind0f87d22016-10-24 09:04:12 -070056 }
57
Annie Chinabd202f2016-10-14 14:23:45 -070058 @Override
59 public View onCreateView(LayoutInflater inflater, ViewGroup container,
60 Bundle savedInstanceState) {
61 final View view = inflater.inflate(
62 R.layout.fragment_history, container, false /* attachToRoot */);
63
Justin Klaassen39297782016-12-19 09:11:38 -080064 mDragLayout = (DragLayout) container.getRootView().findViewById(R.id.drag_layout);
65 mDragLayout.addDragCallback(this);
66
Annie Chind0f87d22016-10-24 09:04:12 -070067 mRecyclerView = (RecyclerView) view.findViewById(R.id.history_recycler_view);
Christine Franks7485df52016-12-01 13:18:45 -080068 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
69 @Override
70 public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
71 if (newState == SCROLL_STATE_DRAGGING) {
72 stopActionModeOrContextMenu();
73 }
74 super.onScrollStateChanged(recyclerView, newState);
75 }
76 });
Annie Chind0f87d22016-10-24 09:04:12 -070077
78 // The size of the RecyclerView is not affected by the adapter's contents.
Annie Chin36147982016-12-01 15:07:34 -080079 mRecyclerView.setHasFixedSize(true);
Annie Chind0f87d22016-10-24 09:04:12 -070080 mRecyclerView.setAdapter(mAdapter);
81
Annie Chinabd202f2016-10-14 14:23:45 -070082 final Toolbar toolbar = (Toolbar) view.findViewById(R.id.history_toolbar);
83 toolbar.inflateMenu(R.menu.fragment_history);
84 toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
85 @Override
86 public boolean onMenuItemClick(MenuItem item) {
87 if (item.getItemId() == R.id.menu_clear_history) {
Annie Chin532b77e2016-12-06 13:30:35 -080088 final Calculator calculator = (Calculator) getActivity();
89 AlertDialogFragment.showMessageDialog(calculator, "" /* title */,
90 getString(R.string.dialog_clear),
91 getString(R.string.menu_clear_history),
92 CLEAR_DIALOG_TAG);
Annie Chinabd202f2016-10-14 14:23:45 -070093 return true;
94 }
95 return onOptionsItemSelected(item);
96 }
97 });
98 toolbar.setNavigationOnClickListener(new View.OnClickListener() {
99 @Override
100 public void onClick(View v) {
Annie Chin09547532016-10-14 10:59:07 -0700101 getActivity().onBackPressed();
Annie Chinabd202f2016-10-14 14:23:45 -0700102 }
103 });
Annie Chinabd202f2016-10-14 14:23:45 -0700104 return view;
105 }
106
107 @Override
Annie Chind0f87d22016-10-24 09:04:12 -0700108 public void onActivityCreated(Bundle savedInstanceState) {
109 super.onActivityCreated(savedInstanceState);
110
Annie Chin70ac8ea2016-11-18 14:43:56 -0800111 final Calculator activity = (Calculator) getActivity();
Christine Frankscbc51fa2017-01-04 21:00:36 -0800112 mEvaluator = Evaluator.getInstance(activity);
113 mAdapter.setEvaluator(mEvaluator);
Annie Chin7d039632016-12-08 15:23:39 -0800114
Annie Chin94c1bd92016-11-23 13:39:56 -0800115 final boolean isResultLayout = activity.isResultLayout();
Annie Chin88613232017-01-04 12:21:52 -0800116 final boolean isOneLine = activity.isOneLine();
Annie Chin70ac8ea2016-11-18 14:43:56 -0800117
Annie Chinbfffafd2017-01-25 15:51:11 -0800118 // Snapshot display state here. For the rest of the lifecycle of this current
119 // HistoryFragment, this is what we will consider the display state.
120 // In rare cases, the display state can change after our adapter is initialized.
121 final CalculatorExpr mainExpr = mEvaluator.getExpr(Evaluator.MAIN_INDEX);
122 mIsDisplayEmpty = mainExpr == null || mainExpr.isEmpty();
123
124 initializeController(isResultLayout, isOneLine, mIsDisplayEmpty);
Annie Chinbc001882016-11-09 19:41:21 -0800125
Annie Chine7c32322017-01-30 18:08:56 -0800126 final long maxIndex = mEvaluator.getMaxIndex();
Annie Chin06fd3cf2016-11-07 16:04:33 -0800127
Annie Chine7c32322017-01-30 18:08:56 -0800128 final ArrayList<HistoryItem> newDataSet = new ArrayList<>();
Annie Chinbc001882016-11-09 19:41:21 -0800129
Annie Chinbfffafd2017-01-25 15:51:11 -0800130 if (!mIsDisplayEmpty && !isResultLayout) {
Annie Chine7c32322017-01-30 18:08:56 -0800131 // Add the current expression as the first element in the list (the layout is
132 // reversed and we want the current expression to be the last one in the
133 // RecyclerView).
134 // If we are in the result state, the result will animate to the last history
135 // element in the list and there will be no "Current Expression."
136 mEvaluator.copyMainToHistory();
137 newDataSet.add(new HistoryItem(Evaluator.HISTORY_MAIN_INDEX,
138 System.currentTimeMillis(), mEvaluator.getExprAsSpannable(0)));
Annie Chin06fd3cf2016-11-07 16:04:33 -0800139 }
Annie Chine7c32322017-01-30 18:08:56 -0800140 for (long i = 0; i < maxIndex; ++i) {
141 newDataSet.add(null);
142 }
143 final boolean isEmpty = newDataSet.isEmpty();
144 mRecyclerView.setBackgroundColor(ContextCompat.getColor(activity,
145 isEmpty ? R.color.empty_history_color : R.color.display_background_color));
146 if (isEmpty) {
147 newDataSet.add(new HistoryItem());
148 }
149 mDataSet = newDataSet;
150 mAdapter.setDataSet(mDataSet);
151 mAdapter.setIsResultLayout(isResultLayout);
152 mAdapter.setIsOneLine(activity.isOneLine());
Annie Chinbfffafd2017-01-25 15:51:11 -0800153 mAdapter.setIsDisplayEmpty(mIsDisplayEmpty);
Annie Chinbc001882016-11-09 19:41:21 -0800154 mAdapter.notifyDataSetChanged();
Annie Chinefa259a2016-11-23 14:15:15 -0800155 }
Annie Chinbc001882016-11-09 19:41:21 -0800156
Annie Chinefa259a2016-11-23 14:15:15 -0800157 @Override
158 public void onStart() {
159 super.onStart();
Justin Klaassen39297782016-12-19 09:11:38 -0800160
Annie Chin88613232017-01-04 12:21:52 -0800161 final Calculator activity = (Calculator) getActivity();
Annie Chinbfffafd2017-01-25 15:51:11 -0800162 mDragController.initializeAnimation(activity.isResultLayout(), activity.isOneLine(),
163 mIsDisplayEmpty);
Annie Chind0f87d22016-10-24 09:04:12 -0700164 }
165
166 @Override
Justin Klaassen39297782016-12-19 09:11:38 -0800167 public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) {
168 if (enter) {
169 if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) {
170 return mDragLayout.createAnimator(true /* toOpen */);
171 } else {
172 return null;
173 }
174 }
175 return mDragLayout.createAnimator(false /* toOpen */);
176 }
177
178 @Override
179 public void onDestroy() {
180 super.onDestroy();
181
182 if (mDragLayout != null) {
183 mDragLayout.removeDragCallback(this);
Annie Chind0f87d22016-10-24 09:04:12 -0700184 }
Annie Chin06fd3cf2016-11-07 16:04:33 -0800185
Annie Chin1838cf72017-01-30 08:46:47 -0800186 if (mEvaluator != null) {
187 // Note that the view is destroyed when the fragment backstack is popped, so
188 // these are essentially called when the DragLayout is closed.
189 mEvaluator.cancelNonMain();
190 }
Annie Chind0f87d22016-10-24 09:04:12 -0700191 }
192
Annie Chinbfffafd2017-01-25 15:51:11 -0800193 private void initializeController(boolean isResult, boolean isOneLine, boolean isDisplayEmpty) {
Annie Chind0f87d22016-10-24 09:04:12 -0700194 mDragController.setDisplayFormula(
195 (CalculatorFormula) getActivity().findViewById(R.id.formula));
Annie Chind0f87d22016-10-24 09:04:12 -0700196 mDragController.setDisplayResult(
197 (CalculatorResult) getActivity().findViewById(R.id.result));
Annie Chind0f87d22016-10-24 09:04:12 -0700198 mDragController.setToolbar(getActivity().findViewById(R.id.toolbar));
Annie Chinbc001882016-11-09 19:41:21 -0800199 mDragController.setEvaluator(mEvaluator);
Annie Chinbfffafd2017-01-25 15:51:11 -0800200 mDragController.initializeController(isResult, isOneLine, isDisplayEmpty);
Annie Chind0f87d22016-10-24 09:04:12 -0700201 }
202
Christine Franks7485df52016-12-01 13:18:45 -0800203 public boolean stopActionModeOrContextMenu() {
Annie Chin1fcfc312016-12-06 09:36:36 -0800204 if (mRecyclerView == null) {
205 return false;
206 }
Christine Franks7485df52016-12-01 13:18:45 -0800207 for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
208 final View view = mRecyclerView.getChildAt(i);
209 final HistoryAdapter.ViewHolder viewHolder =
210 (HistoryAdapter.ViewHolder) mRecyclerView.getChildViewHolder(view);
Annie Chin532b77e2016-12-06 13:30:35 -0800211 if (viewHolder != null && viewHolder.getResult() != null
212 && viewHolder.getResult().stopActionModeOrContextMenu()) {
Christine Franks7485df52016-12-01 13:18:45 -0800213 return true;
214 }
215 }
216 return false;
217 }
Annie Chin52eed7a2017-01-04 15:06:05 -0800218
219 /* Begin override DragCallback methods. */
220
221 @Override
222 public void onStartDraggingOpen() {
223 // no-op
224 }
225
226 @Override
Justin Klaassen39297782016-12-19 09:11:38 -0800227 public void onInstanceStateRestored(boolean isOpen) {
228 if (isOpen) {
229 mRecyclerView.setVisibility(View.VISIBLE);
230 }
231 }
232
233 @Override
Annie Chin52eed7a2017-01-04 15:06:05 -0800234 public void whileDragging(float yFraction) {
Justin Klaassen39297782016-12-19 09:11:38 -0800235 if (isVisible() || isRemoving()) {
236 mDragController.animateViews(yFraction, mRecyclerView);
237 }
Annie Chin52eed7a2017-01-04 15:06:05 -0800238 }
239
240 @Override
241 public boolean shouldCaptureView(View view, int x, int y) {
Justin Klaassen39297782016-12-19 09:11:38 -0800242 return !mRecyclerView.canScrollVertically(1 /* scrolling down */);
Annie Chin52eed7a2017-01-04 15:06:05 -0800243 }
244
245 @Override
246 public int getDisplayHeight() {
247 return 0;
248 }
249
Annie Chin52eed7a2017-01-04 15:06:05 -0800250 /* End override DragCallback methods. */
Annie Chinabd202f2016-10-14 14:23:45 -0700251}