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