OSDN Git Service

resolved conflicts for merge of 1bc128fd to master
[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.View.OnCreateContextMenuListener;
38 import android.view.ViewGroup;
39 import android.widget.AdapterView;
40 import android.widget.AdapterView.AdapterContextMenuInfo;
41 import android.widget.AdapterView.OnItemClickListener;
42 import android.widget.CursorAdapter;
43 import android.widget.ListView;
44 import android.widget.TextView;
45 import android.widget.CheckBox;
46
47 import java.util.Calendar;
48 import java.text.DateFormatSymbols;
49
50 /**
51  * AlarmClock application.
52  */
53 public class AlarmClock extends Activity implements OnItemClickListener {
54
55     final static String PREFERENCES = "AlarmClock";
56     final static String PREF_CLOCK_FACE = "face";
57     final static String PREF_SHOW_CLOCK = "show_clock";
58
59     /** Cap alarm count at this number */
60     final static int MAX_ALARM_COUNT = 12;
61
62     /** This must be false for production.  If true, turns on logging,
63         test code, etc. */
64     final static boolean DEBUG = false;
65
66     private SharedPreferences mPrefs;
67     private LayoutInflater mFactory;
68     private ViewGroup mClockLayout;
69     private View mClock = null;
70     private ListView mAlarmsList;
71     private Cursor mCursor;
72
73     private String mAm, mPm;
74
75     /**
76      * Which clock face to show
77      */
78     private int mFace = -1;
79
80     /*
81      * FIXME: it would be nice for this to live in an xml config file.
82      */
83     final static int[] CLOCKS = {
84         R.layout.clock_basic_bw,
85         R.layout.clock_googly,
86         R.layout.clock_droid2,
87         R.layout.clock_droids,
88         R.layout.digital_clock
89     };
90
91     private class AlarmTimeAdapter extends CursorAdapter {
92         public AlarmTimeAdapter(Context context, Cursor cursor) {
93             super(context, cursor);
94         }
95
96         public View newView(Context context, Cursor cursor, ViewGroup parent) {
97             View ret = mFactory.inflate(R.layout.alarm_time, parent, false);
98
99             ((TextView) ret.findViewById(R.id.am)).setText(mAm);
100             ((TextView) ret.findViewById(R.id.pm)).setText(mPm);
101
102             DigitalClock digitalClock = (DigitalClock)ret.findViewById(R.id.digitalClock);
103             digitalClock.setLive(false);
104             if (Log.LOGV) Log.v("newView " + cursor.getPosition());
105             return ret;
106         }
107
108         public void bindView(View view, Context context, Cursor cursor) {
109             final Alarm alarm = new Alarm(cursor);
110
111             CheckBox onButton = (CheckBox)view.findViewById(R.id.alarmButton);
112             onButton.setChecked(alarm.enabled);
113             onButton.setOnClickListener(new OnClickListener() {
114                     public void onClick(View v) {
115                         boolean isChecked = ((CheckBox) v).isChecked();
116                         Alarms.enableAlarm(AlarmClock.this, alarm.id,
117                             isChecked);
118                         if (isChecked) {
119                             SetAlarm.popAlarmSetToast(AlarmClock.this,
120                                 alarm.hour, alarm.minutes, alarm.daysOfWeek);
121                         }
122                     }
123             });
124
125             DigitalClock digitalClock =
126                     (DigitalClock) view.findViewById(R.id.digitalClock);
127
128             // set the alarm text
129             final Calendar c = Calendar.getInstance();
130             c.set(Calendar.HOUR_OF_DAY, alarm.hour);
131             c.set(Calendar.MINUTE, alarm.minutes);
132             digitalClock.updateTime(c);
133
134             // Set the repeat text or leave it blank if it does not repeat.
135             TextView daysOfWeekView =
136                     (TextView) digitalClock.findViewById(R.id.daysOfWeek);
137             final String daysOfWeekStr =
138                     alarm.daysOfWeek.toString(AlarmClock.this, false);
139             if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) {
140                 daysOfWeekView.setText(daysOfWeekStr);
141                 daysOfWeekView.setVisibility(View.VISIBLE);
142             } else {
143                 daysOfWeekView.setVisibility(View.GONE);
144             }
145
146             // Display the label
147             TextView labelView =
148                     (TextView) digitalClock.findViewById(R.id.label);
149             if (alarm.label != null && alarm.label.length() != 0) {
150                 labelView.setText(alarm.label);
151                 labelView.setVisibility(View.VISIBLE);
152             } else {
153                 labelView.setVisibility(View.GONE);
154             }
155         }
156     };
157
158     @Override
159     public boolean onContextItemSelected(final MenuItem item) {
160         final AdapterContextMenuInfo info =
161                 (AdapterContextMenuInfo) item.getMenuInfo();
162         final int id = (int) info.id;
163         switch (item.getItemId()) {
164             case R.id.delete_alarm:
165                 // Confirm that the alarm will be deleted.
166                 new AlertDialog.Builder(this)
167                         .setTitle(getString(R.string.delete_alarm))
168                         .setMessage(getString(R.string.delete_alarm_confirm))
169                         .setPositiveButton(android.R.string.ok,
170                                 new DialogInterface.OnClickListener() {
171                                     public void onClick(DialogInterface d,
172                                             int w) {
173                                         Alarms.deleteAlarm(AlarmClock.this, id);
174                                     }
175                                 })
176                         .setNegativeButton(android.R.string.cancel, null)
177                         .show();
178                 return true;
179
180             case R.id.enable_alarm:
181                 final Cursor c = (Cursor) mAlarmsList.getAdapter()
182                         .getItem(info.position);
183                 final Alarm alarm = new Alarm(c);
184                 Alarms.enableAlarm(this, alarm.id, !alarm.enabled);
185                 if (!alarm.enabled) {
186                     SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes,
187                             alarm.daysOfWeek);
188                 }
189                 return true;
190
191             default:
192                 break;
193         }
194         return super.onContextItemSelected(item);
195     }
196
197     @Override
198     protected void onCreate(Bundle icicle) {
199         super.onCreate(icicle);
200
201         String[] ampm = new DateFormatSymbols().getAmPmStrings();
202         mAm = ampm[0];
203         mPm = ampm[1];
204
205         // sanity check -- no database, no clock
206         if (getContentResolver() == null) {
207             new AlertDialog.Builder(this)
208                     .setTitle(getString(R.string.error))
209                     .setMessage(getString(R.string.dberror))
210                     .setPositiveButton(
211                             android.R.string.ok,
212                             new DialogInterface.OnClickListener() {
213                                 public void onClick(DialogInterface dialog, int which) {
214                                     finish();
215                                 }
216                             })
217                     .setOnCancelListener(
218                             new DialogInterface.OnCancelListener() {
219                                 public void onCancel(DialogInterface dialog) {
220                                     finish();
221                                 }})
222                     .setIcon(android.R.drawable.ic_dialog_alert)
223                     .create().show();
224             return;
225         }
226
227         setContentView(R.layout.alarm_clock);
228         mFactory = LayoutInflater.from(this);
229         mPrefs = getSharedPreferences(PREFERENCES, 0);
230
231         mCursor = Alarms.getAlarmsCursor(getContentResolver());
232         mAlarmsList = (ListView) findViewById(R.id.alarms_list);
233         mAlarmsList.setAdapter(new AlarmTimeAdapter(this, mCursor));
234         mAlarmsList.setVerticalScrollBarEnabled(true);
235         mAlarmsList.setOnItemClickListener(this);
236         mAlarmsList.setOnCreateContextMenuListener(this);
237
238         mClockLayout = (ViewGroup) findViewById(R.id.clock_layout);
239         mClockLayout.setOnClickListener(new View.OnClickListener() {
240                 public void onClick(View v) {
241                     final Intent intent = new Intent(AlarmClock.this, ClockPicker.class);
242                     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
243                     startActivity(intent);
244                 }
245             });
246
247         setClockVisibility(mPrefs.getBoolean(PREF_SHOW_CLOCK, true));
248     }
249
250     @Override
251     protected void onResume() {
252         super.onResume();
253
254         int face = mPrefs.getInt(PREF_CLOCK_FACE, 0);
255         if (mFace != face) {
256             if (face < 0 || face >= AlarmClock.CLOCKS.length)
257                 mFace = 0;
258             else
259                 mFace = face;
260             inflateClock();
261         }
262     }
263
264     @Override
265     protected void onDestroy() {
266         super.onDestroy();
267         ToastMaster.cancelToast();
268         mCursor.deactivate();
269     }
270
271     protected void inflateClock() {
272         if (mClock != null) {
273             mClockLayout.removeView(mClock);
274         }
275
276         LayoutInflater.from(this).inflate(CLOCKS[mFace], mClockLayout);
277         mClock = findViewById(R.id.clock);
278
279         TextView am = (TextView) findViewById(R.id.am);
280         TextView pm = (TextView) findViewById(R.id.pm);
281
282         if (am != null) {
283             am.setText(mAm);
284         }
285         if (pm != null) {
286             pm.setText(mPm);
287         }
288     }
289
290     @Override
291     public boolean onCreateOptionsMenu(Menu menu) {
292         // Inflate our menu.
293         getMenuInflater().inflate(R.menu.main_menu, menu);
294
295         return super.onCreateOptionsMenu(menu);
296     }
297
298     @Override
299     public void onCreateContextMenu(ContextMenu menu, View view,
300             ContextMenuInfo menuInfo) {
301         // Inflate the menu from xml.
302         getMenuInflater().inflate(R.menu.context_menu, menu);
303
304         // Use the current item to create a custom view for the header.
305         final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
306         final Cursor c =
307                 (Cursor) mAlarmsList.getAdapter().getItem((int) info.position);
308         final Alarm alarm = new Alarm(c);
309
310         // Construct the Calendar to compute the time.
311         final Calendar cal = Calendar.getInstance();
312         cal.set(Calendar.HOUR_OF_DAY, alarm.hour);
313         cal.set(Calendar.MINUTE, alarm.minutes);
314         final String time = Alarms.formatTime(this, cal);
315
316         // Inflate the custom view and set each TextView's text.
317         final View v = mFactory.inflate(R.layout.context_menu_header, null);
318         TextView textView = (TextView) v.findViewById(R.id.header_time);
319         textView.setText(time);
320         textView = (TextView) v.findViewById(R.id.header_label);
321         textView.setText(alarm.label);
322
323         // Set the custom view on the menu.
324         menu.setHeaderView(v);
325         // Change the text to "disable" if the alarm is already enabled.
326         if (alarm.enabled) {
327             menu.findItem(R.id.enable_alarm).setTitle(R.string.disable_alarm);
328         }
329     }
330
331     public void onItemClick(AdapterView parent, View v, int pos, long id) {
332         Intent intent = new Intent(this, SetAlarm.class);
333         intent.putExtra(Alarms.ALARM_ID, (int) id);
334         startActivity(intent);
335     }
336
337     /**
338      * Only allow user to add a new alarm if there are fewer than
339      * MAX_ALARM_COUNT
340      */
341     @Override
342     public boolean onPrepareOptionsMenu(Menu menu) {
343         menu.findItem(R.id.menu_add_alarm).setVisible(
344                 mAlarmsList.getAdapter().getCount() < MAX_ALARM_COUNT);
345         menu.findItem(R.id.menu_toggle_clock).setTitle(
346                 getClockVisibility() ? R.string.hide_clock
347                     : R.string.show_clock);
348         return super.onPrepareOptionsMenu(menu);
349     }
350
351     @Override
352     public boolean onOptionsItemSelected(MenuItem item) {
353         switch (item.getItemId()) {
354             case R.id.menu_add_alarm:
355                 Uri uri = Alarms.addAlarm(getContentResolver());
356                 // FIXME: scroll to new item?
357                 String segment = uri.getPathSegments().get(1);
358                 int newId = Integer.parseInt(segment);
359                 if (Log.LOGV) {
360                     Log.v("In AlarmClock, new alarm id = " + newId);
361                 }
362                 Intent intent = new Intent(this, SetAlarm.class);
363                 intent.putExtra(Alarms.ALARM_ID, newId);
364                 startActivity(intent);
365                 return true;
366
367             case R.id.menu_toggle_clock:
368                 setClockVisibility(!getClockVisibility());
369                 saveClockVisibility();
370                 return true;
371
372             case R.id.menu_settings:
373                 startActivity(new Intent(this, SettingsActivity.class));
374                 return true;
375         }
376
377         return super.onOptionsItemSelected(item);
378     }
379
380
381     private boolean getClockVisibility() {
382         return mClockLayout.getVisibility() == View.VISIBLE;
383     }
384
385     private void setClockVisibility(boolean visible) {
386         mClockLayout.setVisibility(visible ? View.VISIBLE : View.GONE);
387     }
388
389     private void saveClockVisibility() {
390         mPrefs.edit().putBoolean(PREF_SHOW_CLOCK, getClockVisibility()).commit();
391     }
392 }