EditEventFragment.java revision c250e2eae5156fdc5233b7f1d319ee81dfc1cbd9
1/* 2 * Copyright (C) 2010 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.event; 18 19import android.app.Activity; 20import android.app.AlertDialog; 21import android.app.Fragment; 22import android.content.AsyncQueryHandler; 23import android.content.ContentProviderOperation; 24import android.content.ContentResolver; 25import android.content.ContentUris; 26import android.content.ContentValues; 27import android.content.Context; 28import android.content.DialogInterface; 29import android.content.DialogInterface.OnClickListener; 30import android.content.Intent; 31import android.database.Cursor; 32import android.database.MatrixCursor; 33import android.net.Uri; 34import android.os.Bundle; 35import android.provider.Calendar.Attendees; 36import android.provider.Calendar.Calendars; 37import android.provider.Calendar.Events; 38import android.provider.Calendar.Reminders; 39import android.text.TextUtils; 40import android.util.Log; 41import android.view.LayoutInflater; 42import android.view.Menu; 43import android.view.MenuInflater; 44import android.view.MenuItem; 45import android.view.View; 46import android.view.ViewGroup; 47import android.view.inputmethod.InputMethodManager; 48import android.widget.Toast; 49 50import com.android.calendar.AsyncQueryService; 51import com.android.calendar.CalendarController; 52import com.android.calendar.CalendarController.EventHandler; 53import com.android.calendar.CalendarController.EventInfo; 54import com.android.calendar.CalendarController.EventType; 55import com.android.calendar.CalendarEventModel; 56import com.android.calendar.CalendarEventModel.Attendee; 57import com.android.calendar.CalendarEventModel.ReminderEntry; 58import com.android.calendar.DeleteEventHelper; 59import com.android.calendar.R; 60import com.android.calendar.Utils; 61 62import java.io.Serializable; 63import java.util.ArrayList; 64import java.util.Collections; 65 66public class EditEventFragment extends Fragment implements EventHandler { 67 private static final String TAG = "EditEventActivity"; 68 69 private static final String BUNDLE_KEY_MODEL = "key_model"; 70 private static final String BUNDLE_KEY_EDIT_STATE = "key_edit_state"; 71 private static final String BUNDLE_KEY_EVENT = "key_event"; 72 private static final String BUNDLE_KEY_READ_ONLY = "key_read_only"; 73 74 private static final boolean DEBUG = false; 75 76 private static final int TOKEN_EVENT = 1; 77 private static final int TOKEN_ATTENDEES = 1 << 1; 78 private static final int TOKEN_REMINDERS = 1 << 2; 79 private static final int TOKEN_CALENDARS = 1 << 3; 80 private static final int TOKEN_ALL = TOKEN_EVENT | TOKEN_ATTENDEES | TOKEN_REMINDERS 81 | TOKEN_CALENDARS; 82 private static final int TOKEN_UNITIALIZED = 1 << 31; 83 84 /** 85 * A bitfield of TOKEN_* to keep track which query hasn't been completed 86 * yet. Once all queries have returned, the model can be applied to the 87 * view. 88 */ 89 private int mOutstandingQueries = TOKEN_UNITIALIZED; 90 91 EditEventHelper mHelper; 92 CalendarEventModel mModel; 93 CalendarEventModel mOriginalModel; 94 CalendarEventModel mRestoreModel; 95 EditEventView mView; 96 QueryHandler mHandler; 97 98 private AlertDialog mModifyDialog; 99 int mModification = Utils.MODIFY_UNINITIALIZED; 100 101 private EventInfo mEvent; 102 private EventBundle mEventBundle; 103 private Uri mUri; 104 private long mBegin; 105 private long mEnd; 106 107 private Activity mContext; 108 private Done mOnDone = new Done(); 109 private Menu mMenu; 110 111 private boolean mSaveOnDetach = true; 112 private boolean mIsReadOnly = false; 113 public boolean mShowModifyDialogOnLaunch = false; 114 115 private InputMethodManager mInputMethodManager; 116 117 private Intent mIntent; 118 119 // TODO turn this into a helper function in EditEventHelper for building the 120 // model 121 private class QueryHandler extends AsyncQueryHandler { 122 public QueryHandler(ContentResolver cr) { 123 super(cr); 124 } 125 126 @Override 127 protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 128 // If the query didn't return a cursor for some reason return 129 if (cursor == null) { 130 return; 131 } 132 133 // If the Activity is finishing, then close the cursor. 134 // Otherwise, use the new cursor in the adapter. 135 final Activity activity = EditEventFragment.this.getActivity(); 136 if (activity == null || activity.isFinishing()) { 137 cursor.close(); 138 return; 139 } 140 long eventId; 141 switch (token) { 142 case TOKEN_EVENT: 143 if (cursor.getCount() == 0) { 144 // The cursor is empty. This can happen if the event 145 // was deleted. 146 cursor.close(); 147 mOnDone.setDoneCode(Utils.DONE_EXIT); 148 mOnDone.run(); 149 return; 150 } 151 mOriginalModel = new CalendarEventModel(); 152 EditEventHelper.setModelFromCursor(mOriginalModel, cursor); 153 EditEventHelper.setModelFromCursor(mModel, cursor); 154 cursor.close(); 155 156 mOriginalModel.mUri = mUri.toString(); 157 158 mModel.mUri = mUri.toString(); 159 mModel.mOriginalStart = mBegin; 160 mModel.mOriginalEnd = mEnd; 161 mModel.mIsFirstEventInSeries = mBegin == mOriginalModel.mStart; 162 mModel.mStart = mBegin; 163 mModel.mEnd = mEnd; 164 165 eventId = mModel.mId; 166 167 // TOKEN_ATTENDEES 168 if (mModel.mHasAttendeeData && eventId != -1) { 169 Uri attUri = Attendees.CONTENT_URI; 170 String[] whereArgs = { 171 Long.toString(eventId) 172 }; 173 mHandler.startQuery(TOKEN_ATTENDEES, null, attUri, 174 EditEventHelper.ATTENDEES_PROJECTION, 175 EditEventHelper.ATTENDEES_WHERE /* selection */, 176 whereArgs /* selection args */, null /* sort order */); 177 } else { 178 setModelIfDone(TOKEN_ATTENDEES); 179 } 180 181 // TOKEN_REMINDERS 182 if (mModel.mHasAlarm) { 183 Uri rUri = Reminders.CONTENT_URI; 184 String[] remArgs = { 185 Long.toString(eventId) 186 }; 187 mHandler.startQuery(TOKEN_REMINDERS, null, rUri, 188 EditEventHelper.REMINDERS_PROJECTION, 189 EditEventHelper.REMINDERS_WHERE /* selection */, 190 remArgs /* selection args */, null /* sort order */); 191 } else { 192 setModelIfDone(TOKEN_REMINDERS); 193 } 194 195 // TOKEN_CALENDARS 196 String[] selArgs = { 197 Long.toString(mModel.mCalendarId) 198 }; 199 mHandler.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI, 200 EditEventHelper.CALENDARS_PROJECTION, EditEventHelper.CALENDARS_WHERE, 201 selArgs /* selection args */, null /* sort order */); 202 203 setModelIfDone(TOKEN_EVENT); 204 break; 205 case TOKEN_ATTENDEES: 206 try { 207 while (cursor.moveToNext()) { 208 String name = cursor.getString(EditEventHelper.ATTENDEES_INDEX_NAME); 209 String email = cursor.getString(EditEventHelper.ATTENDEES_INDEX_EMAIL); 210 int status = cursor.getInt(EditEventHelper.ATTENDEES_INDEX_STATUS); 211 int relationship = cursor 212 .getInt(EditEventHelper.ATTENDEES_INDEX_RELATIONSHIP); 213 if (relationship == Attendees.RELATIONSHIP_ORGANIZER) { 214 if (email != null) { 215 mModel.mOrganizer = email; 216 mModel.mIsOrganizer = mModel.mOwnerAccount 217 .equalsIgnoreCase(email); 218 mOriginalModel.mOrganizer = email; 219 mOriginalModel.mIsOrganizer = mOriginalModel.mOwnerAccount 220 .equalsIgnoreCase(email); 221 } 222 223 if (TextUtils.isEmpty(name)) { 224 mModel.mOrganizerDisplayName = mModel.mOrganizer; 225 mOriginalModel.mOrganizerDisplayName = 226 mOriginalModel.mOrganizer; 227 } else { 228 mModel.mOrganizerDisplayName = name; 229 mOriginalModel.mOrganizerDisplayName = name; 230 } 231 } 232 233 if (email != null) { 234 if (mModel.mOwnerAccount != null && 235 mModel.mOwnerAccount.equalsIgnoreCase(email)) { 236 int attendeeId = 237 cursor.getInt(EditEventHelper.ATTENDEES_INDEX_ID); 238 mModel.mOwnerAttendeeId = attendeeId; 239 mModel.mSelfAttendeeStatus = status; 240 mOriginalModel.mOwnerAttendeeId = attendeeId; 241 mOriginalModel.mSelfAttendeeStatus = status; 242 continue; 243 } 244 } 245 Attendee attendee = new Attendee(name, email); 246 attendee.mStatus = status; 247 mModel.addAttendee(attendee); 248 mOriginalModel.addAttendee(attendee); 249 } 250 } finally { 251 cursor.close(); 252 } 253 254 setModelIfDone(TOKEN_ATTENDEES); 255 break; 256 case TOKEN_REMINDERS: 257 try { 258 // Add all reminders to the models 259 while (cursor.moveToNext()) { 260 int minutes = cursor.getInt(EditEventHelper.REMINDERS_INDEX_MINUTES); 261 int method = cursor.getInt(EditEventHelper.REMINDERS_INDEX_METHOD); 262 ReminderEntry re = ReminderEntry.valueOf(minutes, method); 263 mModel.mReminders.add(re); 264 mOriginalModel.mReminders.add(re); 265 } 266 267 // Sort appropriately for display 268 Collections.sort(mModel.mReminders); 269 Collections.sort(mOriginalModel.mReminders); 270 } finally { 271 cursor.close(); 272 } 273 274 setModelIfDone(TOKEN_REMINDERS); 275 break; 276 case TOKEN_CALENDARS: 277 try { 278 if (mModel.mCalendarId == -1) { 279 // Populate Calendar spinner only if no calendar is set e.g. new event 280 MatrixCursor matrixCursor = Utils.matrixCursorFromCursor(cursor); 281 if (DEBUG) { 282 Log.d(TAG, "onQueryComplete: setting cursor with " 283 + matrixCursor.getCount() + " calendars"); 284 } 285 mView.setCalendarsCursor(matrixCursor, isAdded() && isResumed()); 286 } else { 287 // Populate model for an existing event 288 EditEventHelper.setModelFromCalendarCursor(mModel, cursor); 289 EditEventHelper.setModelFromCalendarCursor(mOriginalModel, cursor); 290 } 291 } finally { 292 cursor.close(); 293 } 294 295 setModelIfDone(TOKEN_CALENDARS); 296 break; 297 } 298 } 299 } 300 301 private void setModelIfDone(int queryType) { 302 synchronized (this) { 303 mOutstandingQueries &= ~queryType; 304 if (mOutstandingQueries == 0) { 305 if (mRestoreModel != null) { 306 mModel = mRestoreModel; 307 } 308 if (mShowModifyDialogOnLaunch && mModification == Utils.MODIFY_UNINITIALIZED) { 309 if (!TextUtils.isEmpty(mModel.mRrule)) { 310 displayEditWhichDialog(); 311 } else { 312 mModification = Utils.MODIFY_ALL; 313 } 314 315 } 316 mView.setModel(mModel); 317 mView.setModification(mModification); 318 if (mMenu != null) { 319 updateActionBar(); 320 } 321 } 322 } 323 } 324 325 private void updateActionBar() { 326 if (mMenu == null) { 327 return; 328 } 329 MenuItem cancelItem = mMenu.findItem(R.id.action_cancel); 330 MenuItem deleteItem = mMenu.findItem(R.id.action_delete); 331 MenuItem editItem = mMenu.findItem(R.id.action_edit); 332 boolean canModifyEvent = EditEventHelper.canModifyEvent(mModel); 333 boolean canModifyCalendar = EditEventHelper.canModifyCalendar(mModel); 334 335 if (canModifyCalendar && mModel.mUri != null) { 336 deleteItem.setVisible(true); 337 } else { 338 deleteItem.setVisible(false); 339 } 340 if (mIsReadOnly) { 341 mMenu.findItem(R.id.action_done).setVisible(false); 342 } 343 if (mModification == Utils.MODIFY_UNINITIALIZED) { 344 cancelItem.setVisible(false); 345 if (canModifyEvent) { 346 editItem.setVisible(true); 347 } else { 348 editItem.setVisible(false); 349 } 350 return; 351 } else { 352 editItem.setVisible(false); 353 } 354 boolean canRespond = EditEventHelper.canRespond(mModel); 355 356 if (canRespond || canModifyEvent) { 357 cancelItem.setVisible(true); 358 } else { 359 cancelItem.setVisible(false); 360 } 361 } 362 363 public EditEventFragment() { 364 this(null, false, null); 365 } 366 367 public EditEventFragment(EventInfo event, boolean readOnly, Intent intent) { 368 mEvent = event; 369 mIsReadOnly = readOnly; 370 mIntent = intent; 371 setHasOptionsMenu(true); 372 } 373 374 private void startQuery() { 375 mUri = null; 376 mBegin = -1; 377 mEnd = -1; 378 if (mEvent != null) { 379 if (mEvent.id != -1) { 380 mModel.mId = mEvent.id; 381 mUri = ContentUris.withAppendedId(Events.CONTENT_URI, mEvent.id); 382 } 383 if (mEvent.startTime != null) { 384 mBegin = mEvent.startTime.toMillis(true); 385 } 386 if (mEvent.endTime != null) { 387 mEnd = mEvent.endTime.toMillis(true); 388 } 389 } else if (mEventBundle != null) { 390 if (mEventBundle.id != -1) { 391 mModel.mId = mEventBundle.id; 392 mUri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventBundle.id); 393 } 394 mBegin = mEventBundle.start; 395 mEnd = mEventBundle.end; 396 } 397 398 if (mBegin <= 0) { 399 // use a default value instead 400 mBegin = mHelper.constructDefaultStartTime(System.currentTimeMillis()); 401 } 402 if (mEnd < mBegin) { 403 // use a default value instead 404 mEnd = mHelper.constructDefaultEndTime(mBegin); 405 } 406 407 // Kick off the query for the event 408 boolean newEvent = mUri == null; 409 if (!newEvent) { 410 mModel.mCalendarAccessLevel = Calendars.NO_ACCESS; 411 mOutstandingQueries = TOKEN_ALL; 412 if (DEBUG) { 413 Log.d(TAG, "startQuery: uri for event is " + mUri.toString()); 414 } 415 mHandler.startQuery(TOKEN_EVENT, null, mUri, EditEventHelper.EVENT_PROJECTION, 416 null /* selection */, null /* selection args */, null /* sort order */); 417 } else { 418 mOutstandingQueries = TOKEN_CALENDARS; 419 if (DEBUG) { 420 Log.d(TAG, "startQuery: Editing a new event."); 421 } 422 mModel.mStart = mBegin; 423 mModel.mEnd = mEnd; 424 mModel.mSelfAttendeeStatus = Attendees.ATTENDEE_STATUS_ACCEPTED; 425 426 // Start a query in the background to read the list of calendars 427 mHandler.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI, 428 EditEventHelper.CALENDARS_PROJECTION, 429 EditEventHelper.CALENDARS_WHERE_WRITEABLE_VISIBLE, null /* selection args */, 430 null /* sort order */); 431 432 mModification = Utils.MODIFY_ALL; 433 updateActionBar(); 434 mView.setModification(mModification); 435 } 436 } 437 438 @Override 439 public void onAttach(Activity activity) { 440 super.onAttach(activity); 441 mContext = activity; 442 443 mHelper = new EditEventHelper(activity, null); 444 mHandler = new QueryHandler(activity.getContentResolver()); 445 mModel = new CalendarEventModel(activity, mIntent); 446 mInputMethodManager = (InputMethodManager) 447 activity.getSystemService(Context.INPUT_METHOD_SERVICE); 448 } 449 450 @Override 451 public View onCreateView(LayoutInflater inflater, ViewGroup container, 452 Bundle savedInstanceState) { 453// mContext.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); 454 View view; 455 if (mIsReadOnly) { 456 view = inflater.inflate(R.layout.edit_event_single_column, null); 457 } else { 458 view = inflater.inflate(R.layout.edit_event, null); 459 } 460 mView = new EditEventView(mContext, view, mOnDone); 461 startQuery(); 462 return view; 463 } 464 465 @Override 466 public void onCreate(Bundle savedInstanceState) { 467 super.onCreate(savedInstanceState); 468 if (savedInstanceState != null) { 469 if (savedInstanceState.containsKey(BUNDLE_KEY_MODEL)) { 470 mRestoreModel = (CalendarEventModel) savedInstanceState.getSerializable( 471 BUNDLE_KEY_MODEL); 472 } 473 if (savedInstanceState.containsKey(BUNDLE_KEY_EDIT_STATE)) { 474 mModification = savedInstanceState.getInt(BUNDLE_KEY_EDIT_STATE); 475 } 476 if (savedInstanceState.containsKey(BUNDLE_KEY_EVENT)) { 477 mEventBundle = (EventBundle) savedInstanceState.getSerializable(BUNDLE_KEY_EVENT); 478 } 479 if (savedInstanceState.containsKey(BUNDLE_KEY_READ_ONLY)) { 480 mIsReadOnly = savedInstanceState.getBoolean(BUNDLE_KEY_READ_ONLY); 481 } 482 } 483 } 484 485 486 @Override 487 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 488 super.onCreateOptionsMenu(menu, inflater); 489 inflater.inflate(R.menu.edit_event_title_bar, menu); 490 synchronized (this) { 491 mMenu = menu; 492 updateActionBar(); 493 } 494 } 495 496 @Override 497 public boolean onOptionsItemSelected(MenuItem item) { 498 switch (item.getItemId()) { 499 case R.id.action_done: 500 if (EditEventHelper.canModifyEvent(mModel) || EditEventHelper.canRespond(mModel)) { 501 if (mView != null && mView.prepareForSave()) { 502 if (mModification == Utils.MODIFY_UNINITIALIZED) { 503 mModification = Utils.MODIFY_ALL; 504 } 505 mOnDone.setDoneCode(Utils.DONE_SAVE | Utils.DONE_EXIT); 506 mOnDone.run(); 507 } else { 508 mOnDone.setDoneCode(Utils.DONE_REVERT); 509 mOnDone.run(); 510 } 511 } else if (EditEventHelper.canAddReminders(mModel) && mModel.mId != -1 512 && mOriginalModel != null && mView.prepareForSave()) { 513 saveReminders(); 514 mOnDone.setDoneCode(Utils.DONE_EXIT); 515 mOnDone.run(); 516 } else { 517 mOnDone.setDoneCode(Utils.DONE_REVERT); 518 mOnDone.run(); 519 } 520 break; 521 case R.id.action_cancel: 522 mOnDone.setDoneCode(Utils.DONE_REVERT); 523 mOnDone.run(); 524 break; 525 case R.id.action_delete: 526 mOnDone.setDoneCode(Utils.DONE_DELETE); 527 mOnDone.run(); 528 break; 529 case R.id.action_edit: 530 if (mIsReadOnly) { 531 CalendarController.getInstance(mContext).sendEventRelatedEvent(this, 532 EventType.EDIT_EVENT, mModel.mId, mModel.mStart, mModel.mEnd, -1, -1, -1); 533 } else if (!TextUtils.isEmpty(mModel.mRrule)) { 534 displayEditWhichDialog(); 535 } else { 536 mModification = Utils.MODIFY_ALL; 537 updateActionBar(); 538 mView.setModification(mModification); 539 } 540 break; 541 } 542 return true; 543 } 544 545 private void saveReminders() { 546 ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(3); 547 boolean changed = EditEventHelper.saveReminders(ops, mModel.mId, mModel.mReminders, 548 mOriginalModel.mReminders, false /* no force save */); 549 550 if (!changed) { 551 return; 552 } 553 554 AsyncQueryService service = new AsyncQueryService(getActivity()); 555 service.startBatch(0, null, Calendars.CONTENT_URI.getAuthority(), ops, 0); 556 // Update the "hasAlarm" field for the event 557 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, mModel.mId); 558 int len = mModel.mReminders.size(); 559 boolean hasAlarm = len > 0; 560 if (hasAlarm != mOriginalModel.mHasAlarm) { 561 ContentValues values = new ContentValues(); 562 values.put(Events.HAS_ALARM, hasAlarm ? 1 : 0); 563 service.startUpdate(0, null, uri, values, null, null, 0); 564 } 565 566 Toast.makeText(mContext, R.string.saving_event, Toast.LENGTH_SHORT).show(); 567 } 568 569 protected void displayEditWhichDialog() { 570 if (!TextUtils.isEmpty(mModel.mRrule) && mModification == Utils.MODIFY_UNINITIALIZED) { 571 final boolean notSynced = mModel.mSyncId == null; 572 boolean isFirstEventInSeries = mModel.mIsFirstEventInSeries; 573 int itemIndex = 0; 574 CharSequence[] items; 575 576 if (notSynced) { 577 // If this event has not been synced, then don't allow deleting 578 // or changing a single instance. 579 if (isFirstEventInSeries) { 580 // Still display the option so the user knows all events are 581 // changing 582 items = new CharSequence[1]; 583 } else { 584 items = new CharSequence[2]; 585 } 586 } else { 587 if (isFirstEventInSeries) { 588 items = new CharSequence[2]; 589 } else { 590 items = new CharSequence[3]; 591 } 592 items[itemIndex++] = mContext.getText(R.string.modify_event); 593 } 594 items[itemIndex++] = mContext.getText(R.string.modify_all); 595 596 // Do one more check to make sure this remains at the end of the list 597 if (!isFirstEventInSeries) { 598 items[itemIndex++] = mContext.getText(R.string.modify_all_following); 599 } 600 601 // Display the modification dialog. 602 if (mModifyDialog != null) { 603 mModifyDialog.dismiss(); 604 mModifyDialog = null; 605 } 606 mModifyDialog = new AlertDialog.Builder(mContext) 607 .setTitle(R.string.edit_event_label).setItems(items, new OnClickListener() { 608 public void onClick(DialogInterface dialog, int which) { 609 if (which == 0) { 610 mModification = notSynced ? Utils.MODIFY_ALL : Utils.MODIFY_SELECTED; 611 mModel.mOriginalEvent = notSynced ? null : mModel.mSyncId; 612 } else if (which == 1) { 613 mModification = notSynced ? Utils.MODIFY_ALL_FOLLOWING : Utils.MODIFY_ALL; 614 } else if (which == 2) { 615 mModification = Utils.MODIFY_ALL_FOLLOWING; 616 } 617 618 mView.setModification(mModification); 619 updateActionBar(); 620 } 621 }).show(); 622 } 623 } 624 625 class Done implements EditEventHelper.EditDoneRunnable { 626 private int mCode = -1; 627 628 public void setDoneCode(int code) { 629 mCode = code; 630 } 631 632 public void run() { 633 // We only want this to get called once, either because the user 634 // pressed back/home or one of the buttons on screen 635 mSaveOnDetach = false; 636 637 if ((mCode & Utils.DONE_SAVE) != 0 && mModel != null 638 && (EditEventHelper.canRespond(mModel) 639 || EditEventHelper.canModifyEvent(mModel)) 640 && !isEmptyNewEvent() 641 && mModel.normalizeReminders() 642 && !mModel.isUnchanged(mOriginalModel) 643 && mHelper.saveEvent(mModel, mOriginalModel, mModification)) { 644 int stringResource; 645 if (!mModel.mAttendeesList.isEmpty()) { 646 if (mModel.mUri != null) { 647 stringResource = R.string.saving_event_with_guest; 648 } else { 649 stringResource = R.string.creating_event_with_guest; 650 } 651 } else { 652 if (mModel.mUri != null) { 653 stringResource = R.string.saving_event; 654 } else { 655 stringResource = R.string.creating_event; 656 } 657 } 658 Toast.makeText(mContext, stringResource, Toast.LENGTH_SHORT).show(); 659 } 660 661 if ((mCode & Utils.DONE_DELETE) != 0 && mOriginalModel != null 662 && EditEventHelper.canModifyCalendar(mOriginalModel)) { 663 long begin = mModel.mStart; 664 long end = mModel.mEnd; 665 int which = -1; 666 switch (mModification) { 667 case Utils.MODIFY_SELECTED: 668 which = DeleteEventHelper.DELETE_SELECTED; 669 break; 670 case Utils.MODIFY_ALL_FOLLOWING: 671 which = DeleteEventHelper.DELETE_ALL_FOLLOWING; 672 break; 673 case Utils.MODIFY_ALL: 674 which = DeleteEventHelper.DELETE_ALL; 675 break; 676 } 677 DeleteEventHelper deleteHelper = new DeleteEventHelper( 678 mContext, mContext, !mIsReadOnly /* exitWhenDone */); 679 deleteHelper.delete(begin, end, mOriginalModel, which); 680 } 681 682 if ((mCode & Utils.DONE_EXIT) != 0) { 683 // This will exit the edit event screen, should be called 684 // when we want to return to the main calendar views 685 EditEventFragment.this.getActivity().finish(); 686 } 687 688 // Hide a software keyboard so that user won't see it even after this Fragment's 689 // disappearing. 690 final View focusedView = mContext.getCurrentFocus(); 691 if (focusedView != null) { 692 mInputMethodManager.hideSoftInputFromWindow(focusedView.getWindowToken(), 0); 693 focusedView.clearFocus(); 694 } 695 } 696 } 697 698 boolean isEmptyNewEvent() { 699 if (mOriginalModel != null) { 700 // Not new 701 return false; 702 } 703 704 return isEmpty(); 705 } 706 707 private boolean isEmpty() { 708 if (mModel.mTitle != null) { 709 String title = mModel.mTitle.trim(); 710 if (title.length() > 0) { 711 return false; 712 } 713 } 714 715 if (mModel.mLocation != null) { 716 String location = mModel.mLocation.trim(); 717 if (location.length() > 0) { 718 return false; 719 } 720 } 721 722 if (mModel.mDescription != null) { 723 String description = mModel.mDescription.trim(); 724 if (description.length() > 0) { 725 return false; 726 } 727 } 728 729 return true; 730 } 731 732 @Override 733 public void onPause() { 734 Activity act = getActivity(); 735 if (mSaveOnDetach && act != null && !mIsReadOnly && !act.isChangingConfigurations() 736 && mView.prepareForSave()) { 737 mOnDone.setDoneCode(Utils.DONE_SAVE); 738 mOnDone.run(); 739 } 740 super.onPause(); 741 } 742 743 @Override 744 public void onDestroy() { 745 if (mView != null) { 746 mView.setModel(null); 747 } 748 if (mModifyDialog != null) { 749 mModifyDialog.dismiss(); 750 mModifyDialog = null; 751 } 752 super.onDestroy(); 753 } 754 755 @Override 756 public void eventsChanged() { 757 // TODO Requery to see if event has changed 758 } 759 760 @Override 761 public void onSaveInstanceState(Bundle outState) { 762 mView.prepareForSave(); 763 outState.putSerializable(BUNDLE_KEY_MODEL, mModel); 764 outState.putInt(BUNDLE_KEY_EDIT_STATE, mModification); 765 if (mEventBundle == null && mEvent != null) { 766 mEventBundle = new EventBundle(); 767 mEventBundle.id = mEvent.id; 768 if (mEvent.startTime != null) { 769 mEventBundle.start = mEvent.startTime.toMillis(true); 770 } 771 if (mEvent.endTime != null) { 772 mEventBundle.end = mEvent.startTime.toMillis(true); 773 } 774 } 775 776 outState.putSerializable(BUNDLE_KEY_EVENT, mEventBundle); 777 outState.putBoolean(BUNDLE_KEY_READ_ONLY, mIsReadOnly); 778 } 779 780 @Override 781 public long getSupportedEventTypes() { 782 return EventType.USER_HOME; 783 } 784 785 @Override 786 public void handleEvent(EventInfo event) { 787 // It's currently unclear if we want to save the event or not when home 788 // is pressed. When creating a new event we shouldn't save since we 789 // can't get the id of the new event easily. 790 if ((false && event.eventType == EventType.USER_HOME) || (event.eventType == EventType.GO_TO 791 && mSaveOnDetach)) { 792 if (mView != null && mView.prepareForSave()) { 793 mOnDone.setDoneCode(Utils.DONE_SAVE); 794 mOnDone.run(); 795 } 796 } 797 } 798 799 private static class EventBundle implements Serializable { 800 long id = -1; 801 long start = -1; 802 long end = -1; 803 } 804} 805