EventInfoActivity.java revision 98ab9de2fa5ad8dfd37faa6593dc66fa426d8960
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 17package com.android.calendar; 18 19import static android.provider.Calendar.EVENT_BEGIN_TIME; 20import static android.provider.Calendar.EVENT_END_TIME; 21import android.app.Activity; 22import android.content.ContentResolver; 23import android.content.ContentUris; 24import android.content.ContentValues; 25import android.content.Intent; 26import android.content.SharedPreferences; 27import android.content.res.Resources; 28import android.database.Cursor; 29import android.graphics.PorterDuff; 30import android.net.Uri; 31import android.os.Bundle; 32import android.pim.EventRecurrence; 33import android.preference.PreferenceManager; 34import android.provider.Calendar; 35import android.provider.Calendar.Attendees; 36import android.provider.Calendar.Calendars; 37import android.provider.Calendar.Events; 38import android.provider.Calendar.Reminders; 39import android.text.format.DateFormat; 40import android.text.format.DateUtils; 41import android.text.format.Time; 42import android.util.Log; 43import android.view.KeyEvent; 44import android.view.Menu; 45import android.view.MenuItem; 46import android.view.View; 47import android.widget.AdapterView; 48import android.widget.ArrayAdapter; 49import android.widget.ImageButton; 50import android.widget.LinearLayout; 51import android.widget.Spinner; 52import android.widget.TextView; 53import android.widget.Toast; 54 55import java.util.ArrayList; 56import java.util.Arrays; 57 58public class EventInfoActivity extends Activity implements View.OnClickListener, 59 AdapterView.OnItemSelectedListener { 60 private static final int MAX_REMINDERS = 5; 61 62 /** 63 * These are the corresponding indices into the array of strings 64 * "R.array.change_response_labels" in the resource file. 65 */ 66 static final int UPDATE_SINGLE = 0; 67 static final int UPDATE_ALL = 1; 68 69 private static final String[] EVENT_PROJECTION = new String[] { 70 Events._ID, // 0 do not remove; used in DeleteEventHelper 71 Events.TITLE, // 1 do not remove; used in DeleteEventHelper 72 Events.RRULE, // 2 do not remove; used in DeleteEventHelper 73 Events.ALL_DAY, // 3 do not remove; used in DeleteEventHelper 74 Events.CALENDAR_ID, // 4 do not remove; used in DeleteEventHelper 75 Events.DTSTART, // 5 do not remove; used in DeleteEventHelper 76 Events._SYNC_ID, // 6 do not remove; used in DeleteEventHelper 77 Events.EVENT_TIMEZONE, // 7 do not remove; used in DeleteEventHelper 78 Events.DESCRIPTION, // 8 79 Events.EVENT_LOCATION, // 9 80 Events.HAS_ALARM, // 10 81 Events.ACCESS_LEVEL, // 11 82 Events.COLOR, // 12 83 }; 84 private static final int EVENT_INDEX_ID = 0; 85 private static final int EVENT_INDEX_TITLE = 1; 86 private static final int EVENT_INDEX_RRULE = 2; 87 private static final int EVENT_INDEX_ALL_DAY = 3; 88 private static final int EVENT_INDEX_CALENDAR_ID = 4; 89 private static final int EVENT_INDEX_SYNC_ID = 6; 90 private static final int EVENT_INDEX_EVENT_TIMEZONE = 7; 91 private static final int EVENT_INDEX_DESCRIPTION = 8; 92 private static final int EVENT_INDEX_EVENT_LOCATION = 9; 93 private static final int EVENT_INDEX_HAS_ALARM = 10; 94 private static final int EVENT_INDEX_ACCESS_LEVEL = 11; 95 private static final int EVENT_INDEX_COLOR = 12; 96 97 private static final String[] ATTENDEES_PROJECTION = new String[] { 98 Attendees._ID, // 0 99 Attendees.ATTENDEE_RELATIONSHIP, // 1 100 Attendees.ATTENDEE_STATUS, // 2 101 }; 102 private static final int ATTENDEES_INDEX_ID = 0; 103 private static final int ATTENDEES_INDEX_RELATIONSHIP = 1; 104 private static final int ATTENDEES_INDEX_STATUS = 2; 105 private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=%d"; 106 107 static final String[] CALENDARS_PROJECTION = new String[] { 108 Calendars._ID, // 0 109 Calendars.DISPLAY_NAME, // 1 110 }; 111 static final int CALENDARS_INDEX_DISPLAY_NAME = 1; 112 static final String CALENDARS_WHERE = Calendars._ID + "=%d"; 113 114 private static final String[] REMINDERS_PROJECTION = new String[] { 115 Reminders._ID, // 0 116 Reminders.MINUTES, // 1 117 }; 118 private static final int REMINDERS_INDEX_MINUTES = 1; 119 private static final String REMINDERS_WHERE = Reminders.EVENT_ID + "=%d AND (" + 120 Reminders.METHOD + "=" + Reminders.METHOD_ALERT + " OR " + Reminders.METHOD + "=" + 121 Reminders.METHOD_DEFAULT + ")"; 122 123 private static final int MENU_GROUP_REMINDER = 1; 124 private static final int MENU_GROUP_EDIT = 2; 125 private static final int MENU_GROUP_DELETE = 3; 126 127 private static final int MENU_ADD_REMINDER = 1; 128 private static final int MENU_EDIT = 2; 129 private static final int MENU_DELETE = 3; 130 131 private static final int ATTENDEE_NO_RESPONSE = -1; 132 private static final int[] ATTENDEE_VALUES = { 133 ATTENDEE_NO_RESPONSE, 134 Attendees.ATTENDEE_STATUS_ACCEPTED, 135 Attendees.ATTENDEE_STATUS_TENTATIVE, 136 Attendees.ATTENDEE_STATUS_DECLINED, 137 }; 138 139 private LinearLayout mRemindersContainer; 140 141 private Uri mUri; 142 private long mEventId; 143 private Cursor mEventCursor; 144 private Cursor mAttendeesCursor; 145 private Cursor mCalendarsCursor; 146 147 private long mStartMillis; 148 private long mEndMillis; 149 private int mVisibility = Calendars.NO_ACCESS; 150 private int mRelationship = Attendees.RELATIONSHIP_ORGANIZER; 151 152 private ArrayList<Integer> mOriginalMinutes = new ArrayList<Integer>(); 153 private ArrayList<LinearLayout> mReminderItems = new ArrayList<LinearLayout>(0); 154 private ArrayList<Integer> mReminderValues; 155 private ArrayList<String> mReminderLabels; 156 private int mDefaultReminderMinutes; 157 158 private DeleteEventHelper mDeleteEventHelper; 159 private EditResponseHelper mEditResponseHelper; 160 161 private int mResponseOffset; 162 private int mOriginalAttendeeResponse; 163 private boolean mIsRepeating; 164 165 // This is called when one of the "remove reminder" buttons is selected. 166 public void onClick(View v) { 167 LinearLayout reminderItem = (LinearLayout) v.getParent(); 168 LinearLayout parent = (LinearLayout) reminderItem.getParent(); 169 parent.removeView(reminderItem); 170 mReminderItems.remove(reminderItem); 171 updateRemindersVisibility(); 172 } 173 174 public void onItemSelected(AdapterView parent, View v, int position, long id) { 175 // If they selected the "No response" option, then don't display the 176 // dialog asking which events to change. 177 if (id == 0 && mResponseOffset == 0) { 178 return; 179 } 180 181 // If this is not a repeating event, then don't display the dialog 182 // asking which events to change. 183 if (!mIsRepeating) { 184 return; 185 } 186 187 // If the selection is the same as the original, then don't display the 188 // dialog asking which events to change. 189 int index = findResponseIndexFor(mOriginalAttendeeResponse); 190 if (position == index + mResponseOffset) { 191 return; 192 } 193 194 // This is a repeating event. We need to ask the user if they mean to 195 // change just this one instance or all instances. 196 mEditResponseHelper.showDialog(mEditResponseHelper.getWhichEvents()); 197 } 198 199 public void onNothingSelected(AdapterView parent) { 200 } 201 202 @Override 203 protected void onCreate(Bundle icicle) { 204 super.onCreate(icicle); 205 206 // Event cursor 207 Intent intent = getIntent(); 208 mUri = intent.getData(); 209 ContentResolver cr = getContentResolver(); 210 mStartMillis = intent.getLongExtra(EVENT_BEGIN_TIME, 0); 211 mEndMillis = intent.getLongExtra(EVENT_END_TIME, 0); 212 mEventCursor = managedQuery(mUri, EVENT_PROJECTION, null, null); 213 if (initEventCursor()) { 214 // The cursor is empty. This can happen if the event was deleted. 215 finish(); 216 return; 217 } 218 219 setContentView(R.layout.event_info_activity); 220 221 // Attendees cursor 222 Uri uri = Attendees.CONTENT_URI; 223 String where = String.format(ATTENDEES_WHERE, mEventId); 224 mAttendeesCursor = managedQuery(uri, ATTENDEES_PROJECTION, where, null); 225 initAttendeesCursor(); 226 227 // Calendars cursor 228 uri = Calendars.CONTENT_URI; 229 where = String.format(CALENDARS_WHERE, mEventCursor.getLong(EVENT_INDEX_CALENDAR_ID)); 230 mCalendarsCursor = managedQuery(uri, CALENDARS_PROJECTION, where, null); 231 initCalendarsCursor(); 232 233 Resources res = getResources(); 234 235 if (mVisibility >= Calendars.CONTRIBUTOR_ACCESS && 236 mRelationship == Attendees.RELATIONSHIP_ATTENDEE) { 237 setTitle(res.getString(R.string.event_info_title_invite)); 238 } else { 239 setTitle(res.getString(R.string.event_info_title)); 240 } 241 242 // Initialize the reminder values array. 243 Resources r = getResources(); 244 String[] strings = r.getStringArray(R.array.reminder_minutes_values); 245 int size = strings.length; 246 ArrayList<Integer> list = new ArrayList<Integer>(size); 247 for (int i = 0 ; i < size ; i++) { 248 list.add(Integer.parseInt(strings[i])); 249 } 250 mReminderValues = list; 251 String[] labels = r.getStringArray(R.array.reminder_minutes_labels); 252 mReminderLabels = new ArrayList<String>(Arrays.asList(labels)); 253 254 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 255 String durationString = 256 prefs.getString(CalendarPreferenceActivity.KEY_DEFAULT_REMINDER, "0"); 257 mDefaultReminderMinutes = Integer.parseInt(durationString); 258 259 mRemindersContainer = (LinearLayout) findViewById(R.id.reminder_items_container); 260 261 // Reminders cursor 262 boolean hasAlarm = mEventCursor.getInt(EVENT_INDEX_HAS_ALARM) != 0; 263 if (hasAlarm) { 264 uri = Reminders.CONTENT_URI; 265 where = String.format(REMINDERS_WHERE, mEventId); 266 Cursor reminderCursor = cr.query(uri, REMINDERS_PROJECTION, where, null, null); 267 try { 268 // First pass: collect all the custom reminder minutes (e.g., 269 // a reminder of 8 minutes) into a global list. 270 while (reminderCursor.moveToNext()) { 271 int minutes = reminderCursor.getInt(REMINDERS_INDEX_MINUTES); 272 EditEvent.addMinutesToList(this, mReminderValues, mReminderLabels, minutes); 273 } 274 275 // Second pass: create the reminder spinners 276 reminderCursor.moveToPosition(-1); 277 while (reminderCursor.moveToNext()) { 278 int minutes = reminderCursor.getInt(REMINDERS_INDEX_MINUTES); 279 mOriginalMinutes.add(minutes); 280 EditEvent.addReminder(this, this, mReminderItems, mReminderValues, 281 mReminderLabels, minutes); 282 } 283 } finally { 284 reminderCursor.close(); 285 } 286 } 287 288 updateView(); 289 updateRemindersVisibility(); 290 291 // Setup the + Add Reminder Button 292 View.OnClickListener addReminderOnClickListener = new View.OnClickListener() { 293 public void onClick(View v) { 294 addReminder(); 295 } 296 }; 297 ImageButton reminderRemoveButton = (ImageButton) findViewById(R.id.reminder_add); 298 reminderRemoveButton.setOnClickListener(addReminderOnClickListener); 299 300 mDeleteEventHelper = new DeleteEventHelper(this, true /* exit when done */); 301 mEditResponseHelper = new EditResponseHelper(this); 302 } 303 304 @Override 305 protected void onResume() { 306 super.onResume(); 307 if (initEventCursor()) { 308 // The cursor is empty. This can happen if the event was deleted. 309 finish(); 310 return; 311 } 312 initAttendeesCursor(); 313 initCalendarsCursor(); 314 } 315 316 /** 317 * Initializes the event cursor, which is expected to point to the first 318 * (and only) result from a query. 319 * @return true if the cursor is empty. 320 */ 321 private boolean initEventCursor() { 322 if ((mEventCursor == null) || (mEventCursor.getCount() == 0)) { 323 return true; 324 } 325 mEventCursor.moveToFirst(); 326 mVisibility = mEventCursor.getInt(EVENT_INDEX_ACCESS_LEVEL); 327 mEventId = mEventCursor.getInt(EVENT_INDEX_ID); 328 String rRule = mEventCursor.getString(EVENT_INDEX_RRULE); 329 mIsRepeating = (rRule != null); 330 return false; 331 } 332 333 private void initAttendeesCursor() { 334 if (mAttendeesCursor != null) { 335 if (mAttendeesCursor.moveToFirst()) { 336 mRelationship = mAttendeesCursor.getInt(ATTENDEES_INDEX_RELATIONSHIP); 337 } 338 } 339 } 340 341 private void initCalendarsCursor() { 342 if (mCalendarsCursor != null) { 343 mCalendarsCursor.moveToFirst(); 344 } 345 } 346 347 @Override 348 public void onPause() { 349 super.onPause(); 350 if (!isFinishing()) { 351 return; 352 } 353 ContentResolver cr = getContentResolver(); 354 ArrayList<Integer> reminderMinutes = EditEvent.reminderItemsToMinutes(mReminderItems, 355 mReminderValues); 356 boolean changed = EditEvent.saveReminders(cr, mEventId, reminderMinutes, mOriginalMinutes, 357 false /* no force save */); 358 changed |= saveResponse(cr); 359 if (changed) { 360 Toast.makeText(this, R.string.saving_event, Toast.LENGTH_SHORT).show(); 361 } 362 } 363 364 @Override 365 public boolean onCreateOptionsMenu(Menu menu) { 366 MenuItem item; 367 item = menu.add(MENU_GROUP_REMINDER, MENU_ADD_REMINDER, 0, 368 R.string.add_new_reminder); 369 item.setIcon(R.drawable.ic_menu_reminder); 370 item.setAlphabeticShortcut('r'); 371 372 item = menu.add(MENU_GROUP_EDIT, MENU_EDIT, 0, R.string.edit_event_label); 373 item.setIcon(android.R.drawable.ic_menu_edit); 374 item.setAlphabeticShortcut('e'); 375 376 item = menu.add(MENU_GROUP_DELETE, MENU_DELETE, 0, R.string.delete_event_label); 377 item.setIcon(android.R.drawable.ic_menu_delete); 378 379 return super.onCreateOptionsMenu(menu); 380 } 381 382 @Override 383 public boolean onPrepareOptionsMenu(Menu menu) { 384 // Cannot add reminders to a shared calendar with only free/busy 385 // permissions 386 if (mVisibility >= Calendars.READ_ACCESS && mReminderItems.size() < MAX_REMINDERS) { 387 menu.setGroupVisible(MENU_GROUP_REMINDER, true); 388 menu.setGroupEnabled(MENU_GROUP_REMINDER, true); 389 } else { 390 menu.setGroupVisible(MENU_GROUP_REMINDER, false); 391 menu.setGroupEnabled(MENU_GROUP_REMINDER, false); 392 } 393 394 if (mVisibility >= Calendars.CONTRIBUTOR_ACCESS && 395 mRelationship >= Attendees.RELATIONSHIP_ORGANIZER) { 396 menu.setGroupVisible(MENU_GROUP_EDIT, true); 397 menu.setGroupEnabled(MENU_GROUP_EDIT, true); 398 menu.setGroupVisible(MENU_GROUP_DELETE, true); 399 menu.setGroupEnabled(MENU_GROUP_DELETE, true); 400 } else { 401 menu.setGroupVisible(MENU_GROUP_EDIT, false); 402 menu.setGroupEnabled(MENU_GROUP_EDIT, false); 403 menu.setGroupVisible(MENU_GROUP_DELETE, false); 404 menu.setGroupEnabled(MENU_GROUP_DELETE, false); 405 } 406 407 return super.onPrepareOptionsMenu(menu); 408 } 409 410 private void addReminder() { 411 // TODO: when adding a new reminder, make it different from the 412 // last one in the list (if any). 413 if (mDefaultReminderMinutes == 0) { 414 EditEvent.addReminder(this, this, mReminderItems, 415 mReminderValues, mReminderLabels, 10 /* minutes */); 416 } else { 417 EditEvent.addReminder(this, this, mReminderItems, 418 mReminderValues, mReminderLabels, mDefaultReminderMinutes); 419 } 420 updateRemindersVisibility(); 421 } 422 423 @Override 424 public boolean onOptionsItemSelected(MenuItem item) { 425 super.onOptionsItemSelected(item); 426 switch (item.getItemId()) { 427 case MENU_ADD_REMINDER: 428 addReminder(); 429 break; 430 case MENU_EDIT: 431 doEdit(); 432 break; 433 case MENU_DELETE: 434 doDelete(); 435 break; 436 } 437 return true; 438 } 439 440 @Override 441 public boolean onKeyDown(int keyCode, KeyEvent event) { 442 if (keyCode == KeyEvent.KEYCODE_DEL) { 443 doDelete(); 444 return true; 445 } 446 return super.onKeyDown(keyCode, event); 447 } 448 449 private void updateRemindersVisibility() { 450 if (mReminderItems.size() == 0) { 451 mRemindersContainer.setVisibility(View.GONE); 452 } else { 453 mRemindersContainer.setVisibility(View.VISIBLE); 454 } 455 } 456 457 /** 458 * Saves the response to an invitation if the user changed the response. 459 * Returns true if the database was updated. 460 * 461 * @param cr the ContentResolver 462 * @return true if the database was changed 463 */ 464 private boolean saveResponse(ContentResolver cr) { 465 if (mAttendeesCursor == null || mEventCursor == null) { 466 return false; 467 } 468 Spinner spinner = (Spinner) findViewById(R.id.response_value); 469 int position = spinner.getSelectedItemPosition() - mResponseOffset; 470 if (position <= 0) { 471 return false; 472 } 473 474 int status = ATTENDEE_VALUES[position]; 475 476 // If the status has not changed, then don't update the database 477 if (status == mOriginalAttendeeResponse) { 478 return false; 479 } 480 481 long attendeeId = mAttendeesCursor.getInt(ATTENDEES_INDEX_ID); 482 if (!mIsRepeating) { 483 // This is a non-repeating event 484 updateResponse(cr, mEventId, attendeeId, status); 485 return true; 486 } 487 488 // This is a repeating event 489 int whichEvents = mEditResponseHelper.getWhichEvents(); 490 switch (whichEvents) { 491 case -1: 492 return false; 493 case UPDATE_SINGLE: 494 createExceptionResponse(cr, mEventId, attendeeId, status); 495 return true; 496 case UPDATE_ALL: 497 updateResponse(cr, mEventId, attendeeId, status); 498 return true; 499 default: 500 Log.e("Calendar", "Unexpected choice for updating invitation response"); 501 break; 502 } 503 return false; 504 } 505 506 private void updateResponse(ContentResolver cr, long eventId, long attendeeId, int status) { 507 // Update the "selfAttendeeStatus" field for the event 508 ContentValues values = new ContentValues(); 509 510 // Will need to add email when MULTIPLE_ATTENDEES_PER_EVENT supported. 511 values.put(Attendees.ATTENDEE_STATUS, status); 512 values.put(Attendees.EVENT_ID, eventId); 513 514 Uri uri = ContentUris.withAppendedId(Attendees.CONTENT_URI, attendeeId); 515 cr.update(uri, values, null /* where */, null /* selection args */); 516 } 517 518 private void createExceptionResponse(ContentResolver cr, long eventId, 519 long attendeeId, int status) { 520 // Fetch information about the repeating event. 521 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId); 522 Cursor cursor = cr.query(uri, EVENT_PROJECTION, null, null, null); 523 if (cursor == null) { 524 return; 525 } 526 527 try { 528 cursor.moveToFirst(); 529 ContentValues values = new ContentValues(); 530 531 String title = cursor.getString(EVENT_INDEX_TITLE); 532 String timezone = cursor.getString(EVENT_INDEX_EVENT_TIMEZONE); 533 int calendarId = cursor.getInt(EVENT_INDEX_CALENDAR_ID); 534 boolean allDay = cursor.getInt(EVENT_INDEX_ALL_DAY) != 0; 535 String syncId = cursor.getString(EVENT_INDEX_SYNC_ID); 536 537 values.put(Events.TITLE, title); 538 values.put(Events.EVENT_TIMEZONE, timezone); 539 values.put(Events.ALL_DAY, allDay ? 1 : 0); 540 values.put(Events.CALENDAR_ID, calendarId); 541 values.put(Events.DTSTART, mStartMillis); 542 values.put(Events.DTEND, mEndMillis); 543 values.put(Events.ORIGINAL_EVENT, syncId); 544 values.put(Events.ORIGINAL_INSTANCE_TIME, mStartMillis); 545 values.put(Events.ORIGINAL_ALL_DAY, allDay ? 1 : 0); 546 values.put(Events.STATUS, Events.STATUS_CONFIRMED); 547 values.put(Events.SELF_ATTENDEE_STATUS, status); 548 549 // Create a recurrence exception 550 cr.insert(Events.CONTENT_URI, values); 551 } finally { 552 cursor.close(); 553 } 554 } 555 556 private int findResponseIndexFor(int response) { 557 int size = ATTENDEE_VALUES.length; 558 for (int index = 0; index < size; index++) { 559 if (ATTENDEE_VALUES[index] == response) { 560 return index; 561 } 562 } 563 return 0; 564 } 565 566 private void doEdit() { 567 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventId); 568 Intent intent = new Intent(Intent.ACTION_EDIT, uri); 569 intent.putExtra(Calendar.EVENT_BEGIN_TIME, mStartMillis); 570 intent.putExtra(Calendar.EVENT_END_TIME, mEndMillis); 571 intent.setClass(EventInfoActivity.this, EditEvent.class); 572 startActivity(intent); 573 finish(); 574 } 575 576 private void doDelete() { 577 mDeleteEventHelper.delete(mStartMillis, mEndMillis, mEventCursor, -1); 578 } 579 580 private void updateView() { 581 if (mEventCursor == null) { 582 return; 583 } 584 Resources res = getResources(); 585 586 String eventName = mEventCursor.getString(EVENT_INDEX_TITLE); 587 if (eventName == null || eventName.length() == 0) { 588 eventName = res.getString(R.string.no_title_label); 589 } 590 591 boolean allDay = mEventCursor.getInt(EVENT_INDEX_ALL_DAY) != 0; 592 String location = mEventCursor.getString(EVENT_INDEX_EVENT_LOCATION); 593 String description = mEventCursor.getString(EVENT_INDEX_DESCRIPTION); 594 String rRule = mEventCursor.getString(EVENT_INDEX_RRULE); 595 boolean hasAlarm = mEventCursor.getInt(EVENT_INDEX_HAS_ALARM) != 0; 596 String eventTimezone = mEventCursor.getString(EVENT_INDEX_EVENT_TIMEZONE); 597 int color = mEventCursor.getInt(EVENT_INDEX_COLOR) & 0xbbffffff; 598 599 View calBackground = findViewById(R.id.cal_background); 600 calBackground.setBackgroundColor(color); 601 602 TextView title = (TextView) findViewById(R.id.title); 603 title.setTextColor(color); 604 605 View divider = (View) findViewById(R.id.divider); 606 divider.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN); 607 608 // What 609 if (eventName != null) { 610 setTextCommon(R.id.title, eventName); 611 } 612 613 // When 614 String when; 615 int flags; 616 if (allDay) { 617 flags = DateUtils.FORMAT_UTC | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_SHOW_DATE; 618 } else { 619 flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE; 620 if (DateFormat.is24HourFormat(this)) { 621 flags |= DateUtils.FORMAT_24HOUR; 622 } 623 } 624 when = DateUtils.formatDateRange(this, mStartMillis, mEndMillis, flags); 625 setTextCommon(R.id.when, when); 626 627 // Show the event timezone if it is different from the local timezone 628 Time time = new Time(); 629 String localTimezone = time.timezone; 630 if (allDay) { 631 localTimezone = Time.TIMEZONE_UTC; 632 } 633 if (eventTimezone != null && !localTimezone.equals(eventTimezone) && !allDay) { 634 setTextCommon(R.id.timezone, localTimezone); 635 } else { 636 setVisibilityCommon(R.id.timezone_container, View.GONE); 637 } 638 639 // Repeat 640 if (rRule != null) { 641 EventRecurrence eventRecurrence = new EventRecurrence(); 642 eventRecurrence.parse(rRule); 643 Time date = new Time(); 644 if (allDay) { 645 date.timezone = Time.TIMEZONE_UTC; 646 } 647 date.set(mStartMillis); 648 eventRecurrence.setStartDate(date); 649 String repeatString = eventRecurrence.getRepeatString(); 650 setTextCommon(R.id.repeat, repeatString); 651 } else { 652 setVisibilityCommon(R.id.repeat_container, View.GONE); 653 } 654 655 // Where 656 if (location == null || location.length() == 0) { 657 setVisibilityCommon(R.id.where, View.GONE); 658 } else { 659 setTextCommon(R.id.where, location); 660 } 661 662 // Description 663 if (description == null || description.length() == 0) { 664 setVisibilityCommon(R.id.description, View.GONE); 665 } else { 666 setTextCommon(R.id.description, description); 667 } 668 669 // Calendar 670 if (mCalendarsCursor != null) { 671 mCalendarsCursor.moveToFirst(); 672 String calendarName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME); 673 setTextCommon(R.id.calendar, calendarName); 674 } else { 675 setVisibilityCommon(R.id.calendar_container, View.GONE); 676 } 677 678 // Response 679 updateResponse(); 680 } 681 682 void updateResponse() { 683 if (mVisibility < Calendars.CONTRIBUTOR_ACCESS || 684 mRelationship != Attendees.RELATIONSHIP_ATTENDEE) { 685 setVisibilityCommon(R.id.response_container, View.GONE); 686 return; 687 } 688 689 setVisibilityCommon(R.id.response_container, View.VISIBLE); 690 691 Spinner spinner = (Spinner) findViewById(R.id.response_value); 692 693 mOriginalAttendeeResponse = ATTENDEE_NO_RESPONSE; 694 if (mAttendeesCursor != null) { 695 mOriginalAttendeeResponse = mAttendeesCursor.getInt(ATTENDEES_INDEX_STATUS); 696 } 697 mResponseOffset = 0; 698 699 /* If the user has previously responded to this event 700 * we should not allow them to select no response again. 701 * Switch the entries to a set of entries without the 702 * no response option. 703 */ 704 if ((mOriginalAttendeeResponse != Attendees.ATTENDEE_STATUS_INVITED) 705 && (mOriginalAttendeeResponse != ATTENDEE_NO_RESPONSE) 706 && (mOriginalAttendeeResponse != Attendees.ATTENDEE_STATUS_NONE)) { 707 CharSequence[] entries; 708 entries = getResources().getTextArray(R.array.response_labels2); 709 mResponseOffset = -1; 710 ArrayAdapter<CharSequence> adapter = 711 new ArrayAdapter<CharSequence>(this, 712 android.R.layout.simple_spinner_item, entries); 713 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 714 spinner.setAdapter(adapter); 715 } 716 717 int index = findResponseIndexFor(mOriginalAttendeeResponse); 718 spinner.setSelection(index + mResponseOffset); 719 spinner.setOnItemSelectedListener(this); 720 } 721 722 private void setTextCommon(int id, CharSequence text) { 723 TextView textView = (TextView) findViewById(id); 724 if (textView == null) 725 return; 726 textView.setText(text); 727 } 728 729 private void setVisibilityCommon(int id, int visibility) { 730 View v = findViewById(id); 731 if (v != null) { 732 v.setVisibility(visibility); 733 } 734 return; 735 } 736} 737