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.database.Cursor; 26 import android.os.Bundle; 27 import android.view.ContextMenu; 28 import android.view.ContextMenu.ContextMenuInfo; 29 import android.view.LayoutInflater; 30 import android.view.Menu; 31 import android.view.MenuItem; 32 import android.view.View; 33 import android.view.View.OnClickListener; 34 import android.view.ViewGroup; 35 import android.widget.AdapterView; 36 import android.widget.AdapterView.AdapterContextMenuInfo; 37 import android.widget.AdapterView.OnItemClickListener; 38 import android.widget.CheckBox; 39 import android.widget.CursorAdapter; 40 import android.widget.ImageButton; 41 import android.widget.ListView; 42 import android.widget.TextView; 43 44 import java.util.Calendar; 45 46 /** 47 * AlarmClock application. 48 */ 49 public class AlarmClock extends Activity implements OnItemClickListener { 50 51 static final String PREFERENCES = "AlarmClock"; 52 53 /** This must be false for production. If true, turns on logging, 54 test code, etc. */ 55 static final boolean DEBUG = false; 56 57 private SharedPreferences mPrefs; 58 private LayoutInflater mFactory; 59 private ListView mAlarmsList; 60 private Cursor mCursor; 61 62 private void updateAlarm(boolean enabled, 63 Alarm alarm) { 64 Alarms.enableAlarm(this, alarm.id, enabled); 65 if (enabled) { 66 SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes, 67 alarm.daysOfWeek); 68 } 69 } 70 71 private class AlarmTimeAdapter extends CursorAdapter { 72 public AlarmTimeAdapter(Context context, Cursor cursor) { 73 super(context, cursor); 74 } 75 76 @Override 77 public View newView(Context context, Cursor cursor, ViewGroup parent) { 78 View ret = mFactory.inflate(R.layout.alarm_time, parent, false); 79 80 DigitalClock digitalClock = 81 (DigitalClock) ret.findViewById(R.id.digitalClock); 82 digitalClock.setLive(false); 83 return ret; 84 } 85 86 @Override 87 public void bindView(View view, Context context, Cursor cursor) { 88 final Alarm alarm = new Alarm(cursor); 89 90 View indicator = view.findViewById(R.id.indicator); 91 92 // Set the initial state of the clock "checkbox" 93 final CheckBox clockOnOff = 94 (CheckBox) indicator.findViewById(R.id.clock_onoff); 95 clockOnOff.setChecked(alarm.enabled); 96 97 // Clicking outside the "checkbox" should also change the state. 98 indicator.setOnClickListener(new OnClickListener() { 99 public void onClick(View v) { 100 clockOnOff.toggle(); 101 updateAlarm(clockOnOff.isChecked(), alarm); 102 } 103 }); 104 105 DigitalClock digitalClock = 106 (DigitalClock) view.findViewById(R.id.digitalClock); 107 108 // set the alarm text 109 final Calendar c = Calendar.getInstance(); 110 c.set(Calendar.HOUR_OF_DAY, alarm.hour); 111 c.set(Calendar.MINUTE, alarm.minutes); 112 digitalClock.updateTime(c); 113 114 // Set the repeat text or leave it blank if it does not repeat. 115 TextView daysOfWeekView = 116 (TextView) digitalClock.findViewById(R.id.daysOfWeek); 117 final String daysOfWeekStr = 118 alarm.daysOfWeek.toString(AlarmClock.this, false); 119 if (daysOfWeekStr != null && daysOfWeekStr.length() != 0) { 120 daysOfWeekView.setText(daysOfWeekStr); 121 daysOfWeekView.setVisibility(View.VISIBLE); 122 } else { 123 daysOfWeekView.setVisibility(View.GONE); 124 } 125 126 // Display the label 127 TextView labelView = 128 (TextView) view.findViewById(R.id.label); 129 if (alarm.label != null && alarm.label.length() != 0) { 130 labelView.setText(alarm.label); 131 labelView.setVisibility(View.VISIBLE); 132 } else { 133 labelView.setVisibility(View.GONE); 134 } 135 } 136 }; 137 138 @Override 139 public boolean onContextItemSelected(final MenuItem item) { 140 final AdapterContextMenuInfo info = 141 (AdapterContextMenuInfo) item.getMenuInfo(); 142 final int id = (int) info.id; 143 // Error check just in case. 144 if (id == -1) { 145 return super.onContextItemSelected(item); 146 } 147 switch (item.getItemId()) { 148 case R.id.delete_alarm: { 149 // Confirm that the alarm will be deleted. 150 new AlertDialog.Builder(this) 151 .setTitle(getString(R.string.delete_alarm)) 152 .setMessage(getString(R.string.delete_alarm_confirm)) 153 .setPositiveButton(android.R.string.ok, 154 new DialogInterface.OnClickListener() { 155 public void onClick(DialogInterface d, 156 int w) { 157 Alarms.deleteAlarm(AlarmClock.this, id); 158 } 159 }) 160 .setNegativeButton(android.R.string.cancel, null) 161 .show(); 162 return true; 163 } 164 165 case R.id.enable_alarm: { 166 final Cursor c = (Cursor) mAlarmsList.getAdapter() 167 .getItem(info.position); 168 final Alarm alarm = new Alarm(c); 169 Alarms.enableAlarm(this, alarm.id, !alarm.enabled); 170 if (!alarm.enabled) { 171 SetAlarm.popAlarmSetToast(this, alarm.hour, alarm.minutes, 172 alarm.daysOfWeek); 173 } 174 return true; 175 } 176 177 case R.id.edit_alarm: { 178 final Cursor c = (Cursor) mAlarmsList.getAdapter() 179 .getItem(info.position); 180 final Alarm alarm = new Alarm(c); 181 Intent intent = new Intent(this, SetAlarm.class); 182 intent.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm); 183 startActivity(intent); 184 return true; 185 } 186 187 default: 188 break; 189 } 190 return super.onContextItemSelected(item); 191 } 192 193 @Override 194 protected void onCreate(Bundle icicle) { 195 super.onCreate(icicle); 196 197 mFactory = LayoutInflater.from(this); 198 mPrefs = getSharedPreferences(PREFERENCES, 0); 199 mCursor = Alarms.getAlarmsCursor(getContentResolver()); 200 201 updateLayout(); 202 } 203 204 private void updateLayout() { 205 setContentView(R.layout.alarm_clock); 206 mAlarmsList = (ListView) findViewById(R.id.alarms_list); 207 AlarmTimeAdapter adapter = new AlarmTimeAdapter(this, mCursor); 208 mAlarmsList.setAdapter(adapter); 209 mAlarmsList.setVerticalScrollBarEnabled(true); 210 mAlarmsList.setOnItemClickListener(this); 211 mAlarmsList.setOnCreateContextMenuListener(this); 212 213 View addAlarm = findViewById(R.id.add_alarm); 214 addAlarm.setOnClickListener(new View.OnClickListener() { 215 public void onClick(View v) { 216 addNewAlarm(); 217 } 218 }); 219 // Make the entire view selected when focused. 220 addAlarm.setOnFocusChangeListener(new View.OnFocusChangeListener() { 221 public void onFocusChange(View v, boolean hasFocus) { 222 v.setSelected(hasFocus); 223 } 224 }); 225 View doneButton = findViewById(R.id.done); 226 if (doneButton != null) { 227 doneButton.setOnClickListener(new View.OnClickListener() { 228 public void onClick(View v) { 229 finish(); 230 } 231 }); 232 } 233 } 234 235 private void addNewAlarm() { 236 startActivity(new Intent(this, SetAlarm.class)); 237 } 238 239 @Override 240 protected void onDestroy() { 241 super.onDestroy(); 242 ToastMaster.cancelToast(); 243 if (mCursor != null) { 244 mCursor.close(); 245 } 246 } 247 248 @Override 249 public void onCreateContextMenu(ContextMenu menu, View view, 250 ContextMenuInfo menuInfo) { 251 // Inflate the menu from xml. 252 getMenuInflater().inflate(R.menu.context_menu, menu); 253 254 // Use the current item to create a custom view for the header. 255 final AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; 256 final Cursor c = 257 (Cursor) mAlarmsList.getAdapter().getItem(info.position); 258 final Alarm alarm = new Alarm(c); 259 260 // Construct the Calendar to compute the time. 261 final Calendar cal = Calendar.getInstance(); 262 cal.set(Calendar.HOUR_OF_DAY, alarm.hour); 263 cal.set(Calendar.MINUTE, alarm.minutes); 264 final String time = Alarms.formatTime(this, cal); 265 266 // Inflate the custom view and set each TextView's text. 267 final View v = mFactory.inflate(R.layout.context_menu_header, null); 268 TextView textView = (TextView) v.findViewById(R.id.header_time); 269 textView.setText(time); 270 textView = (TextView) v.findViewById(R.id.header_label); 271 textView.setText(alarm.label); 272 273 // Set the custom view on the menu. 274 menu.setHeaderView(v); 275 // Change the text based on the state of the alarm. 276 if (alarm.enabled) { 277 menu.findItem(R.id.enable_alarm).setTitle(R.string.disable_alarm); 278 } 279 } 280 281 @Override 282 public boolean onOptionsItemSelected(MenuItem item) { 283 switch (item.getItemId()) { 284 case R.id.menu_item_settings: 285 startActivity(new Intent(this, SettingsActivity.class)); 286 return true; 287 case R.id.menu_item_desk_clock: 288 startActivity(new Intent(this, DeskClock.class)); 289 finish(); 290 return true; 291 case R.id.menu_item_add_alarm: 292 addNewAlarm(); 293 return true; 294 case R.id.menu_item_done: 295 finish(); 296 return true; 297 default: 298 break; 299 } 300 return super.onOptionsItemSelected(item); 301 } 302 303 @Override 304 public boolean onCreateOptionsMenu(Menu menu) { 305 getMenuInflater().inflate(R.menu.alarm_list_menu, menu); 306 return super.onCreateOptionsMenu(menu); 307 } 308 309 @Override 310 public void onItemClick(AdapterView parent, View v, int pos, long id) { 311 final Cursor c = (Cursor) mAlarmsList.getAdapter() 312 .getItem(pos); 313 final Alarm alarm = new Alarm(c); 314 Intent intent = new Intent(this, SetAlarm.class); 315 intent.putExtra(Alarms.ALARM_INTENT_EXTRA, alarm); 316 startActivity(intent); 317 } 318 } 319