OSDN Git Service

am 630cb4aa: (-s ours) Merge change Iabe6771c into eclair
[android-x86/packages-apps-DeskClock.git] / src / com / android / deskclock / SetAlarm.java
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.deskclock;
18
19 import android.app.AlertDialog;
20 import android.app.TimePickerDialog;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.media.RingtoneManager;
25 import android.net.Uri;
26 import android.os.Bundle;
27 import android.preference.CheckBoxPreference;
28 import android.preference.EditTextPreference;
29 import android.preference.Preference;
30 import android.preference.PreferenceActivity;
31 import android.preference.PreferenceScreen;
32 import android.text.format.DateFormat;
33 import android.view.LayoutInflater;
34 import android.view.Menu;
35 import android.view.MenuItem;
36 import android.view.View;
37 import android.view.ViewGroup.LayoutParams;
38 import android.widget.Button;
39 import android.widget.FrameLayout;
40 import android.widget.LinearLayout;
41 import android.widget.ListView;
42 import android.widget.TimePicker;
43 import android.widget.Toast;
44
45 /**
46  * Manages each alarm
47  */
48 public class SetAlarm extends PreferenceActivity
49         implements TimePickerDialog.OnTimeSetListener {
50
51     private EditTextPreference mLabel;
52     private CheckBoxPreference mEnabledPref;
53     private Preference mTimePref;
54     private AlarmPreference mAlarmPref;
55     private CheckBoxPreference mVibratePref;
56     private RepeatPreference mRepeatPref;
57     private MenuItem mTestAlarmItem;
58
59     private int     mId;
60     private int     mHour;
61     private int     mMinutes;
62
63     /**
64      * Set an alarm.  Requires an Alarms.ALARM_ID to be passed in as an
65      * extra. FIXME: Pass an Alarm object like every other Activity.
66      */
67     @Override
68     protected void onCreate(Bundle icicle) {
69         super.onCreate(icicle);
70
71         addPreferencesFromResource(R.xml.alarm_prefs);
72
73         // Get each preference so we can retrieve the value later.
74         mLabel = (EditTextPreference) findPreference("label");
75         mLabel.setOnPreferenceChangeListener(
76                 new Preference.OnPreferenceChangeListener() {
77                     public boolean onPreferenceChange(Preference p,
78                             Object newValue) {
79                         // Set the summary based on the new label.
80                         p.setSummary((String) newValue);
81                         return true;
82                     }
83                 });
84         mEnabledPref = (CheckBoxPreference) findPreference("enabled");
85         mTimePref = findPreference("time");
86         mAlarmPref = (AlarmPreference) findPreference("alarm");
87         mVibratePref = (CheckBoxPreference) findPreference("vibrate");
88         mRepeatPref = (RepeatPreference) findPreference("setRepeat");
89
90         Intent i = getIntent();
91         mId = i.getIntExtra(Alarms.ALARM_ID, -1);
92         if (Log.LOGV) {
93             Log.v("In SetAlarm, alarm id = " + mId);
94         }
95
96         /* load alarm details from database */
97         Alarm alarm = Alarms.getAlarm(getContentResolver(), mId);
98         // Bad alarm, bail to avoid a NPE.
99         if (alarm == null) {
100             finish();
101             return;
102         }
103         mEnabledPref.setChecked(alarm.enabled);
104         mLabel.setText(alarm.label);
105         mLabel.setSummary(alarm.label);
106         mHour = alarm.hour;
107         mMinutes = alarm.minutes;
108         mRepeatPref.setDaysOfWeek(alarm.daysOfWeek);
109         mVibratePref.setChecked(alarm.vibrate);
110         // Give the alert uri to the preference.
111         mAlarmPref.setAlert(alarm.alert);
112         updateTime();
113
114         // We have to do this to get the save/cancel buttons to highlight on
115         // their own.
116         getListView().setItemsCanFocus(true);
117
118         // Grab the content view so we can modify it.
119         FrameLayout content = (FrameLayout) getWindow().getDecorView()
120                 .findViewById(com.android.internal.R.id.content);
121
122         // Get the main ListView and remove it from the content view.
123         ListView lv = getListView();
124         content.removeView(lv);
125
126         // Create the new LinearLayout that will become the content view and
127         // make it vertical.
128         LinearLayout ll = new LinearLayout(this);
129         ll.setOrientation(LinearLayout.VERTICAL);
130
131         // Have the ListView expand to fill the screen minus the save/cancel
132         // buttons.
133         LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
134                 LayoutParams.FILL_PARENT,
135                 LayoutParams.WRAP_CONTENT);
136         lp.weight = 1;
137         ll.addView(lv, lp);
138
139         // Inflate the buttons onto the LinearLayout.
140         View v = LayoutInflater.from(this).inflate(
141                 R.layout.save_cancel_alarm, ll);
142
143         // Attach actions to each button.
144         Button b = (Button) v.findViewById(R.id.alarm_save);
145         b.setOnClickListener(new View.OnClickListener() {
146                 public void onClick(View v) {
147                     // Enable the alarm when clicking "Done"
148                     mEnabledPref.setChecked(true);
149                     saveAlarm();
150                     finish();
151                 }
152         });
153         b = (Button) v.findViewById(R.id.alarm_cancel);
154         b.setOnClickListener(new View.OnClickListener() {
155                 public void onClick(View v) {
156                     finish();
157                 }
158         });
159         b = (Button) v.findViewById(R.id.alarm_delete);
160         b.setOnClickListener(new View.OnClickListener() {
161                 public void onClick(View v) {
162                     deleteAlarm();
163                 }
164         });
165
166         // Replace the old content view with our new one.
167         setContentView(ll);
168     }
169
170     @Override
171     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
172             Preference preference) {
173         if (preference == mTimePref) {
174             new TimePickerDialog(this, this, mHour, mMinutes,
175                     DateFormat.is24HourFormat(this)).show();
176         }
177
178         return super.onPreferenceTreeClick(preferenceScreen, preference);
179     }
180
181     @Override
182     public void onBackPressed() {
183         saveAlarm();
184         finish();
185     }
186
187     public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
188         mHour = hourOfDay;
189         mMinutes = minute;
190         updateTime();
191         // If the time has been changed, enable the alarm.
192         mEnabledPref.setChecked(true);
193     }
194
195     private void updateTime() {
196         if (Log.LOGV) {
197             Log.v("updateTime " + mId);
198         }
199         mTimePref.setSummary(Alarms.formatTime(this, mHour, mMinutes,
200                 mRepeatPref.getDaysOfWeek()));
201     }
202
203     private void saveAlarm() {
204         final String alert = mAlarmPref.getAlertString();
205         long time = Alarms.setAlarm(this, mId, mEnabledPref.isChecked(), mHour,
206                 mMinutes, mRepeatPref.getDaysOfWeek(), mVibratePref.isChecked(),
207                 mLabel.getText(), alert);
208
209         if (mEnabledPref.isChecked()) {
210             popAlarmSetToast(this, time);
211         }
212     }
213
214     private void deleteAlarm() {
215         new AlertDialog.Builder(this)
216                 .setTitle(getString(R.string.delete_alarm))
217                 .setMessage(getString(R.string.delete_alarm_confirm))
218                 .setPositiveButton(android.R.string.ok,
219                         new DialogInterface.OnClickListener() {
220                             public void onClick(DialogInterface d, int w) {
221                                 Alarms.deleteAlarm(SetAlarm.this, mId);
222                                 finish();
223                             }
224                         })
225                 .setNegativeButton(android.R.string.cancel, null)
226                 .show();
227     }
228
229     /**
230      * Write alarm out to persistent store and pops toast if alarm
231      * enabled.
232      * Used only in test code.
233      */
234     private static void saveAlarm(
235             Context context, int id, boolean enabled, int hour, int minute,
236             Alarm.DaysOfWeek daysOfWeek, boolean vibrate, String label,
237             String alert, boolean popToast) {
238         if (Log.LOGV) Log.v("** saveAlarm " + id + " " + label + " " + enabled
239                 + " " + hour + " " + minute + " vibe " + vibrate);
240
241         // Fix alert string first
242         long time = Alarms.setAlarm(context, id, enabled, hour, minute,
243                 daysOfWeek, vibrate, label, alert);
244
245         if (enabled && popToast) {
246             popAlarmSetToast(context, time);
247         }
248     }
249
250     /**
251      * Display a toast that tells the user how long until the alarm
252      * goes off.  This helps prevent "am/pm" mistakes.
253      */
254     static void popAlarmSetToast(Context context, int hour, int minute,
255                                  Alarm.DaysOfWeek daysOfWeek) {
256         popAlarmSetToast(context,
257                 Alarms.calculateAlarm(hour, minute, daysOfWeek)
258                 .getTimeInMillis());
259     }
260
261     private static void popAlarmSetToast(Context context, long timeInMillis) {
262         String toastText = formatToast(context, timeInMillis);
263         Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_LONG);
264         ToastMaster.setToast(toast);
265         toast.show();
266     }
267
268     /**
269      * format "Alarm set for 2 days 7 hours and 53 minutes from
270      * now"
271      */
272     static String formatToast(Context context, long timeInMillis) {
273         long delta = timeInMillis - System.currentTimeMillis();
274         long hours = delta / (1000 * 60 * 60);
275         long minutes = delta / (1000 * 60) % 60;
276         long days = hours / 24;
277         hours = hours % 24;
278
279         String daySeq = (days == 0) ? "" :
280                 (days == 1) ? context.getString(R.string.day) :
281                 context.getString(R.string.days, Long.toString(days));
282
283         String minSeq = (minutes == 0) ? "" :
284                 (minutes == 1) ? context.getString(R.string.minute) :
285                 context.getString(R.string.minutes, Long.toString(minutes));
286
287         String hourSeq = (hours == 0) ? "" :
288                 (hours == 1) ? context.getString(R.string.hour) :
289                 context.getString(R.string.hours, Long.toString(hours));
290
291         boolean dispDays = days > 0;
292         boolean dispHour = hours > 0;
293         boolean dispMinute = minutes > 0;
294
295         int index = (dispDays ? 1 : 0) |
296                     (dispHour ? 2 : 0) |
297                     (dispMinute ? 4 : 0);
298
299         String[] formats = context.getResources().getStringArray(R.array.alarm_set);
300         return String.format(formats[index], daySeq, hourSeq, minSeq);
301     }
302
303     public boolean onCreateOptionsMenu(Menu menu) {
304         super.onCreateOptionsMenu(menu);
305
306         if (AlarmClock.DEBUG) {
307             mTestAlarmItem = menu.add(0, 0, 0, "test alarm");
308         }
309
310         return true;
311     }
312
313     public boolean onOptionsItemSelected(MenuItem item) {
314         if (AlarmClock.DEBUG) {
315             if (item == mTestAlarmItem) {
316                 setTestAlarm();
317                 return true;
318             }
319         }
320
321         return false;
322     }
323
324
325     /**
326      * Test code: this is disabled for production build.  Sets
327      * this alarm to go off on the next minute
328      */
329     void setTestAlarm() {
330
331         // start with now
332         java.util.Calendar c = java.util.Calendar.getInstance();
333         c.setTimeInMillis(System.currentTimeMillis());
334
335         int nowHour = c.get(java.util.Calendar.HOUR_OF_DAY);
336         int nowMinute = c.get(java.util.Calendar.MINUTE);
337
338         int minutes = (nowMinute + 1) % 60;
339         int hour = nowHour + (nowMinute == 0 ? 1 : 0);
340
341         saveAlarm(this, mId, true, hour, minutes, mRepeatPref.getDaysOfWeek(),
342                 true, mLabel.getText(), mAlarmPref.getAlertString(), true);
343     }
344
345 }