1287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinpackage com.android.deskclock.stopwatch;
265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
3cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultasimport android.animation.LayoutTransition;
476a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoroimport android.content.ActivityNotFoundException;
565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.content.Context;
6815e2f7431c590086d5bd4eee5d7bf08108c77ebIsaac Katzenelsonimport android.content.Intent;
743474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelsonimport android.content.SharedPreferences;
838d99f23dec1ff7816c8da5ce8a66f3991c67978Isaac Katzenelsonimport android.content.SharedPreferences.OnSharedPreferenceChangeListener;
9319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultasimport android.content.res.Configuration;
1065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.os.Bundle;
1164056d415395e8a275910646b4010f55afddec55Isaac Katzenelsonimport android.os.PowerManager;
1264056d415395e8a275910646b4010f55afddec55Isaac Katzenelsonimport android.os.PowerManager.WakeLock;
1343474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelsonimport android.preference.PreferenceManager;
1487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultasimport android.text.format.DateUtils;
1565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.view.LayoutInflater;
1665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.view.View;
1765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.view.ViewGroup;
18319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultasimport android.view.animation.Animation;
19319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultasimport android.view.animation.TranslateAnimation;
2065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.widget.BaseAdapter;
21d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhangimport android.widget.ListPopupWindow;
2265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.widget.ListView;
2365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport android.widget.TextView;
2465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
25c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultasimport com.android.deskclock.CircleButtonsLayout;
26287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinimport com.android.deskclock.CircleTimerView;
27832a20480e1e76d1df846ac20c0eb1fe702a41f8Sam Blitzsteinimport com.android.deskclock.DeskClock;
28287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinimport com.android.deskclock.DeskClockFragment;
29cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassenimport com.android.deskclock.LogUtils;
30287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinimport com.android.deskclock.R;
31287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzsteinimport com.android.deskclock.Utils;
3238d99f23dec1ff7816c8da5ce8a66f3991c67978Isaac Katzenelsonimport com.android.deskclock.timer.CountingTimerView;
33b29cd6c4f734e236a500f41d046105020b73513aIsaac Katzenelson
3465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelsonimport java.util.ArrayList;
3565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
3664056d415395e8a275910646b4010f55afddec55Isaac Katzenelsonpublic class StopwatchFragment extends DeskClockFragment
3764056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        implements OnSharedPreferenceChangeListener {
38cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    private static final boolean DEBUG = false;
3964056d415395e8a275910646b4010f55afddec55Isaac Katzenelson
4064056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    private static final String TAG = "StopwatchFragment";
4155f1b9fdaa89d5ecaae0777db979c0c67956d9e1Budi Kusmiantoro    private static final int STOPWATCH_REFRESH_INTERVAL_MILLIS = 25;
4255f1b9fdaa89d5ecaae0777db979c0c67956d9e1Budi Kusmiantoro
43287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    int mState = Stopwatches.STOPWATCH_RESET;
4465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
4565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    // Stopwatch views that are accessed by the activity
46660b5227d0f10c95389aad567618d23a130079b3Sam Blitzstein    private CircleTimerView mTime;
47fd544b56e462c0e871441bcd48797e022f61d8efIsaac Katzenelson    private CountingTimerView mTimeText;
48660b5227d0f10c95389aad567618d23a130079b3Sam Blitzstein    private ListView mLapsList;
49d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    private ListPopupWindow mSharePopup;
5064056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    private WakeLock mWakeLock;
51319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas    private CircleButtonsLayout mCircleLayout;
5265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
53cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    // Animation constants and objects
54cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    private LayoutTransition mLayoutTransition;
55cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    private LayoutTransition mCircleLayoutTransition;
56cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    private View mStartSpace;
57cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    private View mEndSpace;
58319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas    private boolean mSpacersUsed;
59cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas
6065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    // Used for calculating the time from the start taking into account the pause times
6165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    long mStartTime = 0;
6265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    long mAccumulatedTime = 0;
6365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
6465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    // Lap information
6565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    class Lap {
6665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
6765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        Lap (long time, long total) {
6865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            mLapTime = time;
6965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            mTotalTime = total;
7065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
7165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public long mLapTime;
7265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public long mTotalTime;
739c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas
74ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas        public void updateView() {
759c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            View lapInfo = mLapsList.findViewWithTag(this);
769c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            if (lapInfo != null) {
77ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas                mLapsAdapter.setTimeText(lapInfo, this);
789c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            }
799c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        }
8065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
8165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
8265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    // Adapter for the ListView that shows the lap times.
8365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    class LapsListAdapter extends BaseAdapter {
8465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
8565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        ArrayList<Lap> mLaps = new ArrayList<Lap>();
8665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        private final LayoutInflater mInflater;
8787bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private final String[] mFormats;
8887bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private final String[] mLapFormatSet;
8987bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        // Size of this array must match the size of formats
9087bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private final long[] mThresholds = {
9187bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                10 * DateUtils.MINUTE_IN_MILLIS, // < 10 minutes
9287bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                DateUtils.HOUR_IN_MILLIS, // < 1 hour
9387bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                10 * DateUtils.HOUR_IN_MILLIS, // < 10 hours
9487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                100 * DateUtils.HOUR_IN_MILLIS, // < 100 hours
9587bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                1000 * DateUtils.HOUR_IN_MILLIS // < 1000 hours
9687bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        };
9787bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private int mLapIndex = 0;
9887bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private int mTotalIndex = 0;
9987bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private String mLapFormat;
10065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
10165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public LapsListAdapter(Context context) {
1027b508cb8b3f621b6ea35ecb61773359093a61b81Isaac Katzenelson            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
10387bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mFormats = context.getResources().getStringArray(R.array.stopwatch_format_set);
10487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mLapFormatSet = context.getResources().getStringArray(R.array.sw_lap_number_set);
10587bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            updateLapFormat();
10665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
10765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
10865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        @Override
10965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public long getItemId(int position) {
11065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            return position;
11165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
11265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
11365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        @Override
11465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public View getView(int position, View convertView, ViewGroup parent) {
11565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (mLaps.size() == 0 || position >= mLaps.size()) {
11665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                return null;
11765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
1189c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            Lap lap = getItem(position);
11965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            View lapInfo;
12065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (convertView != null) {
12165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                lapInfo = convertView;
12265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            } else {
1239c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas                lapInfo = mInflater.inflate(R.layout.lap_view, parent, false);
12465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
1259c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            lapInfo.setTag(lap);
12665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            TextView count = (TextView)lapInfo.findViewById(R.id.lap_number);
127ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas            count.setText(String.format(mLapFormat, mLaps.size() - position).toUpperCase());
128ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas            setTimeText(lapInfo, lap);
129ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas
130ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas            return lapInfo;
131ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas        }
132ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas
133ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas        protected void setTimeText(View lapInfo, Lap lap) {
13465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            TextView lapTime = (TextView)lapInfo.findViewById(R.id.lap_time);
1359c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            TextView totalTime = (TextView)lapInfo.findViewById(R.id.lap_total);
1369c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            lapTime.setText(Stopwatches.formatTimeText(lap.mLapTime, mFormats[mLapIndex]));
1379c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            totalTime.setText(Stopwatches.formatTimeText(lap.mTotalTime, mFormats[mTotalIndex]));
13865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
13965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
14065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        @Override
14165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public int getCount() {
14265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            return mLaps.size();
14365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
14465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
14565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        @Override
1469c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        public Lap getItem(int position) {
14765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (mLaps.size() == 0 || position >= mLaps.size()) {
14865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                return null;
14965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
15065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            return mLaps.get(position);
15165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
15265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
15387bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private void updateLapFormat() {
15487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            // Note Stopwatches.MAX_LAPS < 100
15587bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mLapFormat = mLapFormatSet[mLaps.size() < 10 ? 0 : 1];
15687bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        }
15787bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas
15887bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        private void resetTimeFormats() {
15987bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mLapIndex = mTotalIndex = 0;
16087bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        }
16187bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas
1629c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        /**
1639c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         * A lap is printed into two columns: the total time and the lap time. To make this print
1649c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         * as pretty as possible, multiple formats were created which minimize the width of the
1659c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         * print. As the total or lap time exceed the limit of that format, this code updates
1669c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         * the format used for the total and/or lap times.
1679c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         *
1689c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         * @param lap to measure
1699c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         * @return true if this lap exceeded either threshold and a format was updated.
1709c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas         */
17187bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        public boolean updateTimeFormats(Lap lap) {
17287bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            boolean formatChanged = false;
17387bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            while (mLapIndex + 1 < mThresholds.length && lap.mLapTime >= mThresholds[mLapIndex]) {
17487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                mLapIndex++;
17587bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                formatChanged = true;
17687bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            }
177d48339f270ba72bb8416fd194b4a0d1aeb3bd958rachelzhang            while (mTotalIndex + 1 < mThresholds.length &&
1782caafe1670be104d4d4781f0b0fab2e9ae2153b7Romain Guy                lap.mTotalTime >= mThresholds[mTotalIndex]) {
17987bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                mTotalIndex++;
18087bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                formatChanged = true;
18187bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            }
18287bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            return formatChanged;
18387bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas        }
18487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas
18565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public void addLap(Lap l) {
18665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            mLaps.add(0, l);
18787bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            // for efficiency caller also calls notifyDataSetChanged()
18865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
18965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
19065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public void clearLaps() {
19165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            mLaps.clear();
19287bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            updateLapFormat();
19387bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            resetTimeFormats();
19465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            notifyDataSetChanged();
19565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
19665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
197c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        // Helper function used to get the lap data to be stored in the activity's bundle
19865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public long [] getLapTimes() {
19965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            int size = mLaps.size();
20065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (size == 0) {
20165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                return null;
20265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
20365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            long [] laps = new long[size];
20465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            for (int i = 0; i < size; i ++) {
205287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                laps[i] = mLaps.get(i).mTotalTime;
20665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
20765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            return laps;
20865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
20965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
21065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        // Helper function to restore adapter's data from the activity's bundle
21165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public void setLapTimes(long [] laps) {
21265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (laps == null || laps.length == 0) {
21365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                return;
21465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
21565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
21665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            int size = laps.length;
21765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            mLaps.clear();
218c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            for (long lap : laps) {
219c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas                mLaps.add(new Lap(lap, 0));
22065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
22165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            long totalTime = 0;
22265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            for (int i = size -1; i >= 0; i --) {
22365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                totalTime += laps[i];
22465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                mLaps.get(i).mTotalTime = totalTime;
22587bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas                updateTimeFormats(mLaps.get(i));
22665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
22787bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            updateLapFormat();
228c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            showLaps();
22965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            notifyDataSetChanged();
23065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
23165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
23265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
23365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    LapsListAdapter mLapsAdapter;
23465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
23565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    public StopwatchFragment() {
23665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
23765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
2384261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting    private void rightButtonAction() {
2394261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        long time = Utils.getTimeNow();
2404261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        Context context = getActivity().getApplicationContext();
2414261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        Intent intent = new Intent(context, StopwatchService.class);
2424261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        intent.putExtra(Stopwatches.MESSAGE_TIME, time);
2434261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        intent.putExtra(Stopwatches.SHOW_NOTIF, false);
2444261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        switch (mState) {
2454261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting            case Stopwatches.STOPWATCH_RUNNING:
2464261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                // do stop
2474261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                long curTime = Utils.getTimeNow();
2484261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                mAccumulatedTime += (curTime - mStartTime);
2494261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                doStop();
2504261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                intent.setAction(Stopwatches.STOP_STOPWATCH);
2514261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                context.startService(intent);
25264056d415395e8a275910646b4010f55afddec55Isaac Katzenelson                releaseWakeLock();
2534261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                break;
2544261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting            case Stopwatches.STOPWATCH_RESET:
2554261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting            case Stopwatches.STOPWATCH_STOPPED:
2564261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                // do start
2574261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                doStart(time);
2584261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                intent.setAction(Stopwatches.START_STOPWATCH);
2594261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                context.startService(intent);
26064056d415395e8a275910646b4010f55afddec55Isaac Katzenelson                acquireWakeLock();
2614261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                break;
2624261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting            default:
263cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen                LogUtils.wtf("Illegal state " + mState
2644261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                        + " while pressing the right stopwatch button");
2654261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting                break;
2664261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting        }
2674261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting    }
2684261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting
26965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    @Override
27065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    public View onCreateView(LayoutInflater inflater, ViewGroup container,
27165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson                             Bundle savedInstanceState) {
27265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        // Inflate the layout for this fragment
273cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        ViewGroup v = (ViewGroup)inflater.inflate(R.layout.stopwatch_fragment, container, false);
274287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
275c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mTime = (CircleTimerView)v.findViewById(R.id.stopwatch_time);
276c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mTimeText = (CountingTimerView)v.findViewById(R.id.stopwatch_time_text);
277c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mLapsList = (ListView)v.findViewById(R.id.laps_list);
278c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mLapsList.setDividerHeight(0);
279c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mLapsAdapter = new LapsListAdapter(getActivity());
280c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mLapsList.setAdapter(mLapsAdapter);
281c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas
282c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        mTimeText.setVirtualButtonEnabled(true);
2834261870a93db4e92bf5c08a9a253c9c5ff80d41cSara Ting
284319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayout = (CircleButtonsLayout)v.findViewById(R.id.stopwatch_circle);
285d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        mCircleLayout.setCircleTimerViewIds(R.id.stopwatch_time, 0 /* stopwatchId */ ,
286d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                0 /* labelId */,  0 /* labeltextId */);
28700cb5981c984bc13aa2f6af510a9dd9a784f2af0Sam Blitzstein
288cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        // Animation setup
289319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mLayoutTransition = new LayoutTransition();
290319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition = new LayoutTransition();
291319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
292319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        // The CircleButtonsLayout only needs to undertake location changes
293319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition.enableTransitionType(LayoutTransition.CHANGING);
294319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition.disableTransitionType(LayoutTransition.APPEARING);
295319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition.disableTransitionType(LayoutTransition.DISAPPEARING);
296319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
297319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
298319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayoutTransition.setAnimateParentHierarchy(false);
299319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
300319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        // These spacers assist in keeping the size of CircleButtonsLayout constant
301cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        mStartSpace = v.findViewById(R.id.start_space);
302cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        mEndSpace = v.findViewById(R.id.end_space);
303319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mSpacersUsed = mStartSpace != null || mEndSpace != null;
304319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        // Listener to invoke extra animation within the laps-list
305319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mLayoutTransition.addTransitionListener(new LayoutTransition.TransitionListener() {
306319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            @Override
307319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            public void startTransition(LayoutTransition transition, ViewGroup container,
308319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                        View view, int transitionType) {
309319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                if (view == mLapsList) {
310319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    if (transitionType == LayoutTransition.DISAPPEARING) {
311cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen                        if (DEBUG) LogUtils.v("StopwatchFragment.start laps-list disappearing");
312319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        boolean shiftX = view.getResources().getConfiguration().orientation
313319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                == Configuration.ORIENTATION_LANDSCAPE;
314319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        int first = mLapsList.getFirstVisiblePosition();
315319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        int last = mLapsList.getLastVisiblePosition();
316319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        // Ensure index range will not cause a divide by zero
317319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        if (last < first) {
318319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            last = first;
319319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        }
320319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        long duration = transition.getDuration(LayoutTransition.DISAPPEARING);
321319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        long offset = duration / (last - first + 1) / 5;
322319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        for (int visibleIndex = first; visibleIndex <= last; visibleIndex++) {
323319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            View lapView = mLapsList.getChildAt(visibleIndex - first);
324319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            if (lapView != null) {
325319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                float toXValue = shiftX ? 1.0f * (visibleIndex - first + 1) : 0;
326319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                float toYValue = shiftX ? 0 : 4.0f * (visibleIndex - first + 1);
327319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                        TranslateAnimation animation = new TranslateAnimation(
328319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                        Animation.RELATIVE_TO_SELF, 0,
329319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                        Animation.RELATIVE_TO_SELF, toXValue,
330319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                        Animation.RELATIVE_TO_SELF, 0,
331319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                        Animation.RELATIVE_TO_SELF, toYValue);
332319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                animation.setStartOffset((last - visibleIndex) * offset);
333319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                animation.setDuration(duration);
334319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                lapView.startAnimation(animation);
335319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            }
336319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        }
337319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    }
338319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                }
339319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            }
340319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
341319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            @Override
342319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            public void endTransition(LayoutTransition transition, ViewGroup container,
343319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                      View view, int transitionType) {
344319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                if (transitionType == LayoutTransition.DISAPPEARING) {
345cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen                    if (DEBUG) LogUtils.v("StopwatchFragment.end laps-list disappearing");
346319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    int last = mLapsList.getLastVisiblePosition();
347319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    for (int visibleIndex = mLapsList.getFirstVisiblePosition();
348319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                         visibleIndex <= last; visibleIndex++) {
349319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        View lapView = mLapsList.getChildAt(visibleIndex);
350319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        if (lapView != null) {
351319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            Animation animation = lapView.getAnimation();
352319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            if (animation != null) {
353319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                                animation.cancel();
354319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                            }
355319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                        }
356319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    }
357319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                }
358319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            }
359319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        });
360cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas
36165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        return v;
36265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
36365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
364cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    /**
365319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas     * Make the final display setup.
366319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas     *
367319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas     * If the fragment is starting with an existing list of laps, shows the laps list and if the
368319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas     * spacers around the clock exist, hide them. If there are not laps at the start, hide the laps
369319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas     * list and show the clock spacers if they exist.
370cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas     */
371cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    @Override
372cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    public void onStart() {
373cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        super.onStart();
374319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
375319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        boolean lapsVisible = mLapsAdapter.getCount() > 0;
376319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
377319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mLapsList.setVisibility(lapsVisible ? View.VISIBLE : View.GONE);
378319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        if (mSpacersUsed) {
379319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            int spacersVisibility = lapsVisible ? View.GONE : View.VISIBLE;
380319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            if (mStartSpace != null) {
381319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                mStartSpace.setVisibility(spacersVisibility);
382319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            }
383319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            if (mEndSpace != null) {
384319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                mEndSpace.setVisibility(spacersVisibility);
385319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            }
386319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        }
387319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        ((ViewGroup)getView()).setLayoutTransition(mLayoutTransition);
388319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        mCircleLayout.setLayoutTransition(mCircleLayoutTransition);
389cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    }
390cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas
39165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    @Override
39265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    public void onResume() {
3937b508cb8b3f621b6ea35ecb61773359093a61b81Isaac Katzenelson        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
394287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        prefs.registerOnSharedPreferenceChangeListener(this);
39543474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        readFromSharedPref(prefs);
39643474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        mTime.readFromSharedPref(prefs, "sw");
397287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTime.postInvalidate();
398287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
3995e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setFabAppearance();
4005e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setLeftRightButtonAppearance();
40126fd3d012330e5abf4f6452e811938374004d0d8Sam Blitzstein        mTimeText.setTime(mAccumulatedTime, true, true);
402287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (mState == Stopwatches.STOPWATCH_RUNNING) {
40364056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            acquireWakeLock();
40465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            startUpdateThread();
405287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        } else if (mState == Stopwatches.STOPWATCH_STOPPED && mAccumulatedTime != 0) {
40643474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson            mTimeText.blinkTimeStr(true);
40765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
40865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        showLaps();
40964056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        ((DeskClock)getActivity()).registerPageChangedListener(this);
4109633b6cffd00506af022cbde5315b707c5b20e84Isaac Katzenelson        // View was hidden in onPause, make sure it is visible now.
4119633b6cffd00506af022cbde5315b707c5b20e84Isaac Katzenelson        View v = getView();
4129633b6cffd00506af022cbde5315b707c5b20e84Isaac Katzenelson        if (v != null) {
413c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            v.setVisibility(View.VISIBLE);
4149633b6cffd00506af022cbde5315b707c5b20e84Isaac Katzenelson        }
41565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        super.onResume();
41665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
41765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
41865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    @Override
41965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    public void onPause() {
420287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (mState == Stopwatches.STOPWATCH_RUNNING) {
42165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            stopUpdateThread();
42276a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro
42376a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            // This is called because the lock screen was activated, the window stay
42476a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            // active under it and when we unlock the screen, we see the old time for
42576a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            // a fraction of a second.
42676a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            View v = getView();
42776a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            if (v != null) {
42876a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro                v.setVisibility(View.INVISIBLE);
42976a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            }
43065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
43143474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        // The stopwatch must keep running even if the user closes the app so save stopwatch state
43243474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        // in shared prefs
4337b508cb8b3f621b6ea35ecb61773359093a61b81Isaac Katzenelson        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
434287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        prefs.unregisterOnSharedPreferenceChangeListener(this);
43543474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        writeToSharedPref(prefs);
43643474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        mTime.writeToSharedPref(prefs, "sw");
437dbefec37e0c0a3a8d832e5c34697fa0492e1077cIsaac Katzenelson        mTimeText.blinkTimeStr(false);
43864056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        ((DeskClock)getActivity()).unregisterPageChangedListener(this);
43964056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        releaseWakeLock();
44065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        super.onPause();
44165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
44265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
44364056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    @Override
44464056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    public void onPageChanged(int page) {
44564056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        if (page == DeskClock.STOPWATCH_TAB_INDEX && mState == Stopwatches.STOPWATCH_RUNNING) {
44664056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            acquireWakeLock();
44764056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        } else {
44864056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            releaseWakeLock();
44964056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        }
45064056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    }
45164056d415395e8a275910646b4010f55afddec55Isaac Katzenelson
452287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    private void doStop() {
453cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        if (DEBUG) LogUtils.v("StopwatchFragment.doStop");
454287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        stopUpdateThread();
455287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTime.pauseIntervalAnimation();
45626fd3d012330e5abf4f6452e811938374004d0d8Sam Blitzstein        mTimeText.setTime(mAccumulatedTime, true, true);
457287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTimeText.blinkTimeStr(true);
458287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        updateCurrentLap(mAccumulatedTime);
459287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mState = Stopwatches.STOPWATCH_STOPPED;
4605e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setFabAppearance();
4615e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setLeftRightButtonAppearance();
462287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
463287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
464287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    private void doStart(long time) {
465cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        if (DEBUG) LogUtils.v("StopwatchFragment.doStart");
466287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mStartTime = time;
467287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        startUpdateThread();
468287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTimeText.blinkTimeStr(false);
469287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (mTime.isAnimating()) {
470287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            mTime.startIntervalAnimation();
471287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        }
472287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mState = Stopwatches.STOPWATCH_RUNNING;
4735e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setFabAppearance();
4745e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setLeftRightButtonAppearance();
475287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
476287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
477287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    private void doLap() {
478cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        if (DEBUG) LogUtils.v("StopwatchFragment.doLap");
479287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        showLaps();
4805e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setFabAppearance();
4815e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setLeftRightButtonAppearance();
482287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
483287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
484287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    private void doReset() {
485cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        if (DEBUG) LogUtils.v("StopwatchFragment.doReset");
486287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        SharedPreferences prefs =
487287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                PreferenceManager.getDefaultSharedPreferences(getActivity());
488de5f183f54b5d10bc8cbebb977c7c8ab391ad3f5Isaac Katzenelson        Utils.clearSwSharedPref(prefs);
489287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTime.clearSharedPref(prefs, "sw");
490287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mAccumulatedTime = 0;
491287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mLapsAdapter.clearLaps();
492287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        showLaps();
493287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTime.stopIntervalAnimation();
494287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTime.reset();
49526fd3d012330e5abf4f6452e811938374004d0d8Sam Blitzstein        mTimeText.setTime(mAccumulatedTime, true, true);
496287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mTimeText.blinkTimeStr(false);
497287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mState = Stopwatches.STOPWATCH_RESET;
4985e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setFabAppearance();
4995e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        setLeftRightButtonAppearance();
50065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
50165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
50276a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro    private void shareResults() {
50376a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        final Context context = getActivity();
50476a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        final Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
50576a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        shareIntent.setType("text/plain");
50676a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
50776a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        shareIntent.putExtra(Intent.EXTRA_SUBJECT,
50876a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro                Stopwatches.getShareTitle(context.getApplicationContext()));
50976a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        shareIntent.putExtra(Intent.EXTRA_TEXT, Stopwatches.buildShareResults(
510287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                getActivity().getApplicationContext(), mTimeText.getTimeString(),
511287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                getLapShareTimes(mLapsAdapter.getLapTimes())));
51276a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro
51376a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        final Intent launchIntent = Intent.createChooser(shareIntent,
51476a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro                context.getString(R.string.sw_share_button));
51576a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        try {
51676a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro            context.startActivity(launchIntent);
51776a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        } catch (ActivityNotFoundException e) {
518cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen            LogUtils.e("No compatible receiver is found");
51976a34b3ddb42e172900ad984ea327d030e805befBudi Kusmiantoro        }
520287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
521287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
522287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    /** Turn laps as they would be saved in prefs into format for sharing. **/
523287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    private long[] getLapShareTimes(long[] input) {
524287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (input == null) {
525287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            return null;
526287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        }
527287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
528287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        int numLaps = input.length;
529287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        long[] output = new long[numLaps];
530287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        long prevLapElapsedTime = 0;
531287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        for (int lap_i = numLaps - 1; lap_i >= 0; lap_i--) {
532287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            long lap = input[lap_i];
533cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen            LogUtils.v("lap " + lap_i + ": " + lap);
534287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            output[lap_i] = lap - prevLapElapsedTime;
535287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            prevLapElapsedTime = lap;
536287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        }
537287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        return output;
538287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
539287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein
54065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    private boolean reachedMaxLaps() {
541287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        return mLapsAdapter.getCount() >= Stopwatches.MAX_LAPS;
54265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
54365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
54465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    /***
545c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas     * Handle action when user presses the lap button
5469c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas     * @param time - in hundredth of a second
5474ad5b75cd1c5ec94b2122f10f2f02137e1c0e9b2Isaac Katzenelson     */
54865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    private void addLapTime(long time) {
549c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        // The total elapsed time
550c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        final long curTime = time - mStartTime + mAccumulatedTime;
55165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        int size = mLapsAdapter.getCount();
55265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        if (size == 0) {
553c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            // Create and add the first lap
55487bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            Lap firstLap = new Lap(curTime, curTime);
55587bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mLapsAdapter.addLap(firstLap);
556c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            // Create the first active lap
55765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            mLapsAdapter.addLap(new Lap(0, curTime));
558c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            // Update the interval on the clock and check the lap and total time formatting
559287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            mTime.setIntervalTime(curTime);
56087bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mLapsAdapter.updateTimeFormats(firstLap);
56165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        } else {
562c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            // Finish active lap
563c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            final long lapTime = curTime - mLapsAdapter.getItem(1).mTotalTime;
5649c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            mLapsAdapter.getItem(0).mLapTime = lapTime;
5659c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            mLapsAdapter.getItem(0).mTotalTime = curTime;
566c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            // Create a new active lap
567c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            mLapsAdapter.addLap(new Lap(0, curTime));
568c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas            // Update marker on clock and check that formatting for the lap number
569287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            mTime.setMarkerTime(lapTime);
57087bf27c22cf71bfb89e97eba92d4513148d3d8c8Robyn Coultas            mLapsAdapter.updateLapFormat();
57165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
572c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas        // Repaint the laps list
57365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        mLapsAdapter.notifyDataSetChanged();
574c9524f8b8216c7854de4c69c44c9bb63e4097a18Robyn Coultas
57565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        // Start lap animation starting from the second lap
5769c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        mTime.stopIntervalAnimation();
5779c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        if (!reachedMaxLaps()) {
5789c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            mTime.startIntervalAnimation();
5799c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        }
58065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
58165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
582287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    private void updateCurrentLap(long totalTime) {
5839c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas        // There are either 0, 2 or more Laps in the list See {@link #addLapTime}
58465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        if (mLapsAdapter.getCount() > 0) {
5859c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            Lap curLap = mLapsAdapter.getItem(0);
5869c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            curLap.mLapTime = totalTime - mLapsAdapter.getItem(1).mTotalTime;
58765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            curLap.mTotalTime = totalTime;
5889c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            // If this lap has caused a change in the format for total and/or lap time, all of
5899c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            // the rows need a fresh print. The simplest way to refresh all of the rows is
5909c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            // calling notifyDataSetChanged.
5919c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            if (mLapsAdapter.updateTimeFormats(curLap)) {
5929c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas                mLapsAdapter.notifyDataSetChanged();
5939c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            } else {
594ab7b489e853a376d4e06d74c5ee42747bb8ffed7Robyn Coultas                curLap.updateView();
5959c483781c2a4bbc2b7ca228ea959f99cc0be149bRobyn Coultas            }
59665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
59765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
59865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
599cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas    /**
600cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas     * Show or hide the laps-list
601cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas     */
60265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    private void showLaps() {
603cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen        if (DEBUG) LogUtils.v(String.format("StopwatchFragment.showLaps: count=%d",
604cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas                mLapsAdapter.getCount()));
605cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas
606319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        boolean lapsVisible = mLapsAdapter.getCount() > 0;
607319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
608cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        // Layout change animations will start upon the first add/hide view. Temporarily disable
609cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        // the layout transition animation for the spacers, make the changes, then re-enable
610cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        // the animation for the add/hide laps-list
611319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        if (mSpacersUsed) {
612319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            int spacersVisibility = lapsVisible ? View.GONE : View.VISIBLE;
613cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            ViewGroup rootView = (ViewGroup) getView();
614319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            if (rootView != null) {
615319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                rootView.setLayoutTransition(null);
616319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                if (mStartSpace != null) {
617319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    mStartSpace.setVisibility(spacersVisibility);
618319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                }
619319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                if (mEndSpace != null) {
620319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                    mEndSpace.setVisibility(spacersVisibility);
621319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                }
622319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas                rootView.setLayoutTransition(mLayoutTransition);
623cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            }
624cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas        }
625cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas
626319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas        if (lapsVisible) {
627cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            // There are laps - show the laps-list
628cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            // No delay for the CircleButtonsLayout changes - start immediately so that the
629cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            // circle has shifted before the laps-list starts appearing.
630cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            mCircleLayoutTransition.setStartDelay(LayoutTransition.CHANGING, 0);
631319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas
632319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            mLapsList.setVisibility(View.VISIBLE);
63365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        } else {
634cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            // There are no laps - hide the laps list
635cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas
636319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            // Delay the CircleButtonsLayout animation until after the laps-list disappears
637cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            long startDelay = mLayoutTransition.getStartDelay(LayoutTransition.DISAPPEARING) +
638cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas                    mLayoutTransition.getDuration(LayoutTransition.DISAPPEARING);
639cffb4dbf6e1fed0e0c18c2ea5073227c85ca3f9aRobyn Coultas            mCircleLayoutTransition.setStartDelay(LayoutTransition.CHANGING, startDelay);
640319265e3e8564f3e71dca8bc752632c9a1708938Robyn Coultas            mLapsList.setVisibility(View.GONE);
64165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
64265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
64365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
64465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    private void startUpdateThread() {
64565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        mTime.post(mTimeUpdateThread);
64665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
64765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
64865d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    private void stopUpdateThread() {
64965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        mTime.removeCallbacks(mTimeUpdateThread);
65065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    }
65165d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
65265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    Runnable mTimeUpdateThread = new Runnable() {
65365d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        @Override
65465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        public void run() {
655287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            long curTime = Utils.getTimeNow();
65665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            long totalTime = mAccumulatedTime + (curTime - mStartTime);
65765d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (mTime != null) {
65826fd3d012330e5abf4f6452e811938374004d0d8Sam Blitzstein                mTimeText.setTime(totalTime, true, true);
65965d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
66065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            if (mLapsAdapter.getCount() > 0) {
661287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                updateCurrentLap(totalTime);
66265d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson            }
66355f1b9fdaa89d5ecaae0777db979c0c67956d9e1Budi Kusmiantoro            mTime.postDelayed(mTimeUpdateThread, STOPWATCH_REFRESH_INTERVAL_MILLIS);
66465d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson        }
66565d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson    };
66665d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson
66743474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson    private void writeToSharedPref(SharedPreferences prefs) {
66843474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        SharedPreferences.Editor editor = prefs.edit();
669287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        editor.putLong (Stopwatches.PREF_START_TIME, mStartTime);
670287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        editor.putLong (Stopwatches.PREF_ACCUM_TIME, mAccumulatedTime);
671287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        editor.putInt (Stopwatches.PREF_STATE, mState);
67243474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        if (mLapsAdapter != null) {
67343474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson            long [] laps = mLapsAdapter.getLapTimes();
67443474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson            if (laps != null) {
675287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                editor.putInt (Stopwatches.PREF_LAP_NUM, laps.length);
67643474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson                for (int i = 0; i < laps.length; i++) {
677287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    String key = Stopwatches.PREF_LAP_TIME + Integer.toString(laps.length - i);
67843474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson                    editor.putLong (key, laps[i]);
67943474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson                }
68043474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson            }
68143474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        }
682287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (mState == Stopwatches.STOPWATCH_RUNNING) {
683287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.putLong(Stopwatches.NOTIF_CLOCK_BASE, mStartTime-mAccumulatedTime);
684287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.putLong(Stopwatches.NOTIF_CLOCK_ELAPSED, -1);
685287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.putBoolean(Stopwatches.NOTIF_CLOCK_RUNNING, true);
686287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        } else if (mState == Stopwatches.STOPWATCH_STOPPED) {
687287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.putLong(Stopwatches.NOTIF_CLOCK_ELAPSED, mAccumulatedTime);
688287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.putLong(Stopwatches.NOTIF_CLOCK_BASE, -1);
689287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.putBoolean(Stopwatches.NOTIF_CLOCK_RUNNING, false);
690287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        } else if (mState == Stopwatches.STOPWATCH_RESET) {
691287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.remove(Stopwatches.NOTIF_CLOCK_BASE);
692287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.remove(Stopwatches.NOTIF_CLOCK_RUNNING);
693287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            editor.remove(Stopwatches.NOTIF_CLOCK_ELAPSED);
694287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        }
695287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        editor.putBoolean(Stopwatches.PREF_UPDATE_CIRCLE, false);
69643474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        editor.apply();
69743474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson    }
69843474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson
69943474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson    private void readFromSharedPref(SharedPreferences prefs) {
700287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mStartTime = prefs.getLong(Stopwatches.PREF_START_TIME, 0);
701287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mAccumulatedTime = prefs.getLong(Stopwatches.PREF_ACCUM_TIME, 0);
702287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        mState = prefs.getInt(Stopwatches.PREF_STATE, Stopwatches.STOPWATCH_RESET);
703287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        int numLaps = prefs.getInt(Stopwatches.PREF_LAP_NUM, Stopwatches.STOPWATCH_RESET);
70443474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        if (mLapsAdapter != null) {
705287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            long[] oldLaps = mLapsAdapter.getLapTimes();
706287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            if (oldLaps == null || oldLaps.length < numLaps) {
707287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                long[] laps = new long[numLaps];
708287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                long prevLapElapsedTime = 0;
709287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                for (int lap_i = 0; lap_i < numLaps; lap_i++) {
710287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    String key = Stopwatches.PREF_LAP_TIME + Integer.toString(lap_i + 1);
711287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    long lap = prefs.getLong(key, 0);
712287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    laps[numLaps - lap_i - 1] = lap - prevLapElapsedTime;
713287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    prevLapElapsedTime = lap;
714287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                }
715287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                mLapsAdapter.setLapTimes(laps);
716287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            }
717287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        }
718287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (prefs.getBoolean(Stopwatches.PREF_UPDATE_CIRCLE, true)) {
719287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            if (mState == Stopwatches.STOPWATCH_STOPPED) {
720287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                doStop();
721287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            } else if (mState == Stopwatches.STOPWATCH_RUNNING) {
722287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                doStart(mStartTime);
723287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            } else if (mState == Stopwatches.STOPWATCH_RESET) {
724287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                doReset();
72543474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson            }
72643474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson        }
72743474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson    }
72843474e446f4fd103b0f609d1be75c4825adb8b58Isaac Katzenelson
729287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    @Override
730287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
731287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        if (prefs.equals(PreferenceManager.getDefaultSharedPreferences(getActivity()))) {
732287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            if (! (key.equals(Stopwatches.PREF_LAP_NUM) ||
733287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    key.startsWith(Stopwatches.PREF_LAP_TIME))) {
734287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                readFromSharedPref(prefs);
735287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                if (prefs.getBoolean(Stopwatches.PREF_UPDATE_CIRCLE, true)) {
736287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                    mTime.readFromSharedPref(prefs, "sw");
737287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein                }
738287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein            }
739287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein        }
740287f2d82aaf91d881f5de50a133d21684a8d4821Sam Blitzstein    }
74164056d415395e8a275910646b4010f55afddec55Isaac Katzenelson
74264056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    // Used to keeps screen on when stopwatch is running.
74364056d415395e8a275910646b4010f55afddec55Isaac Katzenelson
74464056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    private void acquireWakeLock() {
74564056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        if (mWakeLock == null) {
74664056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            final PowerManager pm =
74764056d415395e8a275910646b4010f55afddec55Isaac Katzenelson                    (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
74864056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            mWakeLock = pm.newWakeLock(
74964056d415395e8a275910646b4010f55afddec55Isaac Katzenelson                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG);
75064056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            mWakeLock.setReferenceCounted(false);
75164056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        }
75264056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        mWakeLock.acquire();
75364056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    }
75464056d415395e8a275910646b4010f55afddec55Isaac Katzenelson
75564056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    private void releaseWakeLock() {
75664056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        if (mWakeLock != null && mWakeLock.isHeld()) {
75764056d415395e8a275910646b4010f55afddec55Isaac Katzenelson            mWakeLock.release();
75864056d415395e8a275910646b4010f55afddec55Isaac Katzenelson        }
75964056d415395e8a275910646b4010f55afddec55Isaac Katzenelson    }
76064056d415395e8a275910646b4010f55afddec55Isaac Katzenelson
7615520461495a8c4fb468aa94d7b18a3fc25d54739rachelzhang    @Override
762d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    public void onFabClick(View view){
7635520461495a8c4fb468aa94d7b18a3fc25d54739rachelzhang        rightButtonAction();
7645520461495a8c4fb468aa94d7b18a3fc25d54739rachelzhang    }
7655520461495a8c4fb468aa94d7b18a3fc25d54739rachelzhang
7665520461495a8c4fb468aa94d7b18a3fc25d54739rachelzhang    @Override
767d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    public void onLeftButtonClick(View view) {
768d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        final long time = Utils.getTimeNow();
769d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        final Context context = getActivity().getApplicationContext();
770d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        final Intent intent = new Intent(context, StopwatchService.class);
771d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        intent.putExtra(Stopwatches.MESSAGE_TIME, time);
772d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        intent.putExtra(Stopwatches.SHOW_NOTIF, false);
773d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        switch (mState) {
774d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang            case Stopwatches.STOPWATCH_RUNNING:
775d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                // Save lap time
776d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                addLapTime(time);
777d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                doLap();
778d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                intent.setAction(Stopwatches.LAP_STOPWATCH);
779d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                context.startService(intent);
780d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                break;
781d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang            case Stopwatches.STOPWATCH_STOPPED:
782d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                // do reset
783d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                doReset();
784d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                intent.setAction(Stopwatches.RESET_STOPWATCH);
785d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                context.startService(intent);
786d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                releaseWakeLock();
787d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                break;
788d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang            default:
789d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                // Happens in monkey tests
790cdbb71b08c13c84af850f4036febc0b90dcfcc7dJustin Klaassen                LogUtils.i("Illegal state " + mState + " while pressing the left stopwatch button");
791d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang                break;
792d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        }
793d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    }
794d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang
795d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    @Override
796d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    public void onRightButtonClick(View view) {
797d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        shareResults();
798d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    }
799d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang
800d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    @Override
8015e469aa155baea98f09d5d5e657aa2315a76679drachelzhang    public void setFabAppearance() {
8025e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        final DeskClock activity = (DeskClock) getActivity();
8035e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        if (mFab == null || activity.getSelectedTab() != DeskClock.STOPWATCH_TAB_INDEX) {
804d0a9d2681d5386471f59cbe3a3962657266905caBudi Kusmiantoro            return;
805d0a9d2681d5386471f59cbe3a3962657266905caBudi Kusmiantoro        }
80689b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro        if (mState == Stopwatches.STOPWATCH_RUNNING) {
80789b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro            mFab.setImageResource(R.drawable.ic_fab_pause);
80889b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro            mFab.setContentDescription(getString(R.string.sw_stop_button));
80989b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro        } else {
81089b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro            mFab.setImageResource(R.drawable.ic_fab_play);
81189b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro            mFab.setContentDescription(getString(R.string.sw_start_button));
81289b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro        }
813d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        mFab.setVisibility(View.VISIBLE);
814d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    }
815d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang
816d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang    @Override
8175e469aa155baea98f09d5d5e657aa2315a76679drachelzhang    public void setLeftRightButtonAppearance() {
8185e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        final DeskClock activity = (DeskClock) getActivity();
8195e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        if (mLeftButton == null || mRightButton == null ||
8205e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                activity.getSelectedTab() != DeskClock.STOPWATCH_TAB_INDEX) {
821d0a9d2681d5386471f59cbe3a3962657266905caBudi Kusmiantoro            return;
822d0a9d2681d5386471f59cbe3a3962657266905caBudi Kusmiantoro        }
823d50ff479c37e33de776c339bc93df308f4ac7ab0rachelzhang        mRightButton.setImageResource(R.drawable.ic_share);
82489b8693723b706636225d042772c80188f4231cdBudi Kusmiantoro        mRightButton.setContentDescription(getString(R.string.sw_share_button));
8255e469aa155baea98f09d5d5e657aa2315a76679drachelzhang
8265e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        switch (mState) {
8275e469aa155baea98f09d5d5e657aa2315a76679drachelzhang            case Stopwatches.STOPWATCH_RESET:
8285e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setImageResource(R.drawable.ic_lap);
8295e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setContentDescription(getString(R.string.sw_lap_button));
8305e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setEnabled(false);
8315e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setVisibility(View.INVISIBLE);
8325e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mRightButton.setVisibility(View.INVISIBLE);
8335e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                break;
8345e469aa155baea98f09d5d5e657aa2315a76679drachelzhang            case Stopwatches.STOPWATCH_RUNNING:
8355e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setImageResource(R.drawable.ic_lap);
8365e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setContentDescription(getString(R.string.sw_lap_button));
8375e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setEnabled(!reachedMaxLaps());
8385e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setVisibility(View.VISIBLE);
8395e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mRightButton.setVisibility(View.INVISIBLE);
8405e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                break;
8415e469aa155baea98f09d5d5e657aa2315a76679drachelzhang            case Stopwatches.STOPWATCH_STOPPED:
8425e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setImageResource(R.drawable.ic_reset);
8435e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setContentDescription(getString(R.string.sw_reset_button));
8445e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setEnabled(true);
8455e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mLeftButton.setVisibility(View.VISIBLE);
8465e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                mRightButton.setVisibility(View.VISIBLE);
8475e469aa155baea98f09d5d5e657aa2315a76679drachelzhang                break;
8485e469aa155baea98f09d5d5e657aa2315a76679drachelzhang        }
8495520461495a8c4fb468aa94d7b18a3fc25d54739rachelzhang    }
85065d7dfb98ab0102ac899b20fecbc760f2d625608Isaac Katzenelson}
851