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