OSDN Git Service

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