15fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/*
25fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
35fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
45fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
55fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * you may not use this file except in compliance with the License.
65fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * You may obtain a copy of the License at
75fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
85fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
95fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project *
105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * See the License for the specific language governing permissions and
145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * limitations under the License.
155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
17fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandlerpackage com.android.deskclock;
185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
193bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.animation.Animator;
203bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.animation.Animator.AnimatorListener;
21f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kungimport android.animation.AnimatorInflater;
223bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.animation.ValueAnimator;
235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.Activity;
245c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.app.Fragment;
255c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.app.FragmentTransaction;
265c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.app.LoaderManager;
271c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowskiimport android.content.ContentResolver;
285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context;
295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent;
305c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.content.Loader;
313bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.content.res.Configuration;
32fa850403039aa9869159978bd83877652606e95bIsaac Katzenelsonimport android.content.res.Resources;
335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.database.Cursor;
343bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.database.DataSetObserver;
3596509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelsonimport android.graphics.Rect;
36fa2e368e5f00fc8f78b9a47f55d86ccfc99750d2Chiao Chengimport android.graphics.Typeface;
373286630083faa144af00617718411bf66eb3242bChiao Chengimport android.media.Ringtone;
385c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.media.RingtoneManager;
395c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.net.Uri;
403286630083faa144af00617718411bf66eb3242bChiao Chengimport android.os.AsyncTask;
415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.os.Bundle;
42dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Chengimport android.os.Vibrator;
431c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowskiimport android.text.format.DateFormat;
443bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.view.Gravity;
455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.view.LayoutInflater;
460cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Chengimport android.view.MotionEvent;
475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.view.View;
483bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.view.View.OnClickListener;
492eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.view.ViewGroup;
503bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.view.ViewGroup.LayoutParams;
512eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport android.view.ViewTreeObserver;
523bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.view.animation.DecelerateInterpolator;
533bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.view.animation.Interpolator;
54bcfaaa6b567b95df64499c2a2e3c15780438a2dcPatrick Scottimport android.widget.CheckBox;
55aba3c451dccd54617947628045367c65febdee6bChiao Chengimport android.widget.CompoundButton;
565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.widget.CursorAdapter;
573bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.widget.FrameLayout;
583bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.widget.ImageButton;
593bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinimport android.widget.ImageView;
605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.widget.LinearLayout;
6196509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelsonimport android.widget.ListView;
62aba3c451dccd54617947628045367c65febdee6bChiao Chengimport android.widget.Switch;
635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.widget.TextView;
641c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowskiimport android.widget.Toast;
655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.widget.ToggleButton;
665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
675f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzsteinimport com.android.datetimepicker.time.RadialPickerLayout;
685f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzsteinimport com.android.datetimepicker.time.TimePickerDialog;
691c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowskiimport com.android.deskclock.alarms.AlarmStateManager;
708c1fcf3490a0d92448c460193c8824dbcd6790fdPaul Sliwowskiimport com.android.deskclock.provider.Alarm;
711c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowskiimport com.android.deskclock.provider.AlarmInstance;
722eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowskiimport com.android.deskclock.provider.DaysOfWeek;
730cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Chengimport com.android.deskclock.widget.ActionableToastBar;
748ecc6f2c6e1697940bf611d5e3e830dd9c590643Alon Albertimport com.android.deskclock.widget.TextTime;
752eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski
765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport java.text.DateFormatSymbols;
77bcfaaa6b567b95df64499c2a2e3c15780438a2dcPatrick Scottimport java.util.Calendar;
785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport java.util.HashSet;
79f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kungimport java.util.concurrent.ConcurrentHashMap;
805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/**
825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * AlarmClock application.
835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzsteinpublic class AlarmClockFragment extends DeskClockFragment implements
853bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        LoaderManager.LoaderCallbacks<Cursor>,
865f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein        TimePickerDialog.OnTimeSetListener,
87f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        View.OnTouchListener
88f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        {
89f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private static final float EXPAND_DECELERATION = 1f;
90f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private static final float COLLAPSE_DECELERATION = 0.7f;
91f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private static final int ANIMATION_DURATION = 300;
925c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private static final String KEY_EXPANDED_IDS = "expandedIds";
935c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private static final String KEY_REPEAT_CHECKED_IDS = "repeatCheckedIds";
943286630083faa144af00617718411bf66eb3242bChiao Cheng    private static final String KEY_RINGTONE_TITLE_CACHE = "ringtoneTitleCache";
95fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson    private static final String KEY_SELECTED_ALARMS = "selectedAlarms";
960cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    private static final String KEY_DELETED_ALARM = "deletedAlarm";
970cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    private static final String KEY_UNDO_SHOWING = "undoShowing";
98ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng    private static final String KEY_PREVIOUS_DAY_MAP = "previousDayMap";
99687d3b672f3a86c108ecb121985d018d8c2481aeChiao Cheng    private static final String KEY_SELECTED_ALARM = "selectedAlarm";
100872c29e9aeb5ff1aa71f28b533573b7a53210a67Isaac Katzenelson    private static final String KEY_DELETE_CONFIRMATION = "deleteConfirmation";
1014e1b06ebcf08dd57240a56bac6f923b2e72ea793Patrick Scott
1025c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private static final int REQUEST_CODE_RINGTONE = 1;
1034e1b06ebcf08dd57240a56bac6f923b2e72ea793Patrick Scott
1041c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    // This extra is used when receiving an intent to create an alarm, but no alarm details
1051c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    // have been passed in, so the alarm page should start the process of creating a new alarm.
1061c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    public static final String ALARM_CREATE_NEW_INTENT_EXTRA = "deskclock.create.new";
1071c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
10873ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski    // This extra is used when receiving an intent to scroll to specific alarm. If alarm
10973ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski    // can not be found, and toast message will pop up that the alarm has be deleted.
11073ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski    public static final String SCROLL_TO_ALARM_INTENT_EXTRA = "deskclock.scroll.to.alarm";
11173ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski
1123bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    private ListView mAlarmsList;
1135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private AlarmItemAdapter mAdapter;
1143bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    private View mEmptyView;
1153bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    private ImageView mAddAlarmButton;
116f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private View mAlarmsView;
117f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private View mTimelineLayout;
118f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private AlarmTimelineView mTimelineView;
119f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private View mFooterView;
120f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1213286630083faa144af00617718411bf66eb3242bChiao Cheng    private Bundle mRingtoneTitleCache; // Key: ringtone uri, value: ringtone title
1220cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    private ActionableToastBar mUndoBar;
123f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private View mUndoFrame;
124185d17974729a98cf48a71ab9f16adaab9d1e1e0The Android Open Source Project
1255c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private Alarm mSelectedAlarm;
1262eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private long mScrollToAlarmId = -1;
1275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
12873ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski    private Loader mCursorLoader = null;
12951193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng
1300cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    // Saved states for undo
1310cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    private Alarm mDeletedAlarm;
132f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private Alarm mAddedAlarm;
1330cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    private boolean mUndoShowing = false;
1340cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng
135f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private Animator mFadeIn;
136f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private Animator mFadeOut;
137f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
138f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private Interpolator mExpandInterpolator;
139f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private Interpolator mCollapseInterpolator;
140f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
141f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private int mTimelineViewWidth;
142f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private int mUndoBarInitialMargin;
143f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
144f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    // Cached layout positions of items in listview prior to add/removal of alarm item
145f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private ConcurrentHashMap<Long, Integer> mItemIdTopMap = new ConcurrentHashMap<Long, Integer>();
146f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1473bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public AlarmClockFragment() {
1483bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        // Basic provider required by Fragment.java
1493bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    }
1503bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
1515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    @Override
1523bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void onCreate(Bundle savedState) {
1535c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        super.onCreate(savedState);
15473ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        mCursorLoader = getLoaderManager().initLoader(0, null, this);
1555c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
1560dffdefe54299ee01b45574244c92d3a06507b87Patrick Scott
1573bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    @Override
1583bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public View onCreateView(LayoutInflater inflater, ViewGroup container,
1593bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            Bundle savedState) {
1603bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        // Inflate the layout for this fragment
161f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        final View v = inflater.inflate(R.layout.alarm_clock, container, false);
1623bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
1632eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        long[] expandedIds = null;
1642eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        long[] repeatCheckedIds = null;
1652eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        long[] selectedAlarms = null;
166ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        Bundle previousDayMap = null;
1675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        if (savedState != null) {
1682eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            expandedIds = savedState.getLongArray(KEY_EXPANDED_IDS);
1692eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            repeatCheckedIds = savedState.getLongArray(KEY_REPEAT_CHECKED_IDS);
1703286630083faa144af00617718411bf66eb3242bChiao Cheng            mRingtoneTitleCache = savedState.getBundle(KEY_RINGTONE_TITLE_CACHE);
1710cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng            mDeletedAlarm = savedState.getParcelable(KEY_DELETED_ALARM);
1720cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng            mUndoShowing = savedState.getBoolean(KEY_UNDO_SHOWING);
1732eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            selectedAlarms = savedState.getLongArray(KEY_SELECTED_ALARMS);
174ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            previousDayMap = savedState.getBundle(KEY_PREVIOUS_DAY_MAP);
175687d3b672f3a86c108ecb121985d018d8c2481aeChiao Cheng            mSelectedAlarm = savedState.getParcelable(KEY_SELECTED_ALARM);
1765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
1773286630083faa144af00617718411bf66eb3242bChiao Cheng
178f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mExpandInterpolator = new DecelerateInterpolator(EXPAND_DECELERATION);
179f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mCollapseInterpolator = new DecelerateInterpolator(COLLAPSE_DECELERATION);
180f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1813bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mAddAlarmButton = (ImageButton) v.findViewById(R.id.alarm_add_alarm);
1823bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mAddAlarmButton.setOnClickListener(new OnClickListener() {
1833bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            @Override
1843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            public void onClick(View v) {
185f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                hideUndoBar(true, null);
186f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein                startCreatingAlarm();
1873bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            }
1883bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        });
1893bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        // For landscape, put the add button on the right and the menu in the actionbar.
1903bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        FrameLayout.LayoutParams layoutParams =
1913bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                (FrameLayout.LayoutParams) mAddAlarmButton.getLayoutParams();
192d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette        boolean isLandscape = getResources().getConfiguration().orientation
193d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette                == Configuration.ORIENTATION_LANDSCAPE;
194d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette        if (isLandscape) {
1953bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            layoutParams.gravity = Gravity.END;
1963bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        } else {
1973bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            layoutParams.gravity = Gravity.CENTER;
1983bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        }
1993bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mAddAlarmButton.setLayoutParams(layoutParams);
2003bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
201d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette        View menuButton = v.findViewById(R.id.menu_button);
202d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette        if (menuButton != null) {
203d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette            if (isLandscape) {
204d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette                menuButton.setVisibility(View.GONE);
205d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette            } else {
206d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette                menuButton.setVisibility(View.VISIBLE);
207d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette                setupFakeOverflowMenuButton(menuButton);
208d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette            }
209d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette        }
210d968d6707f61078c3afacffa08c499ee9ed472a5Alan Viverette
2113bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mEmptyView = v.findViewById(R.id.alarms_empty_view);
2127e52e4a333f6a148532e5d3395412676c0673764Sam Blitzstein        mEmptyView.setOnClickListener(new OnClickListener() {
2137e52e4a333f6a148532e5d3395412676c0673764Sam Blitzstein            @Override
2147e52e4a333f6a148532e5d3395412676c0673764Sam Blitzstein            public void onClick(View v) {
2157e52e4a333f6a148532e5d3395412676c0673764Sam Blitzstein                startCreatingAlarm();
2167e52e4a333f6a148532e5d3395412676c0673764Sam Blitzstein            }
2177e52e4a333f6a148532e5d3395412676c0673764Sam Blitzstein        });
2183bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mAlarmsList = (ListView) v.findViewById(R.id.alarms_list);
219f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
220f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeIn = AnimatorInflater.loadAnimator(getActivity(), R.anim.fade_in);
221f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeIn.setDuration(ANIMATION_DURATION);
222f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeIn.addListener(new AnimatorListener() {
223f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
224f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
225f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationStart(Animator animation) {
226f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mEmptyView.setVisibility(View.VISIBLE);
227f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
228f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
229f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
230f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationCancel(Animator animation) {
231f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Do nothing.
232f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
233f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
234f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
235f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationEnd(Animator animation) {
236f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Do nothing.
237f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
238f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
239f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
240f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationRepeat(Animator animation) {
241f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Do nothing.
242f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
243f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        });
244f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeIn.setTarget(mEmptyView);
245f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeOut = AnimatorInflater.loadAnimator(getActivity(), R.anim.fade_out);
246f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeOut.setDuration(ANIMATION_DURATION);
247f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeOut.addListener(new AnimatorListener() {
248f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
249f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
250f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationStart(Animator arg0) {
251f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mEmptyView.setVisibility(View.VISIBLE);
252f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
253f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
254f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
255f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationCancel(Animator arg0) {
256f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Do nothing.
257f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
258f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
259f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
260f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationEnd(Animator arg0) {
261f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mEmptyView.setVisibility(View.GONE);
262f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
263f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
264f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
265f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onAnimationRepeat(Animator arg0) {
266f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Do nothing.
267f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
268f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        });
269f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFadeOut.setTarget(mEmptyView);
270f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mAlarmsView = v.findViewById(R.id.alarm_layout);
271f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mTimelineLayout = v.findViewById(R.id.timeline_layout);
272f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
273f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoBar = (ActionableToastBar) v.findViewById(R.id.undo_bar);
274f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoBarInitialMargin = getActivity().getResources()
275f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                .getDimensionPixelOffset(R.dimen.alarm_undo_bar_horizontal_margin);
276f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoFrame = v.findViewById(R.id.undo_frame);
277f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoFrame.setOnTouchListener(this);
278f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
279f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFooterView = v.findViewById(R.id.alarms_footer_view);
280f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mFooterView.setOnTouchListener(this);
281f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
282f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        // Timeline layout only exists in tablet landscape mode for now.
283f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        if (mTimelineLayout != null) {
284f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            mTimelineView = (AlarmTimelineView) v.findViewById(R.id.alarm_timeline_view);
285f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            mTimelineViewWidth = getActivity().getResources()
286f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    .getDimensionPixelOffset(R.dimen.alarm_timeline_layout_width);
287f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        }
288f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
2893bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mAdapter = new AlarmItemAdapter(getActivity(),
2903bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                expandedIds, repeatCheckedIds, selectedAlarms, previousDayMap, mAlarmsList);
2913bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        mAdapter.registerDataSetObserver(new DataSetObserver() {
292f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
293f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            private int prevAdapterCount = -1;
294f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
2953bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            @Override
2963bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            public void onChanged() {
297f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
298f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                final int count = mAdapter.getCount();
299f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                if (mDeletedAlarm != null && prevAdapterCount > count) {
300f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    showUndoBar();
301f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                }
302f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
303f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // If there are no alarms in the adapter...
304f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                if (count == 0) {
3053bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    mAddAlarmButton.setBackgroundResource(R.drawable.main_button_red);
306f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
307f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // ...and if there exists a timeline view (currently only in tablet landscape)
308f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    if (mTimelineLayout != null && mAlarmsView != null) {
309f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
310f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // ...and if the previous adapter had alarms (indicating a removal)...
311f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        if (prevAdapterCount > 0) {
312f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
313f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // Then animate in the "no alarms" icon...
314f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mFadeIn.start();
315f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
316f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // and animate out the alarm timeline view, expanding the width of the
317f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // alarms list / undo bar.
318f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mTimelineLayout.setVisibility(View.VISIBLE);
319f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            ValueAnimator animator = ValueAnimator.ofFloat(1f, 0f)
320f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    .setDuration(ANIMATION_DURATION);
321f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.setInterpolator(mCollapseInterpolator);
322f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
323f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                @Override
324f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                public void onAnimationUpdate(ValueAnimator animator) {
325f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    Float value = (Float) animator.getAnimatedValue();
326f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    int currentTimelineWidth = (int) (value * mTimelineViewWidth);
327f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    float rightOffset = mTimelineViewWidth * (1 - value);
328f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineLayout.setTranslationX(rightOffset);
329f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineLayout.setAlpha(value);
330f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineLayout.requestLayout();
331f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    setUndoBarRightMargin(currentTimelineWidth
332f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                            + mUndoBarInitialMargin);
333f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                }
334f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            });
335f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.addListener(new AnimatorListener() {
336f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
337f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                @Override
338f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                public void onAnimationCancel(Animator animation) {
339f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    // Do nothing.
340f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                }
341f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
342f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                @Override
343f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                public void onAnimationEnd(Animator animation) {
344f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineView.setIsAnimatingOut(false);
345f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                }
346f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
347f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                @Override
348f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                public void onAnimationRepeat(Animator animation) {
349f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    // Do nothing.
350f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                }
351f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
352f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                @Override
353f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                public void onAnimationStart(Animator animation) {
354f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineView.setIsAnimatingOut(true);
355f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                }
356f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
357f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            });
358f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.start();
359f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        } else {
360f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // If the previous adapter did not have alarms, no animation needed,
361f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // just hide the timeline view and show the "no alarms" icon.
362f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mTimelineLayout.setVisibility(View.GONE);
363f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mEmptyView.setVisibility(View.VISIBLE);
364f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            setUndoBarRightMargin(mUndoBarInitialMargin);
365f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
366f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    } else {
367f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
368f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // If there is no timeline view, just show the "no alarms" icon.
369f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        mEmptyView.setVisibility(View.VISIBLE);
370f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    }
3713bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                } else {
372f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
373f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // Otherwise, if the adapter DOES contain alarms...
3743bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    mAddAlarmButton.setBackgroundResource(R.drawable.main_button_normal);
375f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
376f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // ...and if there exists a timeline view (currently in tablet landscape mode)
377f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    if (mTimelineLayout != null && mAlarmsView != null) {
378f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
379f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        mTimelineLayout.setVisibility(View.VISIBLE);
380f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // ...and if the previous adapter did not have alarms (indicating an add)
381f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        if (prevAdapterCount == 0) {
382f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
383f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // Then, animate to hide the "no alarms" icon...
384f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mFadeOut.start();
385f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
386f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // and animate to show the timeline view, reducing the width of the
387f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // alarms list / undo bar.
388f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f)
389f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    .setDuration(ANIMATION_DURATION);
390f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.setInterpolator(mExpandInterpolator);
391f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
392f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                @Override
393f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                public void onAnimationUpdate(ValueAnimator animator) {
394f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    Float value = (Float) animator.getAnimatedValue();
395f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    int currentTimelineWidth = (int) (value * mTimelineViewWidth);
396f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    float rightOffset = mTimelineViewWidth * (1 - value);
397f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineLayout.setTranslationX(rightOffset);
398f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineLayout.setAlpha(value);
399f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mTimelineLayout.requestLayout();
400f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    ((FrameLayout.LayoutParams) mAlarmsView.getLayoutParams())
401f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        .setMargins(0, 0, (int) -rightOffset, 0);
402f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    mAlarmsView.requestLayout();
403f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    setUndoBarRightMargin(currentTimelineWidth
404f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                            + mUndoBarInitialMargin);
405f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                }
406f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            });
407f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            animator.start();
408f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        } else {
409f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mTimelineLayout.setVisibility(View.VISIBLE);
410f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mEmptyView.setVisibility(View.GONE);
411f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            setUndoBarRightMargin(mUndoBarInitialMargin + mTimelineViewWidth);
412f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
413f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    } else {
414f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
415f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // If there is no timeline view, just hide the "no alarms" icon.
416f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        mEmptyView.setVisibility(View.GONE);
417f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    }
4183bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                }
419f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
420f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Cache this adapter's count for when the adapter changes.
421f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                prevAdapterCount = count;
4223bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                super.onChanged();
4233bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            }
4243bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        });
4250dffdefe54299ee01b45574244c92d3a06507b87Patrick Scott
4263286630083faa144af00617718411bf66eb3242bChiao Cheng        if (mRingtoneTitleCache == null) {
4273286630083faa144af00617718411bf66eb3242bChiao Cheng            mRingtoneTitleCache = new Bundle();
4283286630083faa144af00617718411bf66eb3242bChiao Cheng        }
4293286630083faa144af00617718411bf66eb3242bChiao Cheng
4305c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mAlarmsList.setAdapter(mAdapter);
4315c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mAlarmsList.setVerticalScrollBarEnabled(true);
4325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mAlarmsList.setOnCreateContextMenuListener(this);
4330cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng
4340cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        if (mUndoShowing) {
435f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            showUndoBar();
4360cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        }
4373bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        return v;
4383bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    }
439fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
440f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private void setUndoBarRightMargin(int margin) {
441f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        FrameLayout.LayoutParams params =
442f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                (FrameLayout.LayoutParams) mUndoBar.getLayoutParams();
443f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        ((FrameLayout.LayoutParams) mUndoBar.getLayoutParams())
444f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            .setMargins(params.leftMargin, params.topMargin, margin, params.bottomMargin);
445f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoBar.requestLayout();
446f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    }
447f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
4483bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    @Override
4493bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void onResume() {
4503bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        super.onResume();
4513bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        // Check if another app asked us to create a blank new alarm.
4523bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        final Intent intent = getActivity().getIntent();
45373ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        if (intent.hasExtra(ALARM_CREATE_NEW_INTENT_EXTRA)) {
45473ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            if (intent.getBooleanExtra(ALARM_CREATE_NEW_INTENT_EXTRA, false)) {
45573ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                // An external app asked us to create a blank alarm.
45673ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                startCreatingAlarm();
45773ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            }
45873ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski
45973ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            // Remove the CREATE_NEW extra now that we've processed it.
46073ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            intent.removeExtra(ALARM_CREATE_NEW_INTENT_EXTRA);
46173ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        } else if (intent.hasExtra(SCROLL_TO_ALARM_INTENT_EXTRA)) {
46273ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            long alarmId = intent.getLongExtra(SCROLL_TO_ALARM_INTENT_EXTRA, Alarm.INVALID_ID);
46373ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            if (alarmId != Alarm.INVALID_ID) {
46473ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                mScrollToAlarmId = alarmId;
46573ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                if (mCursorLoader != null && mCursorLoader.isStarted()) {
46673ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                    // We need to force a reload here to make sure we have the latest view
46773ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                    // of the data to scroll to.
46873ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                    mCursorLoader.forceLoad();
46973ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                }
47073ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            }
47173ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski
47273ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            // Remove the SCROLL_TO_ALARM extra now that we've processed it.
47373ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            intent.removeExtra(SCROLL_TO_ALARM_INTENT_EXTRA);
474fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        }
4755f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein
476a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein        // Make sure to use the child FragmentManager. We have to use that one for the
477a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein        // case where an intent comes in telling the activity to load the timepicker,
478a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein        // which means we have to use that one everywhere so that the fragment can get
479a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein        // correctly picked up here if it's open.
480a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein        TimePickerDialog tpd = (TimePickerDialog) getChildFragmentManager().
4815f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein                findFragmentByTag(AlarmUtils.FRAG_TAG_TIME_PICKER);
4825f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein        if (tpd != null) {
4835f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein            // The dialog is already open so we need to set the listener again.
4845f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein            tpd.setOnTimeSetListener(this);
4855f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein        }
4865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
4875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
48800c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng    private void hideUndoBar(boolean animate, MotionEvent event) {
48900c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng        if (mUndoBar != null) {
490f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            mUndoFrame.setVisibility(View.GONE);
49100c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            if (event != null && mUndoBar.isEventInToastBar(event)) {
49200c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng                // Avoid touches inside the undo bar.
49300c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng                return;
49400c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            }
49500c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            mUndoBar.hide(animate);
49600c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng        }
49700c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng        mDeletedAlarm = null;
49800c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng        mUndoShowing = false;
49900c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng    }
50000c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng
501f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private void showUndoBar() {
502f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoFrame.setVisibility(View.VISIBLE);
503f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        mUndoBar.show(new ActionableToastBar.ActionClickedListener() {
504f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
505f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public void onActionClicked() {
506f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                asyncAddAlarm(mDeletedAlarm);
507f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mDeletedAlarm = null;
508f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mUndoShowing = false;
509f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
510f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        }, 0, getResources().getString(R.string.alarm_deleted), true, R.string.alarm_undo, true);
511f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    }
512f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
5135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    @Override
5143bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void onSaveInstanceState(Bundle outState) {
5154642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng        super.onSaveInstanceState(outState);
5162eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        outState.putLongArray(KEY_EXPANDED_IDS, mAdapter.getExpandedArray());
5172eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        outState.putLongArray(KEY_REPEAT_CHECKED_IDS, mAdapter.getRepeatArray());
5182eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        outState.putLongArray(KEY_SELECTED_ALARMS, mAdapter.getSelectedAlarmsArray());
5193286630083faa144af00617718411bf66eb3242bChiao Cheng        outState.putBundle(KEY_RINGTONE_TITLE_CACHE, mRingtoneTitleCache);
5200cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        outState.putParcelable(KEY_DELETED_ALARM, mDeletedAlarm);
5210cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        outState.putBoolean(KEY_UNDO_SHOWING, mUndoShowing);
522ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        outState.putBundle(KEY_PREVIOUS_DAY_MAP, mAdapter.getPreviousDaysOfWeekMap());
523687d3b672f3a86c108ecb121985d018d8c2481aeChiao Cheng        outState.putParcelable(KEY_SELECTED_ALARM, mSelectedAlarm);
524cf7307401797b159ca32f85e7cf38d18cececd0dPatrick Scott    }
525cf7307401797b159ca32f85e7cf38d18cececd0dPatrick Scott
5265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    @Override
5273bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void onDestroy() {
5285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        super.onDestroy();
5295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        ToastMaster.cancelToast();
5300dffdefe54299ee01b45574244c92d3a06507b87Patrick Scott    }
5310dffdefe54299ee01b45574244c92d3a06507b87Patrick Scott
532e3f01aff06d4bddb09215ccad3d8502de9164966Patrick Scott    @Override
5333bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void onPause() {
5343bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        super.onPause();
5350cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        // When the user places the app in the background by pressing "home",
5360cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        // dismiss the toast bar. However, since there is no way to determine if
5370cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        // home was pressed, just dismiss any existing toast bar when restarting
5380cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        // the app.
539f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        hideUndoBar(false, null);
5400cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    }
5410cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng
542f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein    // Callback used by TimePickerDialog
5434642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng    @Override
5445f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein    public void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute) {
545f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein        if (mSelectedAlarm == null) {
546f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            // If mSelectedAlarm is null then we're creating a new alarm.
547f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            Alarm a = new Alarm();
54873ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            a.alert = RingtoneManager.getActualDefaultRingtoneUri(getActivity(),
54973ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                    RingtoneManager.TYPE_ALARM);
550f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            if (a.alert == null) {
551f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein                a.alert = Uri.parse("content://settings/system/alarm_alert");
552f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            }
553f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            a.hour = hourOfDay;
554f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            a.minutes = minute;
555f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            a.enabled = true;
556f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            asyncAddAlarm(a);
557f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein        } else {
558f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            mSelectedAlarm.hour = hourOfDay;
559f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            mSelectedAlarm.minutes = minute;
560f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            mSelectedAlarm.enabled = true;
561f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            mScrollToAlarmId = mSelectedAlarm.id;
562f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            asyncUpdateAlarm(mSelectedAlarm, true);
563f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein            mSelectedAlarm = null;
564f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein        }
5655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
5665c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
5675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private void showLabelDialog(final Alarm alarm) {
5684642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng        final FragmentTransaction ft = getFragmentManager().beginTransaction();
5694642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng        final Fragment prev = getFragmentManager().findFragmentByTag("label_dialog");
5705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        if (prev != null) {
5715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            ft.remove(prev);
5725c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
5735c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        ft.addToBackStack(null);
5745c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
5755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        // Create and show the dialog.
5763bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        final LabelDialogFragment newFragment =
5773bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                LabelDialogFragment.newInstance(alarm, alarm.label, getTag());
5785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        newFragment.show(ft, "label_dialog");
5795c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
5805c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
5813bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void setLabel(Alarm alarm, String label) {
5824642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng        alarm.label = label;
58300c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng        asyncUpdateAlarm(alarm, false);
5844642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng    }
5854642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng
58641a754faf657c2ac7e414051d0c711c0ee994457Erik    @Override
5875c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
5882eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        return Alarm.getAlarmsCursorLoader(getActivity());
5895c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
5905c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
5915c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    @Override
5925c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    public void onLoadFinished(Loader<Cursor> cursorLoader, final Cursor data) {
5935c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mAdapter.swapCursor(data);
59473ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        if (mScrollToAlarmId != -1) {
5952c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng            scrollToAlarm(mScrollToAlarmId);
5962c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng            mScrollToAlarmId = -1;
59751193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng        }
5985c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
5995c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
6002c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng    /**
6012c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng     * Scroll to alarm with given alarm id.
6022c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng     *
6032c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng     * @param alarmId The alarm id to scroll to.
6042c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng     */
6052eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski    private void scrollToAlarm(long alarmId) {
60673ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        int alarmPosition = -1;
6072c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng        for (int i = 0; i < mAdapter.getCount(); i++) {
6082c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng            long id = mAdapter.getItemId(i);
6092c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng            if (id == alarmId) {
61073ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                alarmPosition = i;
6112c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng                break;
6122c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng            }
6132c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng        }
61473ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski
61573ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        if (alarmPosition >= 0) {
61673ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            mAdapter.setNewAlarm(alarmId);
61773ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            mAlarmsList.smoothScrollToPositionFromTop(alarmPosition, 0);
61873ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        } else {
61973ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            // Trying to display a deleted alarm should only happen from a missed notification for
62073ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            // an alarm that has been marked deleted after use.
62173ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            Context context = getActivity().getApplicationContext();
62273ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            Toast toast = Toast.makeText(context, R.string.missed_alarm_has_been_deleted,
62373ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski                    Toast.LENGTH_LONG);
62473ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            ToastMaster.setToast(toast);
62573ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski            toast.show();
62673ee47ca9ad037d177e40c5eb20a9d36a732e14ePaul Sliwowski        }
6272c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng    }
6282c24f71c5331b42ac58c69637c04db57d48ec918Chiao Cheng
6295c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    @Override
6305c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    public void onLoaderReset(Loader<Cursor> cursorLoader) {
6315c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mAdapter.swapCursor(null);
6325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
6335c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
6345c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private void launchRingTonePicker(Alarm alarm) {
6355c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mSelectedAlarm = alarm;
636eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski        Uri oldRingtone = Alarm.NO_RINGTONE_URI.equals(alarm.alert) ? null : alarm.alert;
6375c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        final Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
638eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, oldRingtone);
639aa3c30991070ed78289964bba6af72a25341cb39Daniel Sandler        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);
640e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
6415c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        startActivityForResult(intent, REQUEST_CODE_RINGTONE);
6425c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
6435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
6445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    private void saveRingtoneUri(Intent intent) {
645eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski        Uri uri = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
646eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski        if (uri == null) {
647eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski            uri = Alarm.NO_RINGTONE_URI;
648eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski        }
6495c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        mSelectedAlarm.alert = uri;
650eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski
651c81760e098c7ef6370fd9e038c6264b06f17f232Isaac Katzenelson        // Save the last selected ringtone as the default for new alarms
652eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski        if (!Alarm.NO_RINGTONE_URI.equals(uri)) {
6533bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            RingtoneManager.setActualDefaultRingtoneUri(
6543bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    getActivity(), RingtoneManager.TYPE_ALARM, uri);
655b2d117c908066290ea8174bed39c9f101af20999Isaac Katzenelson        }
65600c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng        asyncUpdateAlarm(mSelectedAlarm, false);
6575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
6585c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
6595c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    @Override
6603bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein    public void onActivityResult(int requestCode, int resultCode, Intent data) {
6613bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        if (resultCode == Activity.RESULT_OK) {
6625c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            switch (requestCode) {
6635c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                case REQUEST_CODE_RINGTONE:
6645c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    saveRingtoneUri(data);
6655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    break;
6665c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                default:
6675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    Log.w("Unhandled request code in onActivityResult: " + requestCode);
6685c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
6695c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
6705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    }
6715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
6725c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng    public class AlarmItemAdapter extends CursorAdapter {
6733bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        private static final int EXPAND_DURATION = 300;
6743bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        private static final int COLLAPSE_DURATION = 250;
6755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
676e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final Context mContext;
677e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final LayoutInflater mFactory;
678e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final String[] mShortWeekDayStrings;
679932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting        private final String[] mLongWeekDayStrings;
680e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final int mColorLit;
681e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final int mColorDim;
6823bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        private final int mBackgroundColorExpanded;
683fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        private final int mBackgroundColor;
684e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final Typeface mRobotoNormal;
685e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final Typeface mRobotoBold;
68696509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson        private final ListView mList;
687e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson
6882eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private final HashSet<Long> mExpanded = new HashSet<Long>();
6892eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private final HashSet<Long> mRepeatChecked = new HashSet<Long>();
6902eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private final HashSet<Long> mSelectedAlarms = new HashSet<Long>();
691ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        private Bundle mPreviousDaysOfWeekMap = new Bundle();
6925c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
693e10e1df9d70879d9a44e86da390f5a8f26a36baeIsaac Katzenelson        private final boolean mHasVibrator;
6945d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein        private final int mCollapseExpandHeight;
695dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng
6965c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        // This determines the order in which it is shown and processed in the UI.
6975c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        private final int[] DAY_ORDER = new int[] {
6985c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.SUNDAY,
6995c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.MONDAY,
7005c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.TUESDAY,
7015c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.WEDNESDAY,
7025c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.THURSDAY,
7035c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.FRIDAY,
7045c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                Calendar.SATURDAY,
7055c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        };
7065c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
707fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        public class ItemHolder {
7085c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
7095c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            // views for optimization
710aba3c451dccd54617947628045367c65febdee6bChiao Cheng            LinearLayout alarmItem;
7118ecc6f2c6e1697940bf611d5e3e830dd9c590643Alon Albert            TextTime clock;
712aba3c451dccd54617947628045367c65febdee6bChiao Cheng            Switch onoff;
7135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            TextView daysOfWeek;
7145c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            TextView label;
7153bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            ImageView delete;
7165c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            View expandArea;
7173bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            View summary;
7185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            TextView clickableLabel;
7195c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            CheckBox repeat;
7205c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            LinearLayout repeatDays;
721797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            ViewGroup[] dayButtonParents = new ViewGroup[7];
722797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            ToggleButton[] dayButtons = new ToggleButton[7];
7235c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            CheckBox vibrate;
724aba3c451dccd54617947628045367c65febdee6bChiao Cheng            TextView ringtone;
7259722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson            View hairLine;
7263bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            View arrow;
7273bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            View collapseExpandArea;
728f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            View footerFiller;
7295c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
7305c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            // Other states
7315c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            Alarm alarm;
7325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
7335c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
73496509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson        // Used for scrolling an expanded item in the list to make sure it is fully visible.
7352eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private long mScrollAlarmId = -1;
73696509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson        private final Runnable mScrollRunnable = new Runnable() {
73796509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            @Override
73896509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            public void run() {
73996509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson                if (mScrollAlarmId != -1) {
74096509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson                    View v = getViewById(mScrollAlarmId);
7419dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                    if (v != null) {
7429dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                        Rect rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
7439dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                        mList.requestChildRectangleOnScreen(v, rect, false);
7449dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                    }
74596509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson                    mScrollAlarmId = -1;
74696509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson                }
74796509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            }
74896509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson        };
74996509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson
7502eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        public AlarmItemAdapter(Context context, long[] expandedIds, long[] repeatCheckedIds,
7512eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                long[] selectedAlarms, Bundle previousDaysOfWeekMap, ListView list) {
7525c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            super(context, null, 0);
7535c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            mContext = context;
7545c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            mFactory = LayoutInflater.from(context);
75596509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            mList = list;
7565c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
7575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            DateFormatSymbols dfs = new DateFormatSymbols();
7585c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            mShortWeekDayStrings = dfs.getShortWeekdays();
759932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting            mLongWeekDayStrings = dfs.getWeekdays();
7605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
761fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            Resources res = mContext.getResources();
762fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            mColorLit = res.getColor(R.color.clock_white);
763fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            mColorDim = res.getColor(R.color.clock_gray);
7643bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            mBackgroundColorExpanded = res.getColor(R.color.alarm_whiteish);
7653bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            mBackgroundColor = R.drawable.alarm_background_normal;
766fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
767ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            mRobotoBold = Typeface.create("sans-serif-condensed", Typeface.BOLD);
768ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            mRobotoNormal = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
769ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
7705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (expandedIds != null) {
7715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                buildHashSetFromArray(expandedIds, mExpanded);
7725c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
7735c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (repeatCheckedIds != null) {
7745c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                buildHashSetFromArray(repeatCheckedIds, mRepeatChecked);
7755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
776ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            if (previousDaysOfWeekMap != null) {
777ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                mPreviousDaysOfWeekMap = previousDaysOfWeekMap;
778ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            }
779fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            if (selectedAlarms != null) {
780fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                buildHashSetFromArray(selectedAlarms, mSelectedAlarms);
781fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            }
782dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng
783dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng            mHasVibrator = ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE))
784dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                    .hasVibrator();
7855d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein
7865d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein            mCollapseExpandHeight = (int) res.getDimension(R.dimen.collapse_expand_height);
7875c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
7885c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
789fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        public void removeSelectedId(int id) {
790fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            mSelectedAlarms.remove(id);
791fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        }
792fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
7935c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        @Override
7945c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        public View getView(int position, View convertView, ViewGroup parent) {
7955c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (!getCursor().moveToPosition(position)) {
7963fd300659aeebffa2ed96f089eeee188cd53efb5Isaac Katzenelson                // May happen if the last alarm was deleted and the cursor refreshed while the
7973fd300659aeebffa2ed96f089eeee188cd53efb5Isaac Katzenelson                // list is updated.
7983fd300659aeebffa2ed96f089eeee188cd53efb5Isaac Katzenelson                Log.v("couldn't move cursor to position " + position);
7993fd300659aeebffa2ed96f089eeee188cd53efb5Isaac Katzenelson                return null;
8005c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
8015c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            View v;
8025c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (convertView == null) {
8035c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                v = newView(mContext, getCursor(), parent);
8045c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
8059a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein                // TODO temporary hack to prevent the convertView from not having stuff we need.
8069a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein                boolean badConvertView = convertView.findViewById(R.id.digital_clock) == null;
8075c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                // Do a translation check to test for animation. Change this to something more
8085c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                // reliable and robust in the future.
8099a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein                if (convertView.getTranslationX() != 0 || convertView.getTranslationY() != 0 ||
8109a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein                        badConvertView) {
8115c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    // view was animated, reset
8125c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    v = newView(mContext, getCursor(), parent);
8135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                } else {
8145c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    v = convertView;
8155c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                }
8165c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
8175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            bindView(v, mContext, getCursor());
818f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            ItemHolder holder = (ItemHolder) v.getTag();
819f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
820f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            // We need the footer for the last element of the array to allow the user to scroll
821f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            // the item beyond the bottom button bar, which obscures the view.
822f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            holder.footerFiller.setVisibility(position < getCount() - 1 ? View.GONE : View.VISIBLE);
8235c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            return v;
8245c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
8255c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
8265c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        @Override
8275c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        public View newView(Context context, Cursor cursor, ViewGroup parent) {
8285c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            final View view = mFactory.inflate(R.layout.alarm_time, parent, false);
8299a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein            setNewHolder(view);
8309a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein            return view;
8319a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein        }
8325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
833f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        /**
834f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung         * In addition to changing the data set for the alarm list, swapCursor is now also
835f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung         * responsible for preparing the list view's pre-draw operation for any animations that
836f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung         * need to occur if an alarm was removed or added.
837f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung         */
838f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        @Override
839f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        public synchronized Cursor swapCursor(Cursor cursor) {
840f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            Cursor c = super.swapCursor(cursor);
841f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
842f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            if (mItemIdTopMap.isEmpty() && mAddedAlarm == null) {
843f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                return c;
844f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
845f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
846f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            final ListView list = mAlarmsList;
847f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            final ViewTreeObserver observer = list.getViewTreeObserver();
848f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
849f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            /*
850f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * Add a pre-draw listener to the observer to prepare for any possible animations to
851f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * the alarms within the list view.  The animations will occur if an alarm has been
852f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * removed or added.
853f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             *
854f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * For alarm removal, the remaining children should all retain their initial starting
855f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * positions, and transition to their new positions.
856f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             *
857f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * For alarm addition, the other children should all retain their initial starting
858f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * positions, transition to their new positions, and at the end of that transition, the
859f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             * newly added alarm should appear in the designated space.
860f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung             */
861f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
862f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
863f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                private View mAddedView;
864f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
865f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                @Override
866f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                public boolean onPreDraw() {
867f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // Remove the pre-draw listener, as this only needs to occur once.
868ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                    if (observer.isAlive()) {
869ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                        observer.removeOnPreDrawListener(this);
870ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                    }
871f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    boolean firstAnimation = true;
872f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    int firstVisiblePosition = list.getFirstVisiblePosition();
873f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
874f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // Iterate through the children to prepare the add/remove animation.
875f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    for (int i = 0; i< list.getChildCount(); i++) {
876f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        final View child = list.getChildAt(i);
877f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
878f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        int position = firstVisiblePosition + i;
879f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        long itemId = mAdapter.getItemId(position);
880f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
881f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // If this is the added alarm, set it invisible for now, and animate later.
882f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        if (mAddedAlarm != null && itemId == mAddedAlarm.id) {
883f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mAddedView = child;
884f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mAddedView.setAlpha(0.0f);
885f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            continue;
886f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
887f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
888f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // The cached starting position of the child view.
889f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        Integer startTop = mItemIdTopMap.get(itemId);
890f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // The new starting position of the child view.
891f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        int top = child.getTop();
892f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
893f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // If there is no cached starting position, determine whether the item has
894f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // come from the top of bottom of the list view.
895f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        if (startTop == null) {
896f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            int childHeight = child.getHeight() + list.getDividerHeight();
897f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            startTop = top + (i > 0 ? childHeight : -childHeight);
898f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
899f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
900f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        Log.d("Start Top: " + startTop + ", Top: " + top);
901f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // If the starting position of the child view is different from the
902f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        // current position, animate the child.
903f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        if (startTop != top) {
904f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            int delta = startTop - top;
905f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            child.setTranslationY(delta);
906f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            child.animate().setDuration(ANIMATION_DURATION).translationY(0);
907f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            final View addedView = mAddedView;
908f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            if (firstAnimation) {
909f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
910f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                // If this is the first child being animated, then after the
911f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                // animation is complete, and animate in the added alarm (if one
912f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                // exists).
913f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                child.animate().withEndAction(new Runnable() {
914f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
915f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    @Override
916f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    public void run() {
917f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
918f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
919f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        // If there was an added view, animate it in after
920f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        // the other views have animated.
921f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        if (addedView != null) {
922f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                            addedView.animate().alpha(1.0f)
923f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                .setDuration(ANIMATION_DURATION)
924f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                .withEndAction(new Runnable() {
925f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
926f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                    @Override
927f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                    public void run() {
928f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                        // Re-enable the list after the add
929f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                        // animation is complete.
930f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                        list.setEnabled(true);
931f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                    }
932f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
933f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                                });
934f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        } else {
935f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                            // Re-enable the list after animations are complete.
936f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                            list.setEnabled(true);
937f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        }
938f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    }
939f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
940f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                });
941f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                firstAnimation = false;
942f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            }
943f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
944f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    }
945f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
946f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // If there were no child views (outside of a possible added view)
947f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // that require animation...
948f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    if (firstAnimation) {
949f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        if (mAddedView != null) {
950f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // If there is an added view, prepare animation for the added view.
951f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            Log.d("Animating added view...");
952f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            mAddedView.animate().alpha(1.0f)
953f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                .setDuration(ANIMATION_DURATION)
954f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                .withEndAction(new Runnable() {
955f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    @Override
956f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    public void run() {
957f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        // Re-enable the list after animations are complete.
958f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                        list.setEnabled(true);
959f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                    }
960f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                                });
961f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        } else {
962f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            // Re-enable the list after animations are complete.
963f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            list.setEnabled(true);
964f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
965f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    }
966f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
967f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    mAddedAlarm = null;
968f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    mItemIdTopMap.clear();
969f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    return true;
970f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                }
971f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            });
972f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            return c;
973f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        }
974f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
9759a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein        private void setNewHolder(View view) {
9765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            // standard view holder optimization
9775c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            final ItemHolder holder = new ItemHolder();
978aba3c451dccd54617947628045367c65febdee6bChiao Cheng            holder.alarmItem = (LinearLayout) view.findViewById(R.id.alarm_item);
9798ecc6f2c6e1697940bf611d5e3e830dd9c590643Alon Albert            holder.clock = (TextTime) view.findViewById(R.id.digital_clock);
980aba3c451dccd54617947628045367c65febdee6bChiao Cheng            holder.onoff = (Switch) view.findViewById(R.id.onoff);
981aba3c451dccd54617947628045367c65febdee6bChiao Cheng            holder.onoff.setTypeface(mRobotoNormal);
9825c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.daysOfWeek = (TextView) view.findViewById(R.id.daysOfWeek);
9835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.label = (TextView) view.findViewById(R.id.label);
9843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.delete = (ImageView) view.findViewById(R.id.delete);
9853bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.summary = view.findViewById(R.id.summary);
9865c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.expandArea = view.findViewById(R.id.expand_area);
9873bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.hairLine = view.findViewById(R.id.hairline);
9883bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.arrow = view.findViewById(R.id.arrow);
9895c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.repeat = (CheckBox) view.findViewById(R.id.repeat_onoff);
9905c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.clickableLabel = (TextView) view.findViewById(R.id.edit_label);
9915c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.repeatDays = (LinearLayout) view.findViewById(R.id.repeat_days);
9923bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.collapseExpandArea = view.findViewById(R.id.collapse_expand);
993f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            holder.footerFiller = view.findViewById(R.id.alarm_footer_filler);
994f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            holder.footerFiller.setOnClickListener(new OnClickListener() {
995f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
996f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                @Override
997f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                public void onClick(View v) {
998f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    // Do nothing.
999f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                }
1000f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            });
10015c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
10025c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            // Build button for each day.
10035c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            for (int i = 0; i < 7; i++) {
1004797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                final ViewGroup viewgroup = (ViewGroup) mFactory.inflate(R.layout.day_button,
10055c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        holder.repeatDays, false);
1006797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                final ToggleButton button = (ToggleButton) viewgroup.getChildAt(0);
10075c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                final int dayToShowIndex = DAY_ORDER[i];
10085c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                button.setText(mShortWeekDayStrings[dayToShowIndex]);
10095c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                button.setTextOn(mShortWeekDayStrings[dayToShowIndex]);
10105c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                button.setTextOff(mShortWeekDayStrings[dayToShowIndex]);
1011932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting                button.setContentDescription(mLongWeekDayStrings[dayToShowIndex]);
1012797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                holder.repeatDays.addView(viewgroup);
1013797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                holder.dayButtons[i] = button;
1014797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                holder.dayButtonParents[i] = viewgroup;
10155c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
10165c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            holder.vibrate = (CheckBox) view.findViewById(R.id.vibrate_onoff);
1017aba3c451dccd54617947628045367c65febdee6bChiao Cheng            holder.ringtone = (TextView) view.findViewById(R.id.choose_ringtone);
10185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
10195c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            view.setTag(holder);
10205c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
10215c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
10225c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        @Override
1023f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        public void bindView(final View view, Context context, final Cursor cursor) {
10245c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            final Alarm alarm = new Alarm(cursor);
10259a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein            Object tag = view.getTag();
10269a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein            if (tag == null) {
10279a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein                // The view was converted but somehow lost its tag.
10289a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein                setNewHolder(view);
10293bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            }
10309a5470f5b8578f417c3f2ebf17d77b2683dd4046Sam Blitzstein            final ItemHolder itemHolder = (ItemHolder) tag;
10315c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.alarm = alarm;
10325c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
1033aba3c451dccd54617947628045367c65febdee6bChiao Cheng            // We must unset the listener first because this maybe a recycled view so changing the
1034aba3c451dccd54617947628045367c65febdee6bChiao Cheng            // state would affect the wrong alarm.
1035aba3c451dccd54617947628045367c65febdee6bChiao Cheng            itemHolder.onoff.setOnCheckedChangeListener(null);
10365c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.onoff.setChecked(alarm.enabled);
10373bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
1038fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            if (mSelectedAlarms.contains(itemHolder.alarm.id)) {
10393bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                itemHolder.alarmItem.setBackgroundColor(mBackgroundColorExpanded);
10409722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson                setItemAlpha(itemHolder, true);
10419722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson                itemHolder.onoff.setEnabled(false);
1042fa2e368e5f00fc8f78b9a47f55d86ccfc99750d2Chiao Cheng            } else {
10439722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson                itemHolder.onoff.setEnabled(true);
10443bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                itemHolder.alarmItem.setBackgroundResource(mBackgroundColor);
10459722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson                setItemAlpha(itemHolder, itemHolder.onoff.isChecked());
1046fa2e368e5f00fc8f78b9a47f55d86ccfc99750d2Chiao Cheng            }
10476963d4e54776a1b848fbd7e2c7535e7aef2e3740Isaac Katzenelson            itemHolder.clock.setFormat(
10486963d4e54776a1b848fbd7e2c7535e7aef2e3740Isaac Katzenelson                    (int)mContext.getResources().getDimension(R.dimen.alarm_label_size));
10498ecc6f2c6e1697940bf611d5e3e830dd9c590643Alon Albert            itemHolder.clock.setTime(alarm.hour, alarm.minutes);
10503bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.clock.setClickable(true);
10513bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.clock.setOnClickListener(new View.OnClickListener() {
10523bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                @Override
10533bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                public void onClick(View view) {
10545f69b490d4bf9bd52fac8f1e0eef589c5cbf4a27Sam Blitzstein                    mSelectedAlarm = itemHolder.alarm;
1055a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein                    AlarmUtils.showTimeEditDialog(getChildFragmentManager(),
10561c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                            alarm, AlarmClockFragment.this
10571c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                            , DateFormat.is24HourFormat(getActivity()));
10583bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    expandAlarm(itemHolder, true);
10593bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    itemHolder.alarmItem.post(mScrollRunnable);
10603bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                }
10613bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            });
10623bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
1063aba3c451dccd54617947628045367c65febdee6bChiao Cheng            final CompoundButton.OnCheckedChangeListener onOffListener =
1064aba3c451dccd54617947628045367c65febdee6bChiao Cheng                    new CompoundButton.OnCheckedChangeListener() {
1065aba3c451dccd54617947628045367c65febdee6bChiao Cheng                        @Override
1066aba3c451dccd54617947628045367c65febdee6bChiao Cheng                        public void onCheckedChanged(CompoundButton compoundButton,
1067aba3c451dccd54617947628045367c65febdee6bChiao Cheng                                boolean checked) {
1068aba3c451dccd54617947628045367c65febdee6bChiao Cheng                            if (checked != alarm.enabled) {
10699722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson                                setItemAlpha(itemHolder, checked);
1070aba3c451dccd54617947628045367c65febdee6bChiao Cheng                                alarm.enabled = checked;
1071aba3c451dccd54617947628045367c65febdee6bChiao Cheng                                asyncUpdateAlarm(alarm, alarm.enabled);
1072aba3c451dccd54617947628045367c65febdee6bChiao Cheng                            }
1073aba3c451dccd54617947628045367c65febdee6bChiao Cheng                        }
1074aba3c451dccd54617947628045367c65febdee6bChiao Cheng                    };
1075aba3c451dccd54617947628045367c65febdee6bChiao Cheng
1076aba3c451dccd54617947628045367c65febdee6bChiao Cheng            itemHolder.onoff.setOnCheckedChangeListener(onOffListener);
10775c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
10783bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            boolean expanded = isAlarmExpanded(alarm);
10793bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.expandArea.setVisibility(expanded? View.VISIBLE : View.GONE);
10803bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.summary.setVisibility(expanded? View.GONE : View.VISIBLE);
10815c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
1082d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein            String labelSpace = "";
10835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            // Set the repeat text or leave it blank if it does not repeat.
10843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            final String daysOfWeekStr =
10853bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    alarm.daysOfWeek.toString(AlarmClockFragment.this.getActivity(), false);
10865c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) {
10875c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.daysOfWeek.setText(daysOfWeekStr);
10883bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                itemHolder.daysOfWeek.setContentDescription(alarm.daysOfWeek.toAccessibilityString(
10893bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        AlarmClockFragment.this.getActivity()));
10905c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.daysOfWeek.setVisibility(View.VISIBLE);
1091d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                labelSpace = "  ";
1092e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                itemHolder.daysOfWeek.setOnClickListener(new View.OnClickListener() {
1093e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                    @Override
1094e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                    public void onClick(View view) {
10953bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        expandAlarm(itemHolder, true);
1096e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                        itemHolder.alarmItem.post(mScrollRunnable);
1097e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                    }
1098e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                });
1099fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
11005c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
11015c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.daysOfWeek.setVisibility(View.GONE);
11025c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
11035c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
11045c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (alarm.label != null && alarm.label.length() != 0) {
1105d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                itemHolder.label.setText(alarm.label + labelSpace);
11065c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.label.setVisibility(View.VISIBLE);
1107932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting                itemHolder.label.setContentDescription(
1108932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting                        mContext.getResources().getString(R.string.label_description) + " "
1109932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting                        + alarm.label);
1110e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                itemHolder.label.setOnClickListener(new View.OnClickListener() {
1111e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                    @Override
1112e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                    public void onClick(View view) {
11133bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        expandAlarm(itemHolder, true);
1114e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                        itemHolder.alarmItem.post(mScrollRunnable);
1115e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                    }
1116e85aa29405a8b809f3b83a4fca93d21f2b36f4eaItzhak Katzenelson                });
11175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
11185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.label.setVisibility(View.GONE);
11195c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
11205c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
11213bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.delete.setOnClickListener(new View.OnClickListener() {
11223bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                @Override
11233bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                public void onClick(View v) {
1124f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    mDeletedAlarm = alarm;
1125f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1126f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    view.animate().setDuration(ANIMATION_DURATION).alpha(0).translationY(-1)
1127f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    .withEndAction(new Runnable() {
1128f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1129f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        @Override
1130f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        public void run() {
1131f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                            asyncDeleteAlarm(mDeletedAlarm, view);
1132f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        }
1133f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    });
11343bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                }
11353bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            });
11363bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
11373bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            if (expanded) {
11383bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                expandAlarm(itemHolder, false);
11397f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski            } else {
11407f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                collapseAlarm(itemHolder, false);
11415c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
11423bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
11433bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.alarmItem.setOnClickListener(new View.OnClickListener() {
1144fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                @Override
1145fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                public void onClick(View view) {
11463bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    if (isAlarmExpanded(alarm)) {
11477f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                        collapseAlarm(itemHolder, true);
11483bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    } else {
11493bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        expandAlarm(itemHolder, true);
11503bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    }
1151fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                }
1152fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            });
11535c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
11545c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
11555c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        private void bindExpandArea(final ItemHolder itemHolder, final Alarm alarm) {
11565c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            // Views in here are not bound until the item is expanded.
11575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
11585c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            if (alarm.label != null && alarm.label.length() > 0) {
11595c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.clickableLabel.setText(alarm.label);
11605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.clickableLabel.setTextColor(mColorLit);
11615c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
11625c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.clickableLabel.setText(R.string.label);
11635c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.clickableLabel.setTextColor(mColorDim);
11645c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
11655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.clickableLabel.setOnClickListener(new View.OnClickListener() {
11665c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                @Override
11675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                public void onClick(View view) {
11685c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    showLabelDialog(alarm);
11695c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                }
11705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            });
11715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
117213f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski            if (mRepeatChecked.contains(alarm.id) || itemHolder.alarm.daysOfWeek.isRepeating()) {
11735c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.repeat.setChecked(true);
11745c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.repeatDays.setVisibility(View.VISIBLE);
11755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
11765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.repeat.setChecked(false);
11775c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                itemHolder.repeatDays.setVisibility(View.GONE);
11785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
11795c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.repeat.setOnClickListener(new View.OnClickListener() {
11805c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                @Override
11815c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                public void onClick(View view) {
11825c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    final boolean checked = ((CheckBox) view).isChecked();
11835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    if (checked) {
11845c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        // Show days
11855c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        itemHolder.repeatDays.setVisibility(View.VISIBLE);
11865c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        mRepeatChecked.add(alarm.id);
1187ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
1188ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        // Set all previously set days
1189ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        // or
1190ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        // Set all days if no previous.
119113f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        final int bitSet = mPreviousDaysOfWeekMap.getInt("" + alarm.id);
119213f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        alarm.daysOfWeek.setBitSet(bitSet);
119313f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        if (!alarm.daysOfWeek.isRepeating()) {
119413f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                            alarm.daysOfWeek.setDaysOfWeek(true, DAY_ORDER);
1195ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        }
1196ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        updateDaysOfWeekButtons(itemHolder, alarm.daysOfWeek);
11975c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    } else {
11985c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        itemHolder.repeatDays.setVisibility(View.GONE);
11995c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        mRepeatChecked.remove(alarm.id);
1200d091ee89ab2aa5c47d4b7b05e1f5d7e204b99494Chiao Cheng
1201ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        // Remember the set days in case the user wants it back.
120213f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        final int bitSet = alarm.daysOfWeek.getBitSet();
120313f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        mPreviousDaysOfWeekMap.putInt("" + alarm.id, bitSet);
1204ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
1205d091ee89ab2aa5c47d4b7b05e1f5d7e204b99494Chiao Cheng                        // Remove all repeat days
120613f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        alarm.daysOfWeek.clearAllDays();
12075c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    }
1208ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                    asyncUpdateAlarm(alarm, false);
12095c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                }
12105c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            });
12115c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
1212ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            updateDaysOfWeekButtons(itemHolder, alarm.daysOfWeek);
12135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            for (int i = 0; i < 7; i++) {
12145c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                final int buttonIndex = i;
1215797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng
1216797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                itemHolder.dayButtonParents[i].setOnClickListener(new View.OnClickListener() {
12175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    @Override
12185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    public void onClick(View view) {
1219797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                        itemHolder.dayButtons[buttonIndex].toggle();
1220797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                        final boolean checked = itemHolder.dayButtons[buttonIndex].isChecked();
1221ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                        int day = DAY_ORDER[buttonIndex];
122213f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                        alarm.daysOfWeek.setDaysOfWeek(checked, day);
12235c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        if (checked) {
1224ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                            turnOnDayOfWeek(itemHolder, buttonIndex);
12255c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        } else {
1226ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                            turnOffDayOfWeek(itemHolder, buttonIndex);
1227ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
1228ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                            // See if this was the last day, if so, un-check the repeat box.
122913f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                            if (!alarm.daysOfWeek.isRepeating()) {
1230ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                                itemHolder.repeatDays.setVisibility(View.GONE);
1231ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                                itemHolder.repeat.setTextColor(mColorDim);
1232ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                                mRepeatChecked.remove(alarm.id);
1233ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
123413f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                                // Set history to no days, so it will be everyday when repeat is
123513f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                                // turned back on
123613f2fef1a5f6877ffc1f6a593d0e8f10f535805bPaul Sliwowski                                mPreviousDaysOfWeekMap.putInt("" + alarm.id,
12372eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                                        DaysOfWeek.NO_DAYS_SET);
1238ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                            }
12395c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        }
124000c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng                        asyncUpdateAlarm(alarm, false);
12415c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    }
12425c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                });
12435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
12445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
1245dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng
1246dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng            if (!mHasVibrator) {
1247dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                itemHolder.vibrate.setVisibility(View.INVISIBLE);
12485c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
1249dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                itemHolder.vibrate.setVisibility(View.VISIBLE);
1250dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                if (!alarm.vibrate) {
1251dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                    itemHolder.vibrate.setChecked(false);
1252dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                    itemHolder.vibrate.setTextColor(mColorDim);
1253dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                } else {
1254dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                    itemHolder.vibrate.setChecked(true);
1255dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                    itemHolder.vibrate.setTextColor(mColorLit);
1256dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng                }
12575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
1258dbd989a7aebc7914b2cdec3e0cb69e38fae670fbChiao Cheng
12595c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.vibrate.setOnClickListener(new View.OnClickListener() {
12605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                @Override
12615c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                public void onClick(View v) {
12625c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    final boolean checked = ((CheckBox) v).isChecked();
12635c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    if (checked) {
12645c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        itemHolder.vibrate.setTextColor(mColorLit);
12655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    } else {
12665c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                        itemHolder.vibrate.setTextColor(mColorDim);
12675c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    }
12685c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    alarm.vibrate = checked;
126900c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng                    asyncUpdateAlarm(alarm, false);
12705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                }
12715c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            });
12725c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
12735c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            final String ringtone;
1274eddf7797cab8ca51a45dd66908654267fcf6fe18Paul Sliwowski            if (Alarm.NO_RINGTONE_URI.equals(alarm.alert)) {
12755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                ringtone = mContext.getResources().getString(R.string.silent_alarm_summary);
12765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            } else {
12773286630083faa144af00617718411bf66eb3242bChiao Cheng                ringtone = getRingToneTitle(alarm.alert);
12785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
12795c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.ringtone.setText(ringtone);
1280932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting            itemHolder.ringtone.setContentDescription(
1281932e0129e244e2874dfa3c6be58b2fe9a20cc89dSara Ting                    mContext.getResources().getString(R.string.ringtone_description) + " "
1282797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng                            + ringtone);
12835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            itemHolder.ringtone.setOnClickListener(new View.OnClickListener() {
12845c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                @Override
12855c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                public void onClick(View view) {
12865c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                    launchRingTonePicker(alarm);
12875c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                }
12885c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            });
12895c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
12905c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
12919722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson        // Sets the alpha of the item except the on/off switch. This gives a visual effect
12929722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson        // for enabled/disabled alarm while leaving the on/off switch more visible
12939722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson        private void setItemAlpha(ItemHolder holder, boolean enabled) {
12949722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson            float alpha = enabled ? 1f : 0.5f;
12959722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson            holder.clock.setAlpha(alpha);
12963bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.summary.setAlpha(alpha);
12979722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson            holder.expandArea.setAlpha(alpha);
12983bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            holder.delete.setAlpha(alpha);
12990ab167de98f42460c5c5cff7f8c2d0759f9f684bIsaac Katzenelson            holder.daysOfWeek.setAlpha(alpha);
13009722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson        }
13019722dd0b2b040337ec22f4fa9dfa72a1ea83e42cIsaac Katzenelson
13022eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private void updateDaysOfWeekButtons(ItemHolder holder, DaysOfWeek daysOfWeek) {
1303ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            HashSet<Integer> setDays = daysOfWeek.getSetDays();
1304ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            for (int i = 0; i < 7; i++) {
1305ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                if (setDays.contains(DAY_ORDER[i])) {
1306ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                    turnOnDayOfWeek(holder, i);
1307ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                } else {
1308ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                    turnOffDayOfWeek(holder, i);
1309ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng                }
1310ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            }
1311ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        }
1312ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
1313fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        public void toggleSelectState(View v) {
1314fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            // long press could be on the parent view or one of its childs, so find the parent view
1315fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            v = getTopParent(v);
1316fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            if (v != null) {
13172eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski                long id = ((ItemHolder)v.getTag()).alarm.id;
1318fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                if (mSelectedAlarms.contains(id)) {
1319fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                    mSelectedAlarms.remove(id);
1320fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                } else {
1321fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                    mSelectedAlarms.add(id);
1322fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                }
1323fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            }
1324fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        }
1325fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
1326fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        private View getTopParent(View v) {
1327fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            while (v != null && v.getId() != R.id.alarm_item) {
1328fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                v = (View) v.getParent();
1329fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            }
1330fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            return v;
1331fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        }
1332fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
1333fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        public int getSelectedItemsNum() {
1334fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            return mSelectedAlarms.size();
1335fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        }
1336fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
1337ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        private void turnOffDayOfWeek(ItemHolder holder, int dayIndex) {
1338797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            holder.dayButtons[dayIndex].setChecked(false);
1339797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            holder.dayButtons[dayIndex].setTextColor(mColorDim);
1340797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            holder.dayButtons[dayIndex].setTypeface(mRobotoNormal);
1341ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        }
1342ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
1343ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        private void turnOnDayOfWeek(ItemHolder holder, int dayIndex) {
1344797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            holder.dayButtons[dayIndex].setChecked(true);
1345797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            holder.dayButtons[dayIndex].setTextColor(mColorLit);
1346797e22b7224d20f4ce7303f59dc02989bdf83a24Chiao Cheng            holder.dayButtons[dayIndex].setTypeface(mRobotoBold);
1347ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        }
1348ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
1349ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
13505c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        /**
13513286630083faa144af00617718411bf66eb3242bChiao Cheng         * Does a read-through cache for ringtone titles.
13523286630083faa144af00617718411bf66eb3242bChiao Cheng         *
13533286630083faa144af00617718411bf66eb3242bChiao Cheng         * @param uri The uri of the ringtone.
13543286630083faa144af00617718411bf66eb3242bChiao Cheng         * @return The ringtone title. {@literal null} if no matching ringtone found.
13553286630083faa144af00617718411bf66eb3242bChiao Cheng         */
13563286630083faa144af00617718411bf66eb3242bChiao Cheng        private String getRingToneTitle(Uri uri) {
13573286630083faa144af00617718411bf66eb3242bChiao Cheng            // Try the cache first
13583286630083faa144af00617718411bf66eb3242bChiao Cheng            String title = mRingtoneTitleCache.getString(uri.toString());
13593286630083faa144af00617718411bf66eb3242bChiao Cheng            if (title == null) {
13603286630083faa144af00617718411bf66eb3242bChiao Cheng                // This is slow because a media player is created during Ringtone object creation.
13613286630083faa144af00617718411bf66eb3242bChiao Cheng                Ringtone ringTone = RingtoneManager.getRingtone(mContext, uri);
13623286630083faa144af00617718411bf66eb3242bChiao Cheng                title = ringTone.getTitle(mContext);
13633286630083faa144af00617718411bf66eb3242bChiao Cheng                if (title != null) {
13643286630083faa144af00617718411bf66eb3242bChiao Cheng                    mRingtoneTitleCache.putString(uri.toString(), title);
13653286630083faa144af00617718411bf66eb3242bChiao Cheng                }
13663286630083faa144af00617718411bf66eb3242bChiao Cheng            }
13673286630083faa144af00617718411bf66eb3242bChiao Cheng            return title;
13683286630083faa144af00617718411bf66eb3242bChiao Cheng        }
13693286630083faa144af00617718411bf66eb3242bChiao Cheng
13702eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        public void setNewAlarm(long alarmId) {
137151193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng            mExpanded.add(alarmId);
137251193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng        }
137351193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng
13743286630083faa144af00617718411bf66eb3242bChiao Cheng        /**
13755c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng         * Expands the alarm for editing.
13765c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng         *
13775c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng         * @param itemHolder The item holder instance.
13785c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng         */
13793bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein        private void expandAlarm(final ItemHolder itemHolder, boolean animate) {
138051193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng            mExpanded.add(itemHolder.alarm.id);
138151193c62415add1a5fcf7e4ac92e6ba543c2fb88Chiao Cheng            bindExpandArea(itemHolder, itemHolder.alarm);
138296509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            // Scroll the view to make sure it is fully viewed
138396509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            mScrollAlarmId = itemHolder.alarm.id;
13843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
13853bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Save the starting height so we can animate from this value.
13863bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            final int startingHeight = itemHolder.alarmItem.getHeight();
13873bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
13883bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Set the expand area to visible so we can measure the height to animate to.
13893bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.alarmItem.setBackgroundColor(mBackgroundColorExpanded);
13903bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.expandArea.setVisibility(View.VISIBLE);
13913bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
13923bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            if (!animate) {
13933bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                // Set the "end" layout and don't do the animation.
13943bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                itemHolder.arrow.setRotation(180);
1395d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                // We need to translate the hairline up, so the height of the collapseArea
1396d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                // needs to be measured to know how high to translate it.
1397d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                final ViewTreeObserver observer = mAlarmsList.getViewTreeObserver();
1398d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
1399d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                    @Override
1400d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                    public boolean onPreDraw() {
1401d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                        // We don't want to continue getting called for every listview drawing.
1402ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                        if (observer.isAlive()) {
1403ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                            observer.removeOnPreDrawListener(this);
1404ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                        }
1405d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                        int hairlineHeight = itemHolder.hairLine.getHeight();
1406d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                        int collapseHeight =
1407d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                                itemHolder.collapseExpandArea.getHeight() - hairlineHeight;
1408d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                        itemHolder.hairLine.setTranslationY(-collapseHeight);
1409d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                        return true;
1410d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                    }
1411d01970e2116388aea075eaa9296dd7f90cccb067Sam Blitzstein                });
14123bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                return;
14133bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            }
14143bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14153bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Add an onPreDrawListener, which gets called after measurement but before the draw.
14163bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // This way we can check the height we need to animate to before any drawing.
14173bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Note the series of events:
14183bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * expandArea is set to VISIBLE, which causes a layout pass
14193bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * the view is measured, and our onPreDrawListener is called
14203bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * we set up the animation using the start and end values.
14213bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * the height is set back to the starting point so it can be animated down.
14223bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * request another layout pass.
14233bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * return false so that onDraw() is not called for the single frame before
14243bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //    the animations have started.
14253bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            final ViewTreeObserver observer = mAlarmsList.getViewTreeObserver();
14263bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
14273bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                @Override
14283bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                public boolean onPreDraw() {
14293bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // We don't want to continue getting called for every listview drawing.
1430ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                    if (observer.isAlive()) {
1431ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                        observer.removeOnPreDrawListener(this);
1432ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                    }
14333bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Calculate some values to help with the animation.
14343bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    final int endingHeight = itemHolder.alarmItem.getHeight();
14353bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    final int distance = endingHeight - startingHeight;
14363bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    final int collapseHeight = itemHolder.collapseExpandArea.getHeight();
14373bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    int hairlineHeight = itemHolder.hairLine.getHeight();
14383bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    final int hairlineDistance = collapseHeight - hairlineHeight;
14393bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14403bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Set the height back to the start state of the animation.
14413bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    itemHolder.alarmItem.getLayoutParams().height = startingHeight;
14423bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // To allow the expandArea to glide in with the expansion animation, set a
14433bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // negative top margin, which will animate down to a margin of 0 as the height
14443bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // is increased.
14453bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Note that we need to maintain the bottom margin as a fixed value (instead of
14463bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // just using a listview, to allow for a flatter hierarchy) to fit the bottom
14473bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // bar underneath.
14483bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    FrameLayout.LayoutParams expandParams = (FrameLayout.LayoutParams)
14493bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.expandArea.getLayoutParams();
14503bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    expandParams.setMargins(0, -distance, 0, collapseHeight);
14513bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    itemHolder.alarmItem.requestLayout();
14523bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14533bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Set up the animator to animate the expansion.
14543bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f)
14553bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            .setDuration(EXPAND_DURATION);
14563bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.setInterpolator(mExpandInterpolator);
14573bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
14583bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
14593bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationUpdate(ValueAnimator animator) {
14603bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            Float value = (Float) animator.getAnimatedValue();
14613bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14623bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            // For each value from 0 to 1, animate the various parts of the layout.
14633bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.alarmItem.getLayoutParams().height =
14643bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    (int) (value * distance + startingHeight);
14653bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            FrameLayout.LayoutParams expandParams = (FrameLayout.LayoutParams)
14663bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    itemHolder.expandArea.getLayoutParams();
14673bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            expandParams.setMargins(
14683bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    0, (int) -((1 - value) * distance), 0, collapseHeight);
14693bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.arrow.setRotation(180 * value);
14703bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.hairLine.setTranslationY(-hairlineDistance * value);
14713bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.summary.setAlpha(1 - value);
14723bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14733bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.alarmItem.requestLayout();
14743bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        }
14753bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    });
14763bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Set everything to their final values when the animation's done.
14773bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.addListener(new AnimatorListener() {
14783bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
14793bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationEnd(Animator animation) {
14803bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            // Set it back to wrap content since we'd explicitly set the height.
14813bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.alarmItem.getLayoutParams().height =
14823bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    LayoutParams.WRAP_CONTENT;
14833bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.arrow.setRotation(180);
14843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.hairLine.setTranslationY(-hairlineDistance);
14853bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.summary.setVisibility(View.GONE);
14863bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        }
14873bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14883bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
14893bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationCancel(Animator animation) {
14903bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            // TODO we may have to deal with cancelations of the animation.
14913bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        }
14923bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
14933bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
14943bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationRepeat(Animator animation) { }
14953bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
14963bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationStart(Animator animation) { }
14973bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    });
14983bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.start();
14993bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15003bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Return false so this draw does not occur to prevent the final frame from
15013bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // being drawn for the single frame before the animations start.
15023bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    return false;
15033bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                }
15043bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            });
15055c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
15065c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
15075c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        private boolean isAlarmExpanded(Alarm alarm) {
15085c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            return mExpanded.contains(alarm.id);
15095c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
15105c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
15117f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski        private void collapseAlarm(final ItemHolder itemHolder, boolean animate) {
15123bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            mExpanded.remove(itemHolder.alarm.id);
15133bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15143bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Save the starting height so we can animate from this value.
15153bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            final int startingHeight = itemHolder.alarmItem.getHeight();
15163bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15173bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Set the expand area to gone so we can measure the height to animate to.
15183bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.alarmItem.setBackgroundResource(mBackgroundColor);
15193bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            itemHolder.expandArea.setVisibility(View.GONE);
15203bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15217f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski            if (!animate) {
15227f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                // Set the "end" layout and don't do the animation.
15237f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                itemHolder.arrow.setRotation(0);
15247f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                itemHolder.hairLine.setTranslationY(0);
15257f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                return;
15267f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski            }
15277f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski
15283bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Add an onPreDrawListener, which gets called after measurement but before the draw.
15293bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // This way we can check the height we need to animate to before any drawing.
15303bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            // Note the series of events:
15313bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * expandArea is set to GONE, which causes a layout pass
15323bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * the view is measured, and our onPreDrawListener is called
15333bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * we set up the animation using the start and end values.
15343bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * expandArea is set to VISIBLE again so it can be shown animating.
15353bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * request another layout pass.
15363bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //  * return false so that onDraw() is not called for the single frame before
15373bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            //    the animations have started.
15383bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            final ViewTreeObserver observer = mAlarmsList.getViewTreeObserver();
15393bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
15403bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                @Override
15413bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                public boolean onPreDraw() {
1542ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                    if (observer.isAlive()) {
1543ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                        observer.removeOnPreDrawListener(this);
1544ddfdd96273cb99bbaceaaceb417b7761ee539245Sam Blitzstein                    }
15453bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15463bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Calculate some values to help with the animation.
15473bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    final int endingHeight = itemHolder.alarmItem.getHeight();
15483bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    final int distance = endingHeight - startingHeight;
15493bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    int hairlineHeight = itemHolder.hairLine.getHeight();
15505d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein                    final int hairlineDistance = mCollapseExpandHeight - hairlineHeight;
15513bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15523bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Re-set the visibilities for the start state of the animation.
15533bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    itemHolder.expandArea.setVisibility(View.VISIBLE);
15543bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    itemHolder.summary.setVisibility(View.VISIBLE);
15553bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    itemHolder.summary.setAlpha(1);
15563bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15573bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Set up the animator to animate the expansion.
15583bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f)
15593bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            .setDuration(COLLAPSE_DURATION);
15603bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
15613bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
15623bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationUpdate(ValueAnimator animator) {
15633bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            Float value = (Float) animator.getAnimatedValue();
15643bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15653bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            // For each value from 0 to 1, animate the various parts of the layout.
15663bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.alarmItem.getLayoutParams().height =
15673bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    (int) (value * distance + startingHeight);
15683bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            FrameLayout.LayoutParams expandParams = (FrameLayout.LayoutParams)
15693bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    itemHolder.expandArea.getLayoutParams();
15705d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein                            expandParams.setMargins(
15715d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein                                    0, (int) (value * distance), 0, mCollapseExpandHeight);
15723bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.arrow.setRotation(180 * (1 - value));
15733bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.hairLine.setTranslationY(-hairlineDistance * (1 - value));
15743bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.summary.setAlpha(value);
15753bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15763bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.alarmItem.requestLayout();
15773bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        }
15783bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    });
15793bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.setInterpolator(mCollapseInterpolator);
15803bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    // Set everything to their final values when the animation's done.
15813bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.addListener(new AnimatorListener() {
15823bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
15833bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationEnd(Animator animation) {
15843bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            // Set it back to wrap content since we'd explicitly set the height.
15853bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.alarmItem.getLayoutParams().height =
15863bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    LayoutParams.WRAP_CONTENT;
15873bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15883bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            FrameLayout.LayoutParams expandParams = (FrameLayout.LayoutParams)
15893bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                                    itemHolder.expandArea.getLayoutParams();
15905d2a5d41b53ef31567ea242e6f5464eac88d6a2fSam Blitzstein                            expandParams.setMargins(0, 0, 0, mCollapseExpandHeight);
15913bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15923bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.expandArea.setVisibility(View.GONE);
15933bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.arrow.setRotation(0);
15943bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            itemHolder.hairLine.setTranslationY(0);
15953bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        }
15963bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
15973bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
15983bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationCancel(Animator animation) {
15993bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                            // TODO we may have to deal with cancelations of the animation.
16003bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        }
16013bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
16023bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
16033bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationRepeat(Animator animation) { }
16043bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        @Override
16053bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                        public void onAnimationStart(Animator animation) { }
16063bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    });
16073bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    animator.start();
16083bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein
16093bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                    return false;
16103bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein                }
16113bc02950da8c14ec04199043f41a9ffc13290c8dSam Blitzstein            });
16125c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
16135c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
16145c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        @Override
16155c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        public int getViewTypeCount() {
16165c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            return 1;
16175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
16185c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
16192eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private View getViewById(long id) {
162096509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            for (int i = 0; i < mList.getCount(); i++) {
162196509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson                View v = mList.getChildAt(i);
16229dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                if (v != null) {
16239dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                    ItemHolder h = (ItemHolder)(v.getTag());
16249dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                    if (h != null && h.alarm.id == id) {
16259dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                        return v;
16269dad8db45bb8b5b971a5b34aec96617563d243bcIsaac Katzenelson                    }
162796509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson                }
162896509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            }
162996509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson            return null;
163096509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson        }
163196509e15991b34a54a3321c787b3c5d8edb16431Isaac Katzenelson
16322eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        public long[] getExpandedArray() {
16335c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            int index = 0;
16342eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            long[] ids = new long[mExpanded.size()];
16352eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            for (long id : mExpanded) {
16365c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                ids[index] = id;
16375c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                index++;
16385c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
16395c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            return ids;
16405c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
16415c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
16422eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        public long[] getSelectedAlarmsArray() {
1643fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            int index = 0;
16442eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            long[] ids = new long[mSelectedAlarms.size()];
16452eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            for (long id : mSelectedAlarms) {
1646fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                ids[index] = id;
1647fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson                index++;
1648fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            }
1649fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson            return ids;
1650fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson        }
1651fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
16522eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        public long[] getRepeatArray() {
16535c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            int index = 0;
16542eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            long[] ids = new long[mRepeatChecked.size()];
16552eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            for (long id : mRepeatChecked) {
16565c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                ids[index] = id;
16575c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                index++;
16585c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
16595c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            return ids;
16605c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
16615c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng
1662ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        public Bundle getPreviousDaysOfWeekMap() {
1663ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng            return mPreviousDaysOfWeekMap;
1664ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng        }
1665ffe12a38c31058d9c4b32343ff35122b1b8678fcChiao Cheng
16662eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski        private void buildHashSetFromArray(long[] ids, HashSet<Long> set) {
16672eb3e5467cb76617fd6da3ea4a3f222d537a6bd9Paul Sliwowski            for (long id : ids) {
16685c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                set.add(id);
16695c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            }
16705c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng        }
16710cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    }
16720cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng
1673f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein    private void startCreatingAlarm() {
1674f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein        // Set the "selected" alarm as null, and we'll create the new one when the timepicker
1675f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein        // comes back.
1676f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein        mSelectedAlarm = null;
1677a19314fd8af534821bb7c7edacb44087c1a8b6cdSam Blitzstein        AlarmUtils.showTimeEditDialog(getChildFragmentManager(),
16781c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                null, AlarmClockFragment.this, DateFormat.is24HourFormat(getActivity()));
16791c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    }
16801c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
16811c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski    private static AlarmInstance setupAlarmInstance(Context context, Alarm alarm) {
16821c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        ContentResolver cr = context.getContentResolver();
16831c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        AlarmInstance newInstance = alarm.createInstanceAfter(Calendar.getInstance());
16841c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        newInstance = AlarmInstance.addInstance(cr, newInstance);
16851c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        // Register instance to state manager
16861c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        AlarmStateManager.registerInstance(context, newInstance, true);
16871c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        return newInstance;
16880cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    }
16890cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng
1690f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    private void asyncDeleteAlarm(final Alarm alarm, final View viewToRemove) {
16911c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        final Context context = AlarmClockFragment.this.getActivity().getApplicationContext();
16921c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        final AsyncTask<Void, Void, Void> deleteTask = new AsyncTask<Void, Void, Void>() {
16930cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng            @Override
1694f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public synchronized void onPreExecute() {
1695f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                if (viewToRemove == null) {
1696f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    return;
1697f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                }
1698f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // The alarm list needs to be disabled until the animation finishes to prevent
1699f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // possible concurrency issues.  It becomes re-enabled after the animations have
1700f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // completed.
1701f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mAlarmsList.setEnabled(false);
1702f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1703f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Store all of the current list view item positions in memory for animation.
1704f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                final ListView list = mAlarmsList;
1705f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                int firstVisiblePosition = list.getFirstVisiblePosition();
1706f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                for (int i=0; i<list.getChildCount(); i++) {
1707f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    View child = list.getChildAt(i);
1708f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    if (child != viewToRemove) {
1709f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        int position = firstVisiblePosition + i;
1710f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        long itemId = mAdapter.getItemId(position);
1711f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                        mItemIdTopMap.put(itemId, child.getTop());
1712f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    }
1713f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                }
1714f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
1715f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1716f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
17171c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski            protected Void doInBackground(Void... parameters) {
1718be13177b0b9ad533a63f57fee671e9ee6d19286cIsaac Katzenelson                // Activity may be closed at this point , make sure data is still valid
1719be13177b0b9ad533a63f57fee671e9ee6d19286cIsaac Katzenelson                if (context != null && alarm != null) {
1720be13177b0b9ad533a63f57fee671e9ee6d19286cIsaac Katzenelson                    ContentResolver cr = context.getContentResolver();
1721be13177b0b9ad533a63f57fee671e9ee6d19286cIsaac Katzenelson                    AlarmStateManager.deleteAllInstances(context, alarm.id);
1722be13177b0b9ad533a63f57fee671e9ee6d19286cIsaac Katzenelson                    Alarm.deleteAlarm(cr, alarm.id);
1723be13177b0b9ad533a63f57fee671e9ee6d19286cIsaac Katzenelson                }
17240cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng                return null;
17250cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng            }
17260cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        };
17270cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        mUndoShowing = true;
17281c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        deleteTask.execute();
17290cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng    }
17300cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng
1731f233ae3254a1d83aa67042f4333797e534bbb27cSam Blitzstein    private void asyncAddAlarm(final Alarm alarm) {
17321c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        final Context context = AlarmClockFragment.this.getActivity().getApplicationContext();
17331c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        final AsyncTask<Void, Void, AlarmInstance> updateTask =
17341c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                new AsyncTask<Void, Void, AlarmInstance>() {
1735f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            @Override
1736f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            public synchronized void onPreExecute() {
1737f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                final ListView list = mAlarmsList;
1738f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // The alarm list needs to be disabled until the animation finishes to prevent
1739f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // possible concurrency issues.  It becomes re-enabled after the animations have
1740f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // completed.
1741f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                mAlarmsList.setEnabled(false);
1742f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
1743f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                // Store all of the current list view item positions in memory for animation.
1744f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                int firstVisiblePosition = list.getFirstVisiblePosition();
1745f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                for (int i=0; i<list.getChildCount(); i++) {
1746f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    View child = list.getChildAt(i);
1747f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    int position = firstVisiblePosition + i;
1748f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    long itemId = mAdapter.getItemId(position);
1749f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                    mItemIdTopMap.put(itemId, child.getTop());
1750f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung                }
1751f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung            }
1752f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung
17530cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng            @Override
17541c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski            protected AlarmInstance doInBackground(Void... parameters) {
175587a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                if (context != null && alarm != null) {
175687a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                    ContentResolver cr = context.getContentResolver();
17571c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
175887a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                    // Add alarm to db
175987a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                    Alarm newAlarm = Alarm.addAlarm(cr, alarm);
17607f110327c3e26018c3d0e05fe5994f148279ee09Paul Sliwowski                    mScrollToAlarmId = newAlarm.id;
17611c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
176287a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                    // Create and add instance to db
176387a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                    if (newAlarm.enabled) {
176487a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                        return setupAlarmInstance(context, newAlarm);
176587a61c0b2c05be541b19c10cae0ae6d5f59808a6Isaac Katzenelson                    }
17661c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                }
17670cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng                return null;
17680cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng            }
176900c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng
177000c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            @Override
17711c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski            protected void onPostExecute(AlarmInstance instance) {
1772c677dfde1d276531c10efd8008b342318b04782ePaul Sliwowski                if (instance != null) {
17731c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                    AlarmUtils.popAlarmSetToast(context, instance.getAlarmTime().getTimeInMillis());
177400c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng                }
177500c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            }
17760cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        };
17770cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng        updateTask.execute();
17780dffdefe54299ee01b45574244c92d3a06507b87Patrick Scott    }
17793286630083faa144af00617718411bf66eb3242bChiao Cheng
178000c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng    private void asyncUpdateAlarm(final Alarm alarm, final boolean popToast) {
17811c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        final Context context = AlarmClockFragment.this.getActivity().getApplicationContext();
17821c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        final AsyncTask<Void, Void, AlarmInstance> updateTask =
17831c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                new AsyncTask<Void, Void, AlarmInstance>() {
17843286630083faa144af00617718411bf66eb3242bChiao Cheng            @Override
17851c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski            protected AlarmInstance doInBackground(Void ... parameters) {
17861c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                ContentResolver cr = context.getContentResolver();
17871c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
17881c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                // Dismiss all old instances
17891c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                AlarmStateManager.deleteAllInstances(context, alarm.id);
17901c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
17911c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                // Update alarm
17921c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                Alarm.updateAlarm(cr, alarm);
17931c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                if (alarm.enabled) {
17941c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                    return setupAlarmInstance(context, alarm);
17953286630083faa144af00617718411bf66eb3242bChiao Cheng                }
17961c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski
17973286630083faa144af00617718411bf66eb3242bChiao Cheng                return null;
17983286630083faa144af00617718411bf66eb3242bChiao Cheng            }
179900c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng
180000c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            @Override
18011c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski            protected void onPostExecute(AlarmInstance instance) {
18021c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                if (popToast && instance != null) {
18031c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski                    AlarmUtils.popAlarmSetToast(context, instance.getAlarmTime().getTimeInMillis());
180400c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng                }
180500c0d8672ea4741a23ff875ca1a992b8ad080e78Chiao Cheng            }
18063286630083faa144af00617718411bf66eb3242bChiao Cheng        };
18071c7788b33dd4516dae81e6bcab043addc45fc1a1Paul Sliwowski        updateTask.execute();
1808fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson    }
1809fa850403039aa9869159978bd83877652606e95bIsaac Katzenelson
1810f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    @Override
1811f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    public boolean onTouch(View v, MotionEvent event) {
1812f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        hideUndoBar(true, event);
1813f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung        return false;
1814f7de8003e56d6d6f3dd35f494162c75acc993cd9James Kung    }
18155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project}
1816