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
19748e9ada696912c262a097d4211fde528f1cc0b8Steve Levisimport android.app.ActionBar;
2090c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scottimport android.app.AlertDialog;
215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context;
2290c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scottimport android.content.DialogInterface;
235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent;
245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.os.Bundle;
256064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scottimport android.os.Handler;
26bed2fe9bfd0e952c29b5ff90f70350ef8d0a65e4Patrick Scottimport android.os.Vibrator;
27185d17974729a98cf48a71ab9f16adaab9d1e1e0The Android Open Source Projectimport android.preference.CheckBoxPreference;
285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.preference.Preference;
295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.preference.PreferenceActivity;
305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.preference.PreferenceScreen;
31748e9ada696912c262a097d4211fde528f1cc0b8Steve Levisimport android.view.LayoutInflater;
32748e9ada696912c262a097d4211fde528f1cc0b8Steve Levisimport android.view.Menu;
33748e9ada696912c262a097d4211fde528f1cc0b8Steve Levisimport android.view.MenuItem;
34b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scottimport android.view.View;
35748e9ada696912c262a097d4211fde528f1cc0b8Steve Levisimport android.view.View.OnClickListener;
36b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scottimport android.widget.Button;
379c8f420c5d715d1b3923e7c15a38df0df23f7a39Erikimport android.widget.EditText;
389c8f420c5d715d1b3923e7c15a38df0df23f7a39Erikimport android.widget.ListView;
395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/**
415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Manages each alarm
425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */
43d2ee3ef01076138f0ac7b3e0acc580238ffea160Mindy Pereirapublic class SetAlarm extends PreferenceActivity implements Preference.OnPreferenceChangeListener,
444642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng        AlarmTimePickerDialogFragment.AlarmTimePickerDialogHandler {
45748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis
46c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private static final String KEY_CURRENT_ALARM = "currentAlarm";
47c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private static final String KEY_ORIGINAL_ALARM = "originalAlarm";
48c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private static final String KEY_TIME_PICKER_BUNDLE = "timePickerBundle";
495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
509c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik    private EditText mLabel;
5190c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott    private CheckBoxPreference mEnabledPref;
52c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private Preference mTimePref;
535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private AlarmPreference mAlarmPref;
545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private CheckBoxPreference mVibratePref;
555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    private RepeatPreference mRepeatPref;
565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
577495b0046811971ecb0933888d7eafb4c9668ed2Patrick Scott    private int     mId;
58c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private int     mHour;
59c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private int     mMinute;
606064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott    private Alarm   mOriginalAlarm;
615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    @Override
635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    protected void onCreate(Bundle icicle) {
645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        super.onCreate(icicle);
655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
66fe8dd39ee5e173f15337d09c36aa453a55364e98Patrick Scott        // Override the default content view.
67fe8dd39ee5e173f15337d09c36aa453a55364e98Patrick Scott        setContentView(R.layout.set_alarm);
68fe8dd39ee5e173f15337d09c36aa453a55364e98Patrick Scott
699c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        EditText label = (EditText) getLayoutInflater().inflate(R.layout.alarm_label, null);
709c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        ListView list = (ListView) findViewById(android.R.id.list);
719c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        list.addFooterView(label);
729c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik
739c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        // TODO Stop using preferences for this view. Save on done, not after
749c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        // each change.
755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        addPreferencesFromResource(R.xml.alarm_prefs);
76b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott
77b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott        // Get each preference so we can retrieve the value later.
789c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        mLabel = label;
7990c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott        mEnabledPref = (CheckBoxPreference) findPreference("enabled");
8031e21c3131212079a5735bfce949560b03a09a82Michael Chan        mEnabledPref.setOnPreferenceChangeListener(this);
81c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        mTimePref = findPreference("time");
825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        mAlarmPref = (AlarmPreference) findPreference("alarm");
836064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mAlarmPref.setOnPreferenceChangeListener(this);
845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        mVibratePref = (CheckBoxPreference) findPreference("vibrate");
856064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mVibratePref.setOnPreferenceChangeListener(this);
86bed2fe9bfd0e952c29b5ff90f70350ef8d0a65e4Patrick Scott        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
87bed2fe9bfd0e952c29b5ff90f70350ef8d0a65e4Patrick Scott        if (!v.hasVibrator()) {
88bed2fe9bfd0e952c29b5ff90f70350ef8d0a65e4Patrick Scott            getPreferenceScreen().removePreference(mVibratePref);
89bed2fe9bfd0e952c29b5ff90f70350ef8d0a65e4Patrick Scott        }
905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        mRepeatPref = (RepeatPreference) findPreference("setRepeat");
916064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mRepeatPref.setOnPreferenceChangeListener(this);
925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        Intent i = getIntent();
9477f14bd0ce48db935911da5d0a92b6348e6197fbPatrick Scott        Alarm alarm = i.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA);
955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
9677f14bd0ce48db935911da5d0a92b6348e6197fbPatrick Scott        if (alarm == null) {
9777f14bd0ce48db935911da5d0a92b6348e6197fbPatrick Scott            // No alarm means create a new alarm.
98e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            alarm = new Alarm();
99d56e7ebbe8c65b2150214eb3254d36226c1c42a6Patrick Scott        }
1006064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mOriginalAlarm = alarm;
1016064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott
10277f14bd0ce48db935911da5d0a92b6348e6197fbPatrick Scott        // Populate the prefs with the original alarm data.  updatePrefs also
10377f14bd0ce48db935911da5d0a92b6348e6197fbPatrick Scott        // sets mId so it must be called before checking mId below.
1046064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        updatePrefs(mOriginalAlarm);
1055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
106b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott        // We have to do this to get the save/cancel buttons to highlight on
107b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott        // their own.
108b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott        getListView().setItemsCanFocus(true);
109b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott
110748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        ActionBar actionBar = getActionBar();
111748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        if (actionBar != null) {
112748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            actionBar.setDisplayOptions(
113748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    0, ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
114748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            LayoutInflater inflater = (LayoutInflater) getSystemService
115748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    (Context.LAYOUT_INFLATER_SERVICE);
116748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            View customActionBarView = inflater.inflate(R.layout.set_alarm_action_bar, null);
117748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
118748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME |
119748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    ActionBar.DISPLAY_SHOW_TITLE);
120748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            actionBar.setCustomView(customActionBarView);
121748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            View saveMenuItem = customActionBarView.findViewById(R.id.save_menu_item);
122748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            saveMenuItem.setOnClickListener(new OnClickListener() {
123748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                @Override
124b83db52b375a9a28347cacff3a8e8b1ebabe3b46Patrick Scott                public void onClick(View v) {
125748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    saveAndExit();
12690c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott                }
127c9c1acdc0d4a2e7ec3335b9efa4499c92304091dPatrick Scott            });
128c9c1acdc0d4a2e7ec3335b9efa4499c92304091dPatrick Scott        }
1297b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis
1307b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        // Attach actions to each button.
1317b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        Button b = (Button) findViewById(R.id.alarm_save);
1327b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        if (b != null) {
1337b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            b.setOnClickListener(new View.OnClickListener() {
1347b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                    public void onClick(View v) {
1357b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                        long time = saveAlarm(null);
1367b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                        if(mEnabledPref.isChecked()) {
1375c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng                            AlarmUtils.popAlarmSetToast(SetAlarm.this, time);
1387b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                        }
1397b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                        finish();
1407b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                    }
1417b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            });
1427b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        }
1437b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        b = (Button) findViewById(R.id.alarm_revert);
1447b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        if (b != null) {
1457b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            b.setOnClickListener(new View.OnClickListener() {
1467b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                public void onClick(View v) {
1477b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                    revert();
1487b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                    finish();
1497b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                }
1507b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            });
1517b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        }
1527b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        b = (Button) findViewById(R.id.alarm_delete);
1537b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        if (b != null) {
1547b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            if (mId == -1) {
1557b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                b.setEnabled(false);
1567b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                b.setVisibility(View.GONE);
1577b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            } else {
1587b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                b.setVisibility(View.VISIBLE);
1597b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                b.setOnClickListener(new View.OnClickListener() {
1607b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                    public void onClick(View v) {
1617b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                        deleteAlarm();
1627b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                    }
1637b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis                });
1647b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            }
1657b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        }
1667b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis}
167e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
16831e21c3131212079a5735bfce949560b03a09a82Michael Chan    @Override
169748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    public boolean onOptionsItemSelected(MenuItem item) {
170748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        if (item.getItemId() == R.id.menu_delete) {
171748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            deleteAlarm();
172748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            return true;
173748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        }
174748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        return super.onOptionsItemSelected(item);
175748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    }
176748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis
177748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    @Override
178748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    public boolean onCreateOptionsMenu(Menu menu) {
179748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        getMenuInflater().inflate(R.menu.set_alarm_context, menu);
180748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        return true;
181748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    }
182748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis
183748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    @Override
18431e21c3131212079a5735bfce949560b03a09a82Michael Chan    protected void onSaveInstanceState(Bundle outState) {
18531e21c3131212079a5735bfce949560b03a09a82Michael Chan        super.onSaveInstanceState(outState);
18631e21c3131212079a5735bfce949560b03a09a82Michael Chan        outState.putParcelable(KEY_ORIGINAL_ALARM, mOriginalAlarm);
18731e21c3131212079a5735bfce949560b03a09a82Michael Chan        outState.putParcelable(KEY_CURRENT_ALARM, buildAlarmFromUi());
18831e21c3131212079a5735bfce949560b03a09a82Michael Chan    }
18931e21c3131212079a5735bfce949560b03a09a82Michael Chan
19031e21c3131212079a5735bfce949560b03a09a82Michael Chan    @Override
19131e21c3131212079a5735bfce949560b03a09a82Michael Chan    protected void onRestoreInstanceState(Bundle state) {
19231e21c3131212079a5735bfce949560b03a09a82Michael Chan        super.onRestoreInstanceState(state);
19331e21c3131212079a5735bfce949560b03a09a82Michael Chan
19431e21c3131212079a5735bfce949560b03a09a82Michael Chan        Alarm alarmFromBundle = state.getParcelable(KEY_ORIGINAL_ALARM);
19531e21c3131212079a5735bfce949560b03a09a82Michael Chan        if (alarmFromBundle != null) {
19631e21c3131212079a5735bfce949560b03a09a82Michael Chan            mOriginalAlarm = alarmFromBundle;
19731e21c3131212079a5735bfce949560b03a09a82Michael Chan        }
19831e21c3131212079a5735bfce949560b03a09a82Michael Chan
19931e21c3131212079a5735bfce949560b03a09a82Michael Chan        alarmFromBundle = state.getParcelable(KEY_CURRENT_ALARM);
20031e21c3131212079a5735bfce949560b03a09a82Michael Chan        if (alarmFromBundle != null) {
20131e21c3131212079a5735bfce949560b03a09a82Michael Chan            updatePrefs(alarmFromBundle);
202e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        }
203c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan
204c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        Bundle b = state.getParcelable(KEY_TIME_PICKER_BUNDLE);
205c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        if (b != null) {
206c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan            showTimePicker();
207c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        }
2085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2106064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott    // Used to post runnables asynchronously.
2116064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott    private static final Handler sHandler = new Handler();
2126064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott
213585d4e43e87b3cc95763bd4342a3997acb55de8bPatrick Scott    public boolean onPreferenceChange(final Preference p, Object newValue) {
2146064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        // Asynchronously save the alarm since this method is called _before_
2156064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        // the value of the preference has changed.
2166064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        sHandler.post(new Runnable() {
2176064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott            public void run() {
218585d4e43e87b3cc95763bd4342a3997acb55de8bPatrick Scott                // Editing any preference (except enable) enables the alarm.
219585d4e43e87b3cc95763bd4342a3997acb55de8bPatrick Scott                if (p != mEnabledPref) {
220585d4e43e87b3cc95763bd4342a3997acb55de8bPatrick Scott                    mEnabledPref.setChecked(true);
221585d4e43e87b3cc95763bd4342a3997acb55de8bPatrick Scott                }
22231e21c3131212079a5735bfce949560b03a09a82Michael Chan                saveAlarm(null);
2236064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott            }
2246064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        });
2256064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        return true;
2266064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott    }
2276064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott
2286064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott    private void updatePrefs(Alarm alarm) {
2296064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mId = alarm.id;
2306064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mEnabledPref.setChecked(alarm.enabled);
2316064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mLabel.setText(alarm.label);
232c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        mHour = alarm.hour;
233c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        mMinute = alarm.minutes;
2346064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mRepeatPref.setDaysOfWeek(alarm.daysOfWeek);
2356064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mVibratePref.setChecked(alarm.vibrate);
2366064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        // Give the alert uri to the preference.
2376064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        mAlarmPref.setAlert(alarm.alert);
238c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        updateTime();
239c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    }
240c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan
241c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    @Override
242c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
243c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan            Preference preference) {
244c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        if (preference == mTimePref) {
245c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan            showTimePicker();
246c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        }
247c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan
248c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        return super.onPreferenceTreeClick(preferenceScreen, preference);
2495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
2517495b0046811971ecb0933888d7eafb4c9668ed2Patrick Scott    @Override
2527495b0046811971ecb0933888d7eafb4c9668ed2Patrick Scott    public void onBackPressed() {
253748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        saveAndExit();
2547495b0046811971ecb0933888d7eafb4c9668ed2Patrick Scott    }
2557495b0046811971ecb0933888d7eafb4c9668ed2Patrick Scott
256c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private void showTimePicker() {
2574642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng        AlarmUtils.showTimeEditDialog(getFragmentManager(), null);
258c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    }
259c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan
260bed1a89f743ec8b343803a44b938aad97ba0f16eIsaac Katzenelson    @Override
2614642e848a91180f6ff87acbfa54de1d0b945f19aChiao Cheng    public void onDialogTimeSet(Alarm alarm, int hourOfDay, int minute) {
262c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        // onTimeSet is called when the user clicks "Set"
263c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        mHour = hourOfDay;
264c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        mMinute = minute;
265c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        updateTime();
266c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        // If the time has been changed, enable the alarm.
26790c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott        mEnabledPref.setChecked(true);
268748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        saveAlarm(null);
2695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
271c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    private void updateTime() {
272c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        mTimePref.setSummary(Alarms.formatTime(this, mHour, mMinute,
273c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan                mRepeatPref.getDaysOfWeek()));
274c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan    }
275c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan
27631e21c3131212079a5735bfce949560b03a09a82Michael Chan    private long saveAlarm(Alarm alarm) {
27731e21c3131212079a5735bfce949560b03a09a82Michael Chan        if (alarm == null) {
27831e21c3131212079a5735bfce949560b03a09a82Michael Chan            alarm = buildAlarmFromUi();
2795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        }
280e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott
281e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        long time;
2826064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        if (alarm.id == -1) {
283e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            time = Alarms.addAlarm(this, alarm);
2846064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott            // addAlarm populates the alarm with the new id. Update mId so that
2856064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott            // changes to other preferences update the new alarm.
2866064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott            mId = alarm.id;
287e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        } else {
288e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott            time = Alarms.setAlarm(this, alarm);
289e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott        }
2906064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott        return time;
2915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
2925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
29331e21c3131212079a5735bfce949560b03a09a82Michael Chan    private Alarm buildAlarmFromUi() {
29431e21c3131212079a5735bfce949560b03a09a82Michael Chan        Alarm alarm = new Alarm();
29531e21c3131212079a5735bfce949560b03a09a82Michael Chan        alarm.id = mId;
29631e21c3131212079a5735bfce949560b03a09a82Michael Chan        alarm.enabled = mEnabledPref.isChecked();
297c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        alarm.hour = mHour;
298c4c4a127ab49e01cd520808c74f43940f61f467fMichael Chan        alarm.minutes = mMinute;
29931e21c3131212079a5735bfce949560b03a09a82Michael Chan        alarm.daysOfWeek = mRepeatPref.getDaysOfWeek();
30031e21c3131212079a5735bfce949560b03a09a82Michael Chan        alarm.vibrate = mVibratePref.isChecked();
3019c8f420c5d715d1b3923e7c15a38df0df23f7a39Erik        alarm.label = mLabel.getText().toString();
30231e21c3131212079a5735bfce949560b03a09a82Michael Chan        alarm.alert = mAlarmPref.getAlert();
30331e21c3131212079a5735bfce949560b03a09a82Michael Chan        return alarm;
30431e21c3131212079a5735bfce949560b03a09a82Michael Chan    }
30531e21c3131212079a5735bfce949560b03a09a82Michael Chan
30690c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott    private void deleteAlarm() {
307748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        if (mId == -1) {
308748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            // Unedited, newly created alarms don't require confirmation
309748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            finish();
310748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        } else {
311748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis            new AlertDialog.Builder(this)
312748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    .setTitle(getString(R.string.delete_alarm))
313748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    .setMessage(getString(R.string.delete_alarm_confirm))
314748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    .setPositiveButton(android.R.string.ok,
315748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                            new DialogInterface.OnClickListener() {
316748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                                public void onClick(DialogInterface d, int w) {
317748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                                    Alarms.deleteAlarm(SetAlarm.this, mId);
318748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                                    finish();
319748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                                }
320748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                            })
321748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    .setNegativeButton(android.R.string.cancel, null)
322748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis                    .show();
323748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        }
32431e21c3131212079a5735bfce949560b03a09a82Michael Chan    }
32531e21c3131212079a5735bfce949560b03a09a82Michael Chan
3267b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis    private void revert() {
3277b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        int newId = mId;
3287b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        // "Revert" on a newly created alarm should delete it.
3297b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        if (mOriginalAlarm.id == -1) {
3307b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            Alarms.deleteAlarm(SetAlarm.this, newId);
3317b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        } else {
3327b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis            saveAlarm(mOriginalAlarm);
3337b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis        }
3347b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis    }
3357b13ff0a3e1e71b27f7ef5ef749b602ff17a40d3Steve Levis
336748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    /**
337748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis     * Store any changes to the alarm and exit the activity.
338748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis     * Show a toast if the alarm is enabled with the time remaining until alarm
339748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis     */
340748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis    private void saveAndExit() {
341748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        long time = saveAlarm(null);
342748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        if(mEnabledPref.isChecked()) {
3435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng            AlarmUtils.popAlarmSetToast(SetAlarm.this, time);
34431e21c3131212079a5735bfce949560b03a09a82Michael Chan        }
345748e9ada696912c262a097d4211fde528f1cc0b8Steve Levis        finish();
34690c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott    }
34790c4833f94f4775f747333f8bd67107364a1d9c1Patrick Scott
3485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    /**
3495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * format "Alarm set for 2 days 7 hours and 53 minutes from
3505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     * now"
3515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project     */
352c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott    static String formatToast(Context context, long timeInMillis) {
353c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott        long delta = timeInMillis - System.currentTimeMillis();
3545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        long hours = delta / (1000 * 60 * 60);
3555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        long minutes = delta / (1000 * 60) % 60;
3565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        long days = hours / 24;
3575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        hours = hours % 24;
3585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String daySeq = (days == 0) ? "" :
3605fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                (days == 1) ? context.getString(R.string.day) :
3615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getString(R.string.days, Long.toString(days));
3625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String minSeq = (minutes == 0) ? "" :
3645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                (minutes == 1) ? context.getString(R.string.minute) :
3655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getString(R.string.minutes, Long.toString(minutes));
3665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        String hourSeq = (hours == 0) ? "" :
3685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                (hours == 1) ? context.getString(R.string.hour) :
3695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project                context.getString(R.string.hours, Long.toString(hours));
3705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        boolean dispDays = days > 0;
3725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        boolean dispHour = hours > 0;
3735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project        boolean dispMinute = minutes > 0;
3745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3751bc128fd4266656ebc7e8abc6bf22652f6a6134aEric Fischer        int index = (dispDays ? 1 : 0) |
3761bc128fd4266656ebc7e8abc6bf22652f6a6134aEric Fischer                    (dispHour ? 2 : 0) |
3771bc128fd4266656ebc7e8abc6bf22652f6a6134aEric Fischer                    (dispMinute ? 4 : 0);
3785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project
3791bc128fd4266656ebc7e8abc6bf22652f6a6134aEric Fischer        String[] formats = context.getResources().getStringArray(R.array.alarm_set);
3801bc128fd4266656ebc7e8abc6bf22652f6a6134aEric Fischer        return String.format(formats[index], daySeq, hourSeq, minSeq);
3815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project    }
3825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project}
383