OSDN Git Service

2b542b630bb833ea7711fe664a65ed547aaa2e9e
[android-x86/packages-apps-DeskClock.git] / src / com / android / alarmclock / AlarmClock.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.alarmclock;
18
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.content.SharedPreferences;
25 import android.database.Cursor;
26 import android.net.Uri;
27 import android.os.Bundle;
28 import android.os.Handler;
29 import android.provider.Settings;
30 import android.view.ContextMenu;
31 import android.view.ContextMenu.ContextMenuInfo;
32 import android.view.LayoutInflater;
33 import android.view.Menu;
34 import android.view.MenuItem;
35 import android.view.View;
36 import android.view.View.OnClickListener;
37 import android.view.ViewGroup;
38 import android.widget.CursorAdapter;
39 import android.widget.ListView;
40 import android.widget.TextView;
41 import android.widget.CheckBox;
42
43 import java.util.Calendar;
44
45 /**
46  * AlarmClock application.
47  */
48 public class AlarmClock extends Activity {
49
50     final static String PREFERENCES = "AlarmClock";
51     final static String PREF_CLOCK_FACE = "face";
52     final static String PREF_SHOW_CLOCK = "show_clock";
53
54     /** Cap alarm count at this number */
55     final static int MAX_ALARM_COUNT = 12;
56
57     /** This must be false for production.  If true, turns on logging,
58         test code, etc. */
59     final static boolean DEBUG = false;
60
61     private SharedPreferences mPrefs;
62     private LayoutInflater mFactory;
63     private ViewGroup mClockLayout;
64     private View mClock = null;
65     private MenuItem mAddAlarmItem;
66     private MenuItem mToggleClockItem;
67     private ListView mAlarmsList;
68     private Cursor mCursor;
69
70     /**
71      * Which clock face to show
72      */
73     private int mFace = -1;
74
75     /*
76      * FIXME: it would be nice for this to live in an xml config file.
77      */
78     final static int[] CLOCKS = {
79         R.layout.clock_basic_bw,
80         R.layout.clock_googly,
81         R.layout.clock_droid2,
82         R.layout.clock_droids,
83         R.layout.digital_clock
84     };
85
86     private class AlarmTimeAdapter extends CursorAdapter {
87         public AlarmTimeAdapter(Context context, Cursor cursor) {
88             super(context, cursor);
89         }
90
91         public View newView(Context context, Cursor cursor, ViewGroup parent) {
92             View ret = mFactory.inflate(R.layout.alarm_time, parent, false);
93             DigitalClock digitalClock = (DigitalClock)ret.findViewById(R.id.digitalClock);
94             digitalClock.setLive(false);
95             if (Log.LOGV) Log.v("newView " + cursor.getPosition());
96             return ret;
97         }
98
99         public void bindView(View view, Context context, Cursor cursor) {
100             final int id = cursor.getInt(Alarms.AlarmColumns.ALARM_ID_INDEX);
101             final int hour = cursor.getInt(Alarms.AlarmColumns.ALARM_HOUR_INDEX);
102             final int minutes = cursor.getInt(Alarms.AlarmColumns.ALARM_MINUTES_INDEX);
103             final Alarms.DaysOfWeek daysOfWeek = new Alarms.DaysOfWeek(
104                     cursor.getInt(Alarms.AlarmColumns.ALARM_DAYS_OF_WEEK_INDEX));
105             final boolean enabled = cursor.getInt(Alarms.AlarmColumns.ALARM_ENABLED_INDEX) == 1;
106             final String label =
107                     cursor.getString(Alarms.AlarmColumns.ALARM_MESSAGE_INDEX);
108
109             CheckBox onButton = (CheckBox)view.findViewById(R.id.alarmButton);
110             onButton.setChecked(enabled);
111             onButton.setOnClickListener(new OnClickListener() {
112                     public void onClick(View v) {
113                         boolean isChecked = ((CheckBox) v).isChecked();
114                         Alarms.enableAlarm(AlarmClock.this, id, isChecked);
115                         if (isChecked) {
116                             SetAlarm.popAlarmSetToast(
117                                     AlarmClock.this, hour, minutes, daysOfWeek);
118                         }
119                     }
120             });
121
122             DigitalClock digitalClock = (DigitalClock)view.findViewById(R.id.digitalClock);
123             if (Log.LOGV) Log.v("bindView " + cursor.getPosition() + " " + id + " " + hour +
124                                 ":" + minutes + " " + daysOfWeek.toString(context, true) + " dc " + digitalClock);
125
126             digitalClock.setOnClickListener(new OnClickListener() {
127                     public void onClick(View v) {
128                         if (true) {
129                             Intent intent = new Intent(AlarmClock.this, SetAlarm.class);
130                             intent.putExtra(Alarms.ID, id);
131                             startActivity(intent);
132                         } else {
133                             // TESTING: immediately pop alarm
134                             Intent fireAlarm = new Intent(AlarmClock.this, AlarmAlert.class);
135                             fireAlarm.putExtra(Alarms.ID, id);
136                             fireAlarm.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
137                             startActivity(fireAlarm);
138                         }
139                     }
140                 });
141
142             // set the alarm text
143             final Calendar c = Calendar.getInstance();
144             c.set(Calendar.HOUR_OF_DAY, hour);
145             c.set(Calendar.MINUTE, minutes);
146             digitalClock.updateTime(c);
147
148             // Set the repeat text or leave it blank if it does not repeat.
149             TextView daysOfWeekView = (TextView) digitalClock.findViewById(R.id.daysOfWeek);
150             final String daysOfWeekStr =
151                     daysOfWeek.toString(AlarmClock.this, false);
152             if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) {
153                 daysOfWeekView.setText(daysOfWeekStr);
154                 daysOfWeekView.setVisibility(View.VISIBLE);
155             } else {
156                 daysOfWeekView.setVisibility(View.GONE);
157             }
158
159             // Display the label
160             TextView labelView =
161                     (TextView) digitalClock.findViewById(R.id.label);
162             if (label != null && label.length() != 0) {
163                 labelView.setText(label);
164                 labelView.setVisibility(View.VISIBLE);
165             } else {
166                 labelView.setVisibility(View.GONE);
167             }
168
169             // Build context menu
170             digitalClock.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
171                     public void onCreateContextMenu(ContextMenu menu, View view,
172                                                     ContextMenuInfo menuInfo) {
173                         menu.setHeaderTitle(Alarms.formatTime(AlarmClock.this, c));
174                         MenuItem deleteAlarmItem = menu.add(0, id, 0, R.string.delete_alarm);
175                     }
176                 });
177         }
178     };
179
180     @Override
181     public boolean onContextItemSelected(final MenuItem item) {
182         // Confirm that the alarm will be deleted.
183         new AlertDialog.Builder(this)
184                 .setTitle(getString(R.string.delete_alarm))
185                 .setMessage(getString(R.string.delete_alarm_confirm))
186                 .setPositiveButton(android.R.string.ok,
187                         new DialogInterface.OnClickListener() {
188                             public void onClick(DialogInterface d, int w) {
189                                 Alarms.deleteAlarm(AlarmClock.this,
190                                         item.getItemId());
191                             }
192                         })
193                 .setNegativeButton(android.R.string.cancel, null)
194                 .show();
195         return true;
196     }
197
198     @Override
199     protected void onCreate(Bundle icicle) {
200         super.onCreate(icicle);
201
202         // sanity check -- no database, no clock
203         if (getContentResolver() == null) {
204             new AlertDialog.Builder(this)
205                     .setTitle(getString(R.string.error))
206                     .setMessage(getString(R.string.dberror))
207                     .setPositiveButton(
208                             android.R.string.ok,
209                             new DialogInterface.OnClickListener() {
210                                 public void onClick(DialogInterface dialog, int which) {
211                                     finish();
212                                 }
213                             })
214                     .setOnCancelListener(
215                             new DialogInterface.OnCancelListener() {
216                                 public void onCancel(DialogInterface dialog) {
217                                     finish();
218                                 }})
219                     .setIcon(android.R.drawable.ic_dialog_alert)
220                     .create().show();
221             return;
222         }
223
224         setContentView(R.layout.alarm_clock);
225         mFactory = LayoutInflater.from(this);
226         mPrefs = getSharedPreferences(PREFERENCES, 0);
227
228         mCursor = Alarms.getAlarmsCursor(getContentResolver());
229         mAlarmsList = (ListView) findViewById(R.id.alarms_list);
230         mAlarmsList.setAdapter(new AlarmTimeAdapter(this, mCursor));
231         mAlarmsList.setVerticalScrollBarEnabled(true);
232         mAlarmsList.setItemsCanFocus(true);
233
234         mClockLayout = (ViewGroup) findViewById(R.id.clock_layout);
235         mClockLayout.setOnClickListener(new View.OnClickListener() {
236                 public void onClick(View v) {
237                     final Intent intent = new Intent(AlarmClock.this, ClockPicker.class);
238                     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
239                     startActivity(intent);
240                 }
241             });
242
243         setClockVisibility(mPrefs.getBoolean(PREF_SHOW_CLOCK, true));
244     }
245
246     @Override
247     protected void onResume() {
248         super.onResume();
249
250         int face = mPrefs.getInt(PREF_CLOCK_FACE, 0);
251         if (mFace != face) {
252             if (face < 0 || face >= AlarmClock.CLOCKS.length)
253                 mFace = 0;
254             else
255                 mFace = face;
256             inflateClock();
257         }
258     }
259
260     @Override
261     protected void onDestroy() {
262         super.onDestroy();
263         ToastMaster.cancelToast();
264         mCursor.deactivate();
265     }
266
267     protected void inflateClock() {
268         if (mClock != null) {
269             mClockLayout.removeView(mClock);
270         }
271         mClock = mFactory.inflate(CLOCKS[mFace], null);
272         mClockLayout.addView(mClock, 0);
273     }
274
275     @Override
276     public boolean onCreateOptionsMenu(Menu menu) {
277         // Inflate our menu.
278         getMenuInflater().inflate(R.menu.main_menu, menu);
279
280         return super.onCreateOptionsMenu(menu);
281     }
282
283     /**
284      * Only allow user to add a new alarm if there are fewer than
285      * MAX_ALARM_COUNT
286      */
287     @Override
288     public boolean onPrepareOptionsMenu(Menu menu) {
289         menu.findItem(R.id.menu_add_alarm).setVisible(
290                 mAlarmsList.getAdapter().getCount() < MAX_ALARM_COUNT);
291         menu.findItem(R.id.menu_toggle_clock).setTitle(
292                 getClockVisibility() ? R.string.hide_clock
293                     : R.string.show_clock);
294         return super.onPrepareOptionsMenu(menu);
295     }
296
297     @Override
298     public boolean onOptionsItemSelected(MenuItem item) {
299         switch (item.getItemId()) {
300             case R.id.menu_add_alarm:
301                 Uri uri = Alarms.addAlarm(getContentResolver());
302                 // FIXME: scroll to new item?
303                 String segment = uri.getPathSegments().get(1);
304                 int newId = Integer.parseInt(segment);
305                 if (Log.LOGV) {
306                     Log.v("In AlarmClock, new alarm id = " + newId);
307                 }
308                 Intent intent = new Intent(this, SetAlarm.class);
309                 intent.putExtra(Alarms.ID, newId);
310                 startActivity(intent);
311                 return true;
312
313             case R.id.menu_toggle_clock:
314                 setClockVisibility(!getClockVisibility());
315                 saveClockVisibility();
316                 return true;
317
318             case R.id.menu_settings:
319                 startActivity(new Intent(this, SettingsActivity.class));
320                 return true;
321         }
322
323         return super.onOptionsItemSelected(item);
324     }
325
326
327     private boolean getClockVisibility() {
328         return mClockLayout.getVisibility() == View.VISIBLE;
329     }
330
331     private void setClockVisibility(boolean visible) {
332         mClockLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
333     }
334
335     private void saveClockVisibility() {
336         mPrefs.edit().putBoolean(PREF_SHOW_CLOCK, getClockVisibility()).commit();
337     }
338 }