EditEventFragment.java revision c130d9d5e0d178585721428e394df0c8e0a6729f
179f228124de7d98146ca526d743436f6419e2365Erik/*
279f228124de7d98146ca526d743436f6419e2365Erik * Copyright (C) 2010 The Android Open Source Project
379f228124de7d98146ca526d743436f6419e2365Erik *
479f228124de7d98146ca526d743436f6419e2365Erik * Licensed under the Apache License, Version 2.0 (the "License");
579f228124de7d98146ca526d743436f6419e2365Erik * you may not use this file except in compliance with the License.
679f228124de7d98146ca526d743436f6419e2365Erik * You may obtain a copy of the License at
779f228124de7d98146ca526d743436f6419e2365Erik *
879f228124de7d98146ca526d743436f6419e2365Erik *      http://www.apache.org/licenses/LICENSE-2.0
979f228124de7d98146ca526d743436f6419e2365Erik *
1079f228124de7d98146ca526d743436f6419e2365Erik * Unless required by applicable law or agreed to in writing, software
1179f228124de7d98146ca526d743436f6419e2365Erik * distributed under the License is distributed on an "AS IS" BASIS,
1279f228124de7d98146ca526d743436f6419e2365Erik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379f228124de7d98146ca526d743436f6419e2365Erik * See the License for the specific language governing permissions and
1479f228124de7d98146ca526d743436f6419e2365Erik * limitations under the License.
1579f228124de7d98146ca526d743436f6419e2365Erik */
1679f228124de7d98146ca526d743436f6419e2365Erik
17fbce65e53c7a111955f638db5bf8bee35381e5b7Erikpackage com.android.calendar.event;
1879f228124de7d98146ca526d743436f6419e2365Erik
195f62079ab9daefe95ede87631766e99e8b4a2220Erikimport com.android.calendar.AsyncQueryService;
20dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport com.android.calendar.CalendarController.EventHandler;
21dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport com.android.calendar.CalendarController.EventInfo;
22dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport com.android.calendar.CalendarController.EventType;
23fbce65e53c7a111955f638db5bf8bee35381e5b7Erikimport com.android.calendar.CalendarEventModel;
24d845fbe558d5229102b58cce70a1b29fe6cb6967Erikimport com.android.calendar.CalendarEventModel.Attendee;
25fbce65e53c7a111955f638db5bf8bee35381e5b7Erikimport com.android.calendar.DeleteEventHelper;
26fbce65e53c7a111955f638db5bf8bee35381e5b7Erikimport com.android.calendar.R;
27fbce65e53c7a111955f638db5bf8bee35381e5b7Erikimport com.android.calendar.Utils;
28fbce65e53c7a111955f638db5bf8bee35381e5b7Erik
2979f228124de7d98146ca526d743436f6419e2365Erikimport android.app.Activity;
3079f228124de7d98146ca526d743436f6419e2365Erikimport android.app.AlertDialog;
3179f228124de7d98146ca526d743436f6419e2365Erikimport android.app.Fragment;
3279f228124de7d98146ca526d743436f6419e2365Erikimport android.content.AsyncQueryHandler;
335f62079ab9daefe95ede87631766e99e8b4a2220Erikimport android.content.ContentProviderOperation;
3479f228124de7d98146ca526d743436f6419e2365Erikimport android.content.ContentResolver;
35dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.content.ContentUris;
365f62079ab9daefe95ede87631766e99e8b4a2220Erikimport android.content.ContentValues;
375c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawaimport android.content.Context;
3879f228124de7d98146ca526d743436f6419e2365Erikimport android.content.DialogInterface;
3979f228124de7d98146ca526d743436f6419e2365Erikimport android.content.DialogInterface.OnCancelListener;
4079f228124de7d98146ca526d743436f6419e2365Erikimport android.content.DialogInterface.OnClickListener;
4179f228124de7d98146ca526d743436f6419e2365Erikimport android.database.Cursor;
4279f228124de7d98146ca526d743436f6419e2365Erikimport android.database.MatrixCursor;
4379f228124de7d98146ca526d743436f6419e2365Erikimport android.net.Uri;
4479f228124de7d98146ca526d743436f6419e2365Erikimport android.os.Bundle;
4579f228124de7d98146ca526d743436f6419e2365Erikimport android.provider.Calendar.Attendees;
4679f228124de7d98146ca526d743436f6419e2365Erikimport android.provider.Calendar.Calendars;
47dd95df57c8c5a58a85c4c0effad5652dec14f621Erikimport android.provider.Calendar.Events;
4879f228124de7d98146ca526d743436f6419e2365Erikimport android.provider.Calendar.Reminders;
4979f228124de7d98146ca526d743436f6419e2365Erikimport android.text.TextUtils;
5079f228124de7d98146ca526d743436f6419e2365Erikimport android.util.Log;
5179f228124de7d98146ca526d743436f6419e2365Erikimport android.view.LayoutInflater;
525f62079ab9daefe95ede87631766e99e8b4a2220Erikimport android.view.Menu;
535f62079ab9daefe95ede87631766e99e8b4a2220Erikimport android.view.MenuInflater;
545f62079ab9daefe95ede87631766e99e8b4a2220Erikimport android.view.MenuItem;
5579f228124de7d98146ca526d743436f6419e2365Erikimport android.view.View;
5679f228124de7d98146ca526d743436f6419e2365Erikimport android.view.ViewGroup;
575c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawaimport android.view.inputmethod.InputMethodManager;
5879f228124de7d98146ca526d743436f6419e2365Erikimport android.widget.Toast;
5979f228124de7d98146ca526d743436f6419e2365Erik
60c130d9d5e0d178585721428e394df0c8e0a6729fErikimport java.io.Serializable;
615f62079ab9daefe95ede87631766e99e8b4a2220Erikimport java.util.ArrayList;
625f62079ab9daefe95ede87631766e99e8b4a2220Erik
63dd95df57c8c5a58a85c4c0effad5652dec14f621Erikpublic class EditEventFragment extends Fragment implements EventHandler {
6479f228124de7d98146ca526d743436f6419e2365Erik    private static final String TAG = "EditEventActivity";
6579f228124de7d98146ca526d743436f6419e2365Erik
6659ead671b50514b49749fcd6a1d4186a270239d2Erik    private static final String BUNDLE_KEY_MODEL = "key_model";
6759ead671b50514b49749fcd6a1d4186a270239d2Erik    private static final String BUNDLE_KEY_EDIT_STATE = "key_edit_state";
68c130d9d5e0d178585721428e394df0c8e0a6729fErik    private static final String BUNDLE_KEY_EVENT = "key_event";
6959ead671b50514b49749fcd6a1d4186a270239d2Erik
7079f228124de7d98146ca526d743436f6419e2365Erik    private static final boolean DEBUG = false;
7179f228124de7d98146ca526d743436f6419e2365Erik
72352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    private static final int TOKEN_EVENT = 1;
73352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    private static final int TOKEN_ATTENDEES = 1 << 1;
74352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    private static final int TOKEN_REMINDERS = 1 << 2;
75352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    private static final int TOKEN_CALENDARS = 1 << 3;
76352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    private static final int TOKEN_ALL = TOKEN_EVENT | TOKEN_ATTENDEES | TOKEN_REMINDERS
77352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            | TOKEN_CALENDARS;
785f62079ab9daefe95ede87631766e99e8b4a2220Erik    private static final int TOKEN_UNITIALIZED = 1 << 31;
79352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
80352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    /**
81352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan     * A bitfield of TOKEN_* to keep track which query hasn't been completed
82352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan     * yet. Once all queries have returned, the model can be applied to the
83352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan     * view.
84352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan     */
855f62079ab9daefe95ede87631766e99e8b4a2220Erik    private int mOutstandingQueries = TOKEN_UNITIALIZED;
8679f228124de7d98146ca526d743436f6419e2365Erik
8779f228124de7d98146ca526d743436f6419e2365Erik    EditEventHelper mHelper;
8879f228124de7d98146ca526d743436f6419e2365Erik    CalendarEventModel mModel;
8979f228124de7d98146ca526d743436f6419e2365Erik    CalendarEventModel mOriginalModel;
9059ead671b50514b49749fcd6a1d4186a270239d2Erik    CalendarEventModel mRestoreModel;
9179f228124de7d98146ca526d743436f6419e2365Erik    EditEventView mView;
9279f228124de7d98146ca526d743436f6419e2365Erik    QueryHandler mHandler;
9379f228124de7d98146ca526d743436f6419e2365Erik
9479f228124de7d98146ca526d743436f6419e2365Erik    private AlertDialog mModifyDialog;
9579f228124de7d98146ca526d743436f6419e2365Erik    int mModification = Utils.MODIFY_UNINITIALIZED;
9679f228124de7d98146ca526d743436f6419e2365Erik
97dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    private EventInfo mEvent;
98c130d9d5e0d178585721428e394df0c8e0a6729fErik    private EventBundle mEventBundle;
9979f228124de7d98146ca526d743436f6419e2365Erik    private Uri mUri;
10079f228124de7d98146ca526d743436f6419e2365Erik    private long mBegin;
10179f228124de7d98146ca526d743436f6419e2365Erik    private long mEnd;
10279f228124de7d98146ca526d743436f6419e2365Erik
10379f228124de7d98146ca526d743436f6419e2365Erik    private Activity mContext;
104dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    private Done mOnDone = new Done();
1055f62079ab9daefe95ede87631766e99e8b4a2220Erik    private Menu mMenu;
106dd95df57c8c5a58a85c4c0effad5652dec14f621Erik
107dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    private boolean mSaveOnDetach = true;
10879f228124de7d98146ca526d743436f6419e2365Erik
1095c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa    private InputMethodManager mInputMethodManager;
1105c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa
11179f228124de7d98146ca526d743436f6419e2365Erik    private class QueryHandler extends AsyncQueryHandler {
11279f228124de7d98146ca526d743436f6419e2365Erik        public QueryHandler(ContentResolver cr) {
11379f228124de7d98146ca526d743436f6419e2365Erik            super(cr);
11479f228124de7d98146ca526d743436f6419e2365Erik        }
11579f228124de7d98146ca526d743436f6419e2365Erik
11679f228124de7d98146ca526d743436f6419e2365Erik        @Override
11779f228124de7d98146ca526d743436f6419e2365Erik        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
11879f228124de7d98146ca526d743436f6419e2365Erik            // If the query didn't return a cursor for some reason return
11979f228124de7d98146ca526d743436f6419e2365Erik            if (cursor == null) {
12079f228124de7d98146ca526d743436f6419e2365Erik                return;
12179f228124de7d98146ca526d743436f6419e2365Erik            }
12279f228124de7d98146ca526d743436f6419e2365Erik
12379f228124de7d98146ca526d743436f6419e2365Erik            // If the Activity is finishing, then close the cursor.
12479f228124de7d98146ca526d743436f6419e2365Erik            // Otherwise, use the new cursor in the adapter.
1256a7878f0cfe2f13e4e33fee74ed9f91eaffc227bMichael Chan            final Activity activity = EditEventFragment.this.getActivity();
1266a7878f0cfe2f13e4e33fee74ed9f91eaffc227bMichael Chan            if (activity == null || activity.isFinishing()) {
12779f228124de7d98146ca526d743436f6419e2365Erik                cursor.close();
12879f228124de7d98146ca526d743436f6419e2365Erik                return;
12979f228124de7d98146ca526d743436f6419e2365Erik            }
13079f228124de7d98146ca526d743436f6419e2365Erik            long eventId;
13179f228124de7d98146ca526d743436f6419e2365Erik            switch (token) {
13279f228124de7d98146ca526d743436f6419e2365Erik                case TOKEN_EVENT:
13379f228124de7d98146ca526d743436f6419e2365Erik                    if (cursor.getCount() == 0) {
13479f228124de7d98146ca526d743436f6419e2365Erik                        // The cursor is empty. This can happen if the event
13579f228124de7d98146ca526d743436f6419e2365Erik                        // was deleted.
13679f228124de7d98146ca526d743436f6419e2365Erik                        cursor.close();
137352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        mOnDone.setDoneCode(Utils.DONE_EXIT);
138352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        mOnDone.run();
13979f228124de7d98146ca526d743436f6419e2365Erik                        return;
14079f228124de7d98146ca526d743436f6419e2365Erik                    }
14179f228124de7d98146ca526d743436f6419e2365Erik                    mOriginalModel = new CalendarEventModel();
14279f228124de7d98146ca526d743436f6419e2365Erik                    EditEventHelper.setModelFromCursor(mOriginalModel, cursor);
14379f228124de7d98146ca526d743436f6419e2365Erik                    EditEventHelper.setModelFromCursor(mModel, cursor);
14479f228124de7d98146ca526d743436f6419e2365Erik                    cursor.close();
14579f228124de7d98146ca526d743436f6419e2365Erik
14659ead671b50514b49749fcd6a1d4186a270239d2Erik                    mOriginalModel.mUri = mUri.toString();
14779f228124de7d98146ca526d743436f6419e2365Erik
14859ead671b50514b49749fcd6a1d4186a270239d2Erik                    mModel.mUri = mUri.toString();
14979f228124de7d98146ca526d743436f6419e2365Erik                    mModel.mOriginalStart = mBegin;
15079f228124de7d98146ca526d743436f6419e2365Erik                    mModel.mOriginalEnd = mEnd;
15179f228124de7d98146ca526d743436f6419e2365Erik                    mModel.mIsFirstEventInSeries = mBegin == mOriginalModel.mStart;
15279f228124de7d98146ca526d743436f6419e2365Erik                    mModel.mStart = mBegin;
15379f228124de7d98146ca526d743436f6419e2365Erik                    mModel.mEnd = mEnd;
15479f228124de7d98146ca526d743436f6419e2365Erik
15579f228124de7d98146ca526d743436f6419e2365Erik                    eventId = mModel.mId;
156352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
157352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    // TOKEN_ATTENDEES
15879f228124de7d98146ca526d743436f6419e2365Erik                    if (mModel.mHasAttendeeData && eventId != -1) {
15979f228124de7d98146ca526d743436f6419e2365Erik                        Uri attUri = Attendees.CONTENT_URI;
16079f228124de7d98146ca526d743436f6419e2365Erik                        String[] whereArgs = {
16179f228124de7d98146ca526d743436f6419e2365Erik                            Long.toString(eventId)
16279f228124de7d98146ca526d743436f6419e2365Erik                        };
16379f228124de7d98146ca526d743436f6419e2365Erik                        mHandler.startQuery(TOKEN_ATTENDEES, null, attUri,
16479f228124de7d98146ca526d743436f6419e2365Erik                                EditEventHelper.ATTENDEES_PROJECTION,
165d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                EditEventHelper.ATTENDEES_WHERE /* selection */,
16679f228124de7d98146ca526d743436f6419e2365Erik                                whereArgs /* selection args */, null /* sort order */);
167352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    } else {
168352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        setModelIfDone(TOKEN_ATTENDEES);
169352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    }
170352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
171352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    // TOKEN_REMINDERS
172352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    if (mModel.mHasAlarm) {
173d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                        Uri rUri = Reminders.CONTENT_URI;
174d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                        String[] remArgs = {
175d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                Long.toString(eventId), Integer.toString(Reminders.METHOD_ALERT),
176d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                Integer.toString(Reminders.METHOD_DEFAULT)
177d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                        };
178d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                        mHandler
179d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                .startQuery(TOKEN_REMINDERS, null, rUri,
180d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                        EditEventHelper.REMINDERS_PROJECTION,
181d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                        EditEventHelper.REMINDERS_WHERE /* selection */,
182d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                        remArgs /* selection args */, null /* sort order */);
18379f228124de7d98146ca526d743436f6419e2365Erik                    } else {
184352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        setModelIfDone(TOKEN_REMINDERS);
18579f228124de7d98146ca526d743436f6419e2365Erik                    }
186352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
187352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    // TOKEN_CALENDARS
188352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    String[] selArgs = {
189352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        Long.toString(mModel.mCalendarId)
190352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    };
191352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    mHandler.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI,
192352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            EditEventHelper.CALENDARS_PROJECTION, EditEventHelper.CALENDARS_WHERE,
193352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            selArgs /* selection args */, null /* sort order */);
194352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
195352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    setModelIfDone(TOKEN_EVENT);
19679f228124de7d98146ca526d743436f6419e2365Erik                    break;
19779f228124de7d98146ca526d743436f6419e2365Erik                case TOKEN_ATTENDEES:
19879f228124de7d98146ca526d743436f6419e2365Erik                    try {
19979f228124de7d98146ca526d743436f6419e2365Erik                        while (cursor.moveToNext()) {
20079f228124de7d98146ca526d743436f6419e2365Erik                            String name = cursor.getString(EditEventHelper.ATTENDEES_INDEX_NAME);
20179f228124de7d98146ca526d743436f6419e2365Erik                            String email = cursor.getString(EditEventHelper.ATTENDEES_INDEX_EMAIL);
202d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                            int status = cursor.getInt(EditEventHelper.ATTENDEES_INDEX_STATUS);
20379f228124de7d98146ca526d743436f6419e2365Erik                            int relationship = cursor
20479f228124de7d98146ca526d743436f6419e2365Erik                                    .getInt(EditEventHelper.ATTENDEES_INDEX_RELATIONSHIP);
205352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
206352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                if (email != null) {
20779f228124de7d98146ca526d743436f6419e2365Erik                                    mModel.mOrganizer = email;
208352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                    mModel.mIsOrganizer = mModel.mOwnerAccount
209352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                            .equalsIgnoreCase(email);
210352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                }
211352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
212352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                if (TextUtils.isEmpty(name)) {
213352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                    mModel.mOrganizerDisplayName = mModel.mOrganizer;
214352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                } else {
215352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                    mModel.mOrganizerDisplayName = name;
21679f228124de7d98146ca526d743436f6419e2365Erik                                }
217352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            }
218352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
219352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            if (email != null) {
220d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                if (mModel.mOwnerAccount != null &&
221d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                        mModel.mOwnerAccount.equalsIgnoreCase(email)) {
222d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                    int attendeeId =
223d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                        cursor.getInt(EditEventHelper.ATTENDEES_INDEX_ID);
224d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                    mModel.mOwnerAttendeeId = attendeeId;
225d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                    mModel.mSelfAttendeeStatus = status;
226d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                    mOriginalModel.mOwnerAttendeeId = attendeeId;
227d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                    mOriginalModel.mSelfAttendeeStatus = status;
228d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                    continue;
229d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                                }
23079f228124de7d98146ca526d743436f6419e2365Erik                            }
231d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                            Attendee attendee = new Attendee(name, email);
232d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                            attendee.mStatus = status;
233d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                            mModel.addAttendee(attendee);
234d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                            mOriginalModel.addAttendee(attendee);
23579f228124de7d98146ca526d743436f6419e2365Erik                        }
23679f228124de7d98146ca526d743436f6419e2365Erik                    } finally {
23779f228124de7d98146ca526d743436f6419e2365Erik                        cursor.close();
23879f228124de7d98146ca526d743436f6419e2365Erik                    }
239352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
240352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    setModelIfDone(TOKEN_ATTENDEES);
24179f228124de7d98146ca526d743436f6419e2365Erik                    break;
24279f228124de7d98146ca526d743436f6419e2365Erik                case TOKEN_REMINDERS:
24379f228124de7d98146ca526d743436f6419e2365Erik                    try {
244d290a01420234214d73d31b8bfa61652625bb149Erik                        // Add all reminders to the models
24579f228124de7d98146ca526d743436f6419e2365Erik                        while (cursor.moveToNext()) {
24679f228124de7d98146ca526d743436f6419e2365Erik                            int minutes = cursor.getInt(EditEventHelper.REMINDERS_INDEX_MINUTES);
24779f228124de7d98146ca526d743436f6419e2365Erik                            mModel.mReminderMinutes.add(minutes);
248d290a01420234214d73d31b8bfa61652625bb149Erik                            mOriginalModel.mReminderMinutes.add(minutes);
24979f228124de7d98146ca526d743436f6419e2365Erik                        }
25079f228124de7d98146ca526d743436f6419e2365Erik                    } finally {
25179f228124de7d98146ca526d743436f6419e2365Erik                        cursor.close();
25279f228124de7d98146ca526d743436f6419e2365Erik                    }
253352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
254352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    setModelIfDone(TOKEN_REMINDERS);
25579f228124de7d98146ca526d743436f6419e2365Erik                    break;
25679f228124de7d98146ca526d743436f6419e2365Erik                case TOKEN_CALENDARS:
257352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    try {
258352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        if (mModel.mCalendarId == -1) {
259352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            // Populate Calendar spinner only if no calendar is set e.g. new event
260352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            MatrixCursor matrixCursor = Utils.matrixCursorFromCursor(cursor);
261352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            if (DEBUG) {
262352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                Log.d(TAG, "onQueryComplete: setting cursor with "
263352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                                        + matrixCursor.getCount() + " calendars");
264352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            }
265352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            mView.setCalendarsCursor(matrixCursor, isAdded() && isResumed());
266352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        } else {
267352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            // Populate model for an existing event
268352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            EditEventHelper.setModelFromCalendarCursor(mModel, cursor);
269352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        }
270352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    } finally {
271352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                        cursor.close();
27279f228124de7d98146ca526d743436f6419e2365Erik                    }
273352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
274352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    setModelIfDone(TOKEN_CALENDARS);
27579f228124de7d98146ca526d743436f6419e2365Erik                    break;
27679f228124de7d98146ca526d743436f6419e2365Erik            }
27779f228124de7d98146ca526d743436f6419e2365Erik        }
27879f228124de7d98146ca526d743436f6419e2365Erik    }
27979f228124de7d98146ca526d743436f6419e2365Erik
280bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private void setModelIfDone(int queryType) {
281352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan        synchronized (this) {
282352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            mOutstandingQueries &= ~queryType;
283352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            if (mOutstandingQueries == 0) {
28459ead671b50514b49749fcd6a1d4186a270239d2Erik                if (mRestoreModel != null) {
28559ead671b50514b49749fcd6a1d4186a270239d2Erik                    mModel = mRestoreModel;
28659ead671b50514b49749fcd6a1d4186a270239d2Erik                }
287352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                mView.setModel(mModel);
288c07a57fb7436d807ad505fa7319b9de13f91e741Erik                if (mMenu != null) {
2895f62079ab9daefe95ede87631766e99e8b4a2220Erik                    updateActionBar();
2905f62079ab9daefe95ede87631766e99e8b4a2220Erik                }
291352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            }
292352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan        }
293352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    }
294352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
2955f62079ab9daefe95ede87631766e99e8b4a2220Erik    private void updateActionBar() {
296c07a57fb7436d807ad505fa7319b9de13f91e741Erik        if (mMenu == null) {
297c07a57fb7436d807ad505fa7319b9de13f91e741Erik            return;
298c07a57fb7436d807ad505fa7319b9de13f91e741Erik        }
2995f62079ab9daefe95ede87631766e99e8b4a2220Erik        MenuItem cancelItem = mMenu.findItem(R.id.action_cancel);
3005f62079ab9daefe95ede87631766e99e8b4a2220Erik        MenuItem deleteItem = mMenu.findItem(R.id.action_delete);
301c07a57fb7436d807ad505fa7319b9de13f91e741Erik        MenuItem editItem = mMenu.findItem(R.id.action_edit);
302c07a57fb7436d807ad505fa7319b9de13f91e741Erik        boolean canModifyEvent = EditEventHelper.canModifyEvent(mModel);
30346cde5cff48d6862f492f60c6a6336bfc047ce25Erik        boolean canModifyCalendar = EditEventHelper.canModifyCalendar(mModel);
304c07a57fb7436d807ad505fa7319b9de13f91e741Erik
30546cde5cff48d6862f492f60c6a6336bfc047ce25Erik        if (canModifyCalendar && mModel.mUri != null) {
30646cde5cff48d6862f492f60c6a6336bfc047ce25Erik            deleteItem.setVisible(true);
30746cde5cff48d6862f492f60c6a6336bfc047ce25Erik        } else {
30846cde5cff48d6862f492f60c6a6336bfc047ce25Erik            deleteItem.setVisible(false);
30946cde5cff48d6862f492f60c6a6336bfc047ce25Erik        }
310c07a57fb7436d807ad505fa7319b9de13f91e741Erik        if (mModification == Utils.MODIFY_UNINITIALIZED) {
311c07a57fb7436d807ad505fa7319b9de13f91e741Erik            cancelItem.setVisible(false);
312c07a57fb7436d807ad505fa7319b9de13f91e741Erik            if (canModifyEvent) {
313c07a57fb7436d807ad505fa7319b9de13f91e741Erik                editItem.setVisible(true);
314c07a57fb7436d807ad505fa7319b9de13f91e741Erik            } else {
315c07a57fb7436d807ad505fa7319b9de13f91e741Erik                editItem.setVisible(false);
316c07a57fb7436d807ad505fa7319b9de13f91e741Erik            }
317c07a57fb7436d807ad505fa7319b9de13f91e741Erik            return;
318c07a57fb7436d807ad505fa7319b9de13f91e741Erik        } else {
31946cde5cff48d6862f492f60c6a6336bfc047ce25Erik            editItem.setVisible(false);
320c07a57fb7436d807ad505fa7319b9de13f91e741Erik        }
321c07a57fb7436d807ad505fa7319b9de13f91e741Erik        boolean canRespond = EditEventHelper.canRespond(mModel);
3225f62079ab9daefe95ede87631766e99e8b4a2220Erik
3235f62079ab9daefe95ede87631766e99e8b4a2220Erik        if (canRespond || canModifyEvent) {
3245f62079ab9daefe95ede87631766e99e8b4a2220Erik            cancelItem.setVisible(true);
3255f62079ab9daefe95ede87631766e99e8b4a2220Erik        } else {
3265f62079ab9daefe95ede87631766e99e8b4a2220Erik            cancelItem.setVisible(false);
3275f62079ab9daefe95ede87631766e99e8b4a2220Erik        }
3285f62079ab9daefe95ede87631766e99e8b4a2220Erik    }
3295f62079ab9daefe95ede87631766e99e8b4a2220Erik
330dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    public EditEventFragment() {
3315f62079ab9daefe95ede87631766e99e8b4a2220Erik        this(null);
332dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    }
333dd95df57c8c5a58a85c4c0effad5652dec14f621Erik
3345f62079ab9daefe95ede87631766e99e8b4a2220Erik    public EditEventFragment(EventInfo event) {
335dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mEvent = event;
3365f62079ab9daefe95ede87631766e99e8b4a2220Erik        setHasOptionsMenu(true);
33779f228124de7d98146ca526d743436f6419e2365Erik    }
33879f228124de7d98146ca526d743436f6419e2365Erik
33979f228124de7d98146ca526d743436f6419e2365Erik    private void startQuery() {
340dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mUri = null;
341dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mBegin = -1;
342dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mEnd = -1;
343dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        if (mEvent != null) {
344dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            if (mEvent.id != -1) {
345352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                mModel.mId = mEvent.id;
346dd95df57c8c5a58a85c4c0effad5652dec14f621Erik                mUri = ContentUris.withAppendedId(Events.CONTENT_URI, mEvent.id);
347dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            }
348dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            if (mEvent.startTime != null) {
349dd95df57c8c5a58a85c4c0effad5652dec14f621Erik                mBegin = mEvent.startTime.toMillis(true);
350dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            }
351dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            if (mEvent.endTime != null) {
352dd95df57c8c5a58a85c4c0effad5652dec14f621Erik                mEnd = mEvent.endTime.toMillis(true);
353dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            }
354c130d9d5e0d178585721428e394df0c8e0a6729fErik        } else if (mEventBundle != null) {
355c130d9d5e0d178585721428e394df0c8e0a6729fErik            mModel.mId = mEventBundle.id;
356c130d9d5e0d178585721428e394df0c8e0a6729fErik            mUri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventBundle.id);
357c130d9d5e0d178585721428e394df0c8e0a6729fErik            mBegin = mEventBundle.start;
358c130d9d5e0d178585721428e394df0c8e0a6729fErik            mEnd = mEventBundle.end;
359dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        }
360e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang
361e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang        if (mBegin <= 0) {
362e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang            // use a default value instead
363e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang            mBegin = mHelper.constructDefaultStartTime(System.currentTimeMillis());
364e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang        }
365e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang        if (mEnd < mBegin) {
366e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang            // use a default value instead
367e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang            mEnd = mHelper.constructDefaultEndTime(mBegin);
368e700c16ec2464cbba86f91f8f757ae59cbed34b0Mason Tang        }
36979f228124de7d98146ca526d743436f6419e2365Erik
37079f228124de7d98146ca526d743436f6419e2365Erik        // Kick off the query for the event
37179f228124de7d98146ca526d743436f6419e2365Erik        boolean newEvent = mUri == null;
37279f228124de7d98146ca526d743436f6419e2365Erik        if (!newEvent) {
373c07a57fb7436d807ad505fa7319b9de13f91e741Erik            mModel.mCalendarAccessLevel = Calendars.NO_ACCESS;
374352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            mOutstandingQueries = TOKEN_ALL;
37579f228124de7d98146ca526d743436f6419e2365Erik            if (DEBUG) {
376352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                Log.d(TAG, "startQuery: uri for event is " + mUri.toString());
37779f228124de7d98146ca526d743436f6419e2365Erik            }
37879f228124de7d98146ca526d743436f6419e2365Erik            mHandler.startQuery(TOKEN_EVENT, null, mUri, EditEventHelper.EVENT_PROJECTION,
37979f228124de7d98146ca526d743436f6419e2365Erik                    null /* selection */, null /* selection args */, null /* sort order */);
38079f228124de7d98146ca526d743436f6419e2365Erik        } else {
381352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            mOutstandingQueries = TOKEN_CALENDARS;
38279f228124de7d98146ca526d743436f6419e2365Erik            if (DEBUG) {
383352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                Log.d(TAG, "startQuery: Editing a new event.");
38479f228124de7d98146ca526d743436f6419e2365Erik            }
38579f228124de7d98146ca526d743436f6419e2365Erik            mModel.mStart = mBegin;
38679f228124de7d98146ca526d743436f6419e2365Erik            mModel.mEnd = mEnd;
387d845fbe558d5229102b58cce70a1b29fe6cb6967Erik            mModel.mSelfAttendeeStatus = Attendees.ATTENDEE_STATUS_ACCEPTED;
38879f228124de7d98146ca526d743436f6419e2365Erik
38979f228124de7d98146ca526d743436f6419e2365Erik            // Start a query in the background to read the list of calendars
39079f228124de7d98146ca526d743436f6419e2365Erik            mHandler.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI,
39179f228124de7d98146ca526d743436f6419e2365Erik                    EditEventHelper.CALENDARS_PROJECTION,
39279f228124de7d98146ca526d743436f6419e2365Erik                    EditEventHelper.CALENDARS_WHERE_WRITEABLE_VISIBLE, null /* selection args */,
39379f228124de7d98146ca526d743436f6419e2365Erik                    null /* sort order */);
394c07a57fb7436d807ad505fa7319b9de13f91e741Erik
395c07a57fb7436d807ad505fa7319b9de13f91e741Erik            mModification = Utils.MODIFY_ALL;
396c07a57fb7436d807ad505fa7319b9de13f91e741Erik            updateActionBar();
397c07a57fb7436d807ad505fa7319b9de13f91e741Erik            mView.setModification(mModification);
39879f228124de7d98146ca526d743436f6419e2365Erik        }
39979f228124de7d98146ca526d743436f6419e2365Erik    }
40079f228124de7d98146ca526d743436f6419e2365Erik
40179f228124de7d98146ca526d743436f6419e2365Erik    @Override
40279f228124de7d98146ca526d743436f6419e2365Erik    public void onAttach(Activity activity) {
40379f228124de7d98146ca526d743436f6419e2365Erik        super.onAttach(activity);
40479f228124de7d98146ca526d743436f6419e2365Erik        mContext = activity;
40579f228124de7d98146ca526d743436f6419e2365Erik
406dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mHelper = new EditEventHelper(activity, null);
40779f228124de7d98146ca526d743436f6419e2365Erik        mHandler = new QueryHandler(activity.getContentResolver());
408dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mModel = new CalendarEventModel(activity);
4095c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa        mInputMethodManager = (InputMethodManager)
4105c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa                activity.getSystemService(Context.INPUT_METHOD_SERVICE);
41179f228124de7d98146ca526d743436f6419e2365Erik    }
41279f228124de7d98146ca526d743436f6419e2365Erik
41379f228124de7d98146ca526d743436f6419e2365Erik    @Override
41479f228124de7d98146ca526d743436f6419e2365Erik    public View onCreateView(LayoutInflater inflater, ViewGroup container,
41579f228124de7d98146ca526d743436f6419e2365Erik            Bundle savedInstanceState) {
41679f228124de7d98146ca526d743436f6419e2365Erik//        mContext.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
41779f228124de7d98146ca526d743436f6419e2365Erik        View view = inflater.inflate(R.layout.edit_event, null);
418dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        mView = new EditEventView(mContext, view, mOnDone);
41979f228124de7d98146ca526d743436f6419e2365Erik        startQuery();
42079f228124de7d98146ca526d743436f6419e2365Erik        return view;
42179f228124de7d98146ca526d743436f6419e2365Erik    }
42279f228124de7d98146ca526d743436f6419e2365Erik
42379f228124de7d98146ca526d743436f6419e2365Erik    @Override
42479f228124de7d98146ca526d743436f6419e2365Erik    public void onCreate(Bundle savedInstanceState) {
42579f228124de7d98146ca526d743436f6419e2365Erik        super.onCreate(savedInstanceState);
42659ead671b50514b49749fcd6a1d4186a270239d2Erik        if (savedInstanceState != null) {
42759ead671b50514b49749fcd6a1d4186a270239d2Erik            if (savedInstanceState.containsKey(BUNDLE_KEY_MODEL)) {
42859ead671b50514b49749fcd6a1d4186a270239d2Erik                mRestoreModel = (CalendarEventModel) savedInstanceState.getSerializable(
42959ead671b50514b49749fcd6a1d4186a270239d2Erik                        BUNDLE_KEY_MODEL);
43059ead671b50514b49749fcd6a1d4186a270239d2Erik            }
43159ead671b50514b49749fcd6a1d4186a270239d2Erik            if (savedInstanceState.containsKey(BUNDLE_KEY_EDIT_STATE)) {
43259ead671b50514b49749fcd6a1d4186a270239d2Erik                mModification = savedInstanceState.getInt(BUNDLE_KEY_EDIT_STATE);
43359ead671b50514b49749fcd6a1d4186a270239d2Erik            }
434c130d9d5e0d178585721428e394df0c8e0a6729fErik            if (savedInstanceState.containsKey(BUNDLE_KEY_EVENT)) {
435c130d9d5e0d178585721428e394df0c8e0a6729fErik                mEventBundle = (EventBundle) savedInstanceState.getSerializable(BUNDLE_KEY_EVENT);
436c130d9d5e0d178585721428e394df0c8e0a6729fErik            }
43759ead671b50514b49749fcd6a1d4186a270239d2Erik        }
43879f228124de7d98146ca526d743436f6419e2365Erik    }
4395f62079ab9daefe95ede87631766e99e8b4a2220Erik
4405f62079ab9daefe95ede87631766e99e8b4a2220Erik
4415f62079ab9daefe95ede87631766e99e8b4a2220Erik    @Override
4425f62079ab9daefe95ede87631766e99e8b4a2220Erik    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
4435f62079ab9daefe95ede87631766e99e8b4a2220Erik        super.onCreateOptionsMenu(menu, inflater);
4445f62079ab9daefe95ede87631766e99e8b4a2220Erik        inflater.inflate(R.menu.edit_event_title_bar, menu);
4455f62079ab9daefe95ede87631766e99e8b4a2220Erik        synchronized (this) {
4465f62079ab9daefe95ede87631766e99e8b4a2220Erik            mMenu = menu;
447c07a57fb7436d807ad505fa7319b9de13f91e741Erik            updateActionBar();
4485f62079ab9daefe95ede87631766e99e8b4a2220Erik        }
4495f62079ab9daefe95ede87631766e99e8b4a2220Erik    }
4505f62079ab9daefe95ede87631766e99e8b4a2220Erik
4515f62079ab9daefe95ede87631766e99e8b4a2220Erik    @Override
4525f62079ab9daefe95ede87631766e99e8b4a2220Erik    public boolean onOptionsItemSelected(MenuItem item) {
4535f62079ab9daefe95ede87631766e99e8b4a2220Erik        switch (item.getItemId()) {
4545f62079ab9daefe95ede87631766e99e8b4a2220Erik            case R.id.action_done:
4555f62079ab9daefe95ede87631766e99e8b4a2220Erik                if (EditEventHelper.canModifyEvent(mModel) || EditEventHelper.canRespond(mModel)) {
4565f62079ab9daefe95ede87631766e99e8b4a2220Erik                    if (mView != null && mView.prepareForSave()) {
45746cde5cff48d6862f492f60c6a6336bfc047ce25Erik                        if (mModification == Utils.MODIFY_UNINITIALIZED) {
45846cde5cff48d6862f492f60c6a6336bfc047ce25Erik                            mModification = Utils.MODIFY_ALL;
45946cde5cff48d6862f492f60c6a6336bfc047ce25Erik                        }
4605f62079ab9daefe95ede87631766e99e8b4a2220Erik                        mOnDone.setDoneCode(Utils.DONE_SAVE | Utils.DONE_EXIT);
4615f62079ab9daefe95ede87631766e99e8b4a2220Erik                        mOnDone.run();
4625f62079ab9daefe95ede87631766e99e8b4a2220Erik                    } else {
4635f62079ab9daefe95ede87631766e99e8b4a2220Erik                        mOnDone.setDoneCode(Utils.DONE_REVERT);
4645f62079ab9daefe95ede87631766e99e8b4a2220Erik                        mOnDone.run();
4655f62079ab9daefe95ede87631766e99e8b4a2220Erik                    }
4665f62079ab9daefe95ede87631766e99e8b4a2220Erik                } else if (EditEventHelper.canAddReminders(mModel) && mModel.mId != -1
4675f62079ab9daefe95ede87631766e99e8b4a2220Erik                        && mOriginalModel != null && mView.prepareForSave()) {
4685f62079ab9daefe95ede87631766e99e8b4a2220Erik                    saveReminders();
4695f62079ab9daefe95ede87631766e99e8b4a2220Erik                    mOnDone.setDoneCode(Utils.DONE_EXIT);
4705f62079ab9daefe95ede87631766e99e8b4a2220Erik                    mOnDone.run();
4715f62079ab9daefe95ede87631766e99e8b4a2220Erik                } else {
4725f62079ab9daefe95ede87631766e99e8b4a2220Erik                    mOnDone.setDoneCode(Utils.DONE_REVERT);
4735f62079ab9daefe95ede87631766e99e8b4a2220Erik                    mOnDone.run();
4745f62079ab9daefe95ede87631766e99e8b4a2220Erik                }
4755f62079ab9daefe95ede87631766e99e8b4a2220Erik                break;
4765f62079ab9daefe95ede87631766e99e8b4a2220Erik            case R.id.action_cancel:
4775f62079ab9daefe95ede87631766e99e8b4a2220Erik                mOnDone.setDoneCode(Utils.DONE_REVERT);
4785f62079ab9daefe95ede87631766e99e8b4a2220Erik                mOnDone.run();
4795f62079ab9daefe95ede87631766e99e8b4a2220Erik                break;
4805f62079ab9daefe95ede87631766e99e8b4a2220Erik            case R.id.action_delete:
4815f62079ab9daefe95ede87631766e99e8b4a2220Erik                mOnDone.setDoneCode(Utils.DONE_DELETE);
4825f62079ab9daefe95ede87631766e99e8b4a2220Erik                mOnDone.run();
4835f62079ab9daefe95ede87631766e99e8b4a2220Erik                break;
484c07a57fb7436d807ad505fa7319b9de13f91e741Erik            case R.id.action_edit:
485c07a57fb7436d807ad505fa7319b9de13f91e741Erik                if (!TextUtils.isEmpty(mModel.mRrule)) {
48646cde5cff48d6862f492f60c6a6336bfc047ce25Erik                    displayEditWhichDialog();
487c07a57fb7436d807ad505fa7319b9de13f91e741Erik                } else {
488c07a57fb7436d807ad505fa7319b9de13f91e741Erik                    mModification = Utils.MODIFY_ALL;
489c07a57fb7436d807ad505fa7319b9de13f91e741Erik                    updateActionBar();
490c07a57fb7436d807ad505fa7319b9de13f91e741Erik                    mView.setModification(mModification);
491c07a57fb7436d807ad505fa7319b9de13f91e741Erik                }
492c07a57fb7436d807ad505fa7319b9de13f91e741Erik                break;
4935f62079ab9daefe95ede87631766e99e8b4a2220Erik        }
4945f62079ab9daefe95ede87631766e99e8b4a2220Erik        return true;
4955f62079ab9daefe95ede87631766e99e8b4a2220Erik    }
4965f62079ab9daefe95ede87631766e99e8b4a2220Erik
4975f62079ab9daefe95ede87631766e99e8b4a2220Erik    private void saveReminders() {
4985f62079ab9daefe95ede87631766e99e8b4a2220Erik        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(3);
4995f62079ab9daefe95ede87631766e99e8b4a2220Erik        boolean changed = EditEventHelper.saveReminders(ops, mModel.mId, mModel.mReminderMinutes,
5005f62079ab9daefe95ede87631766e99e8b4a2220Erik                mOriginalModel.mReminderMinutes, false /* no force save */);
5015f62079ab9daefe95ede87631766e99e8b4a2220Erik
5025f62079ab9daefe95ede87631766e99e8b4a2220Erik        if (!changed) {
5035f62079ab9daefe95ede87631766e99e8b4a2220Erik            return;
5045f62079ab9daefe95ede87631766e99e8b4a2220Erik        }
5055f62079ab9daefe95ede87631766e99e8b4a2220Erik
5065f62079ab9daefe95ede87631766e99e8b4a2220Erik        AsyncQueryService service = new AsyncQueryService(getActivity());
5075f62079ab9daefe95ede87631766e99e8b4a2220Erik        service.startBatch(0, null, Calendars.CONTENT_URI.getAuthority(), ops, 0);
5085f62079ab9daefe95ede87631766e99e8b4a2220Erik        // Update the "hasAlarm" field for the event
5095f62079ab9daefe95ede87631766e99e8b4a2220Erik        Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, mModel.mId);
5105f62079ab9daefe95ede87631766e99e8b4a2220Erik        int len = mModel.mReminderMinutes.size();
5115f62079ab9daefe95ede87631766e99e8b4a2220Erik        boolean hasAlarm = len > 0;
5125f62079ab9daefe95ede87631766e99e8b4a2220Erik        if (hasAlarm != mOriginalModel.mHasAlarm) {
5135f62079ab9daefe95ede87631766e99e8b4a2220Erik            ContentValues values = new ContentValues();
5145f62079ab9daefe95ede87631766e99e8b4a2220Erik            values.put(Events.HAS_ALARM, hasAlarm ? 1 : 0);
5155f62079ab9daefe95ede87631766e99e8b4a2220Erik            service.startUpdate(0, null, uri, values, null, null, 0);
5165f62079ab9daefe95ede87631766e99e8b4a2220Erik        }
5175f62079ab9daefe95ede87631766e99e8b4a2220Erik
5185f62079ab9daefe95ede87631766e99e8b4a2220Erik        Toast.makeText(mContext, R.string.saving_event, Toast.LENGTH_SHORT).show();
5195f62079ab9daefe95ede87631766e99e8b4a2220Erik    }
5205f62079ab9daefe95ede87631766e99e8b4a2220Erik
52146cde5cff48d6862f492f60c6a6336bfc047ce25Erik    protected void displayEditWhichDialog() {
52279f228124de7d98146ca526d743436f6419e2365Erik        if (!TextUtils.isEmpty(mModel.mRrule) && mModification == Utils.MODIFY_UNINITIALIZED) {
5231ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan            final boolean notSynced = mModel.mSyncId == null;
52479f228124de7d98146ca526d743436f6419e2365Erik            boolean isFirstEventInSeries = mModel.mIsFirstEventInSeries;
52579f228124de7d98146ca526d743436f6419e2365Erik            int itemIndex = 0;
52679f228124de7d98146ca526d743436f6419e2365Erik            CharSequence[] items;
5271ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan
5281ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan            if (notSynced) {
5291ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan                // If this event has not been synced, then don't allow deleting
5301ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan                // or changing a single instance.
53179f228124de7d98146ca526d743436f6419e2365Erik                if (isFirstEventInSeries) {
53279f228124de7d98146ca526d743436f6419e2365Erik                    // Still display the option so the user knows all events are
53379f228124de7d98146ca526d743436f6419e2365Erik                    // changing
53479f228124de7d98146ca526d743436f6419e2365Erik                    items = new CharSequence[1];
53579f228124de7d98146ca526d743436f6419e2365Erik                } else {
53679f228124de7d98146ca526d743436f6419e2365Erik                    items = new CharSequence[2];
53779f228124de7d98146ca526d743436f6419e2365Erik                }
53879f228124de7d98146ca526d743436f6419e2365Erik            } else {
53979f228124de7d98146ca526d743436f6419e2365Erik                if (isFirstEventInSeries) {
54079f228124de7d98146ca526d743436f6419e2365Erik                    items = new CharSequence[2];
54179f228124de7d98146ca526d743436f6419e2365Erik                } else {
54279f228124de7d98146ca526d743436f6419e2365Erik                    items = new CharSequence[3];
54379f228124de7d98146ca526d743436f6419e2365Erik                }
54479f228124de7d98146ca526d743436f6419e2365Erik                items[itemIndex++] = mContext.getText(R.string.modify_event);
54579f228124de7d98146ca526d743436f6419e2365Erik            }
54679f228124de7d98146ca526d743436f6419e2365Erik            items[itemIndex++] = mContext.getText(R.string.modify_all);
54779f228124de7d98146ca526d743436f6419e2365Erik
54879f228124de7d98146ca526d743436f6419e2365Erik            // Do one more check to make sure this remains at the end of the list
54979f228124de7d98146ca526d743436f6419e2365Erik            if (!isFirstEventInSeries) {
55079f228124de7d98146ca526d743436f6419e2365Erik                items[itemIndex++] = mContext.getText(R.string.modify_all_following);
55179f228124de7d98146ca526d743436f6419e2365Erik            }
55279f228124de7d98146ca526d743436f6419e2365Erik
55379f228124de7d98146ca526d743436f6419e2365Erik            // Display the modification dialog.
55479f228124de7d98146ca526d743436f6419e2365Erik            if (mModifyDialog != null) {
55579f228124de7d98146ca526d743436f6419e2365Erik                mModifyDialog.dismiss();
55679f228124de7d98146ca526d743436f6419e2365Erik                mModifyDialog = null;
55779f228124de7d98146ca526d743436f6419e2365Erik            }
55879f228124de7d98146ca526d743436f6419e2365Erik            mModifyDialog = new AlertDialog.Builder(mContext).setOnCancelListener(
55979f228124de7d98146ca526d743436f6419e2365Erik                    new OnCancelListener() {
56079f228124de7d98146ca526d743436f6419e2365Erik                public void onCancel(DialogInterface dialog) {
56179f228124de7d98146ca526d743436f6419e2365Erik                    mContext.finish();
56279f228124de7d98146ca526d743436f6419e2365Erik                }
56379f228124de7d98146ca526d743436f6419e2365Erik            }).setTitle(R.string.edit_event_label).setItems(items, new OnClickListener() {
56479f228124de7d98146ca526d743436f6419e2365Erik                public void onClick(DialogInterface dialog, int which) {
56579f228124de7d98146ca526d743436f6419e2365Erik                    if (which == 0) {
5661ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan                        mModification = notSynced ? Utils.MODIFY_ALL : Utils.MODIFY_SELECTED;
567c07a57fb7436d807ad505fa7319b9de13f91e741Erik                        mModel.mOriginalEvent = notSynced ? null : mModel.mSyncId;
56879f228124de7d98146ca526d743436f6419e2365Erik                    } else if (which == 1) {
5691ec87639bd05857bcb2c4a0acc189c0ff413a287Michael Chan                        mModification = notSynced ? Utils.MODIFY_ALL_FOLLOWING : Utils.MODIFY_ALL;
57079f228124de7d98146ca526d743436f6419e2365Erik                    } else if (which == 2) {
57179f228124de7d98146ca526d743436f6419e2365Erik                        mModification = Utils.MODIFY_ALL_FOLLOWING;
57279f228124de7d98146ca526d743436f6419e2365Erik                    }
57379f228124de7d98146ca526d743436f6419e2365Erik
57479f228124de7d98146ca526d743436f6419e2365Erik                    mView.setModification(mModification);
575c07a57fb7436d807ad505fa7319b9de13f91e741Erik                    updateActionBar();
57679f228124de7d98146ca526d743436f6419e2365Erik                }
57779f228124de7d98146ca526d743436f6419e2365Erik            }).show();
57879f228124de7d98146ca526d743436f6419e2365Erik        }
57979f228124de7d98146ca526d743436f6419e2365Erik    }
58079f228124de7d98146ca526d743436f6419e2365Erik
58179f228124de7d98146ca526d743436f6419e2365Erik    class Done implements EditEventHelper.EditDoneRunnable {
58279f228124de7d98146ca526d743436f6419e2365Erik        private int mCode = -1;
58379f228124de7d98146ca526d743436f6419e2365Erik
58479f228124de7d98146ca526d743436f6419e2365Erik        public void setDoneCode(int code) {
58579f228124de7d98146ca526d743436f6419e2365Erik            mCode = code;
58679f228124de7d98146ca526d743436f6419e2365Erik        }
58779f228124de7d98146ca526d743436f6419e2365Erik
58879f228124de7d98146ca526d743436f6419e2365Erik        public void run() {
589dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            // We only want this to get called once, either because the user
590dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            // pressed back/home or one of the buttons on screen
591dd95df57c8c5a58a85c4c0effad5652dec14f621Erik            mSaveOnDetach = false;
5927b92da258a480284dcc15a518ea570072329a31dErik
59318a3c2e829ded43dc1e238f6a4ac054c0eb04684Michael Chan            if ((mCode & Utils.DONE_SAVE) != 0
59418a3c2e829ded43dc1e238f6a4ac054c0eb04684Michael Chan                    && mModel != null
59518a3c2e829ded43dc1e238f6a4ac054c0eb04684Michael Chan                    && (EditEventHelper.canRespond(mModel) || EditEventHelper
596304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                            .canModifyEvent(mModel)) && !mModel.equals(mOriginalModel)
597304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                    && mHelper.saveEvent(mModel, mOriginalModel, mModification)) {
598304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                int stringResource;
599304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                if (mModel.mUri != null) {
600304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                    stringResource = R.string.saving_event;
601304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                } else {
602304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                    stringResource = R.string.creating_event;
6037b92da258a480284dcc15a518ea570072329a31dErik                }
604304bf0d244d54c2c8c1799e3d43c54d197a891d8Michael Chan                Toast.makeText(mContext, stringResource, Toast.LENGTH_SHORT).show();
6057b92da258a480284dcc15a518ea570072329a31dErik            }
6067b92da258a480284dcc15a518ea570072329a31dErik
60718a3c2e829ded43dc1e238f6a4ac054c0eb04684Michael Chan            if ((mCode & Utils.DONE_DELETE) != 0 && mModel != null
60818a3c2e829ded43dc1e238f6a4ac054c0eb04684Michael Chan                    && EditEventHelper.canModifyCalendar(mModel)) {
6097b92da258a480284dcc15a518ea570072329a31dErik                long begin = mModel.mStart;
6107b92da258a480284dcc15a518ea570072329a31dErik                long end = mModel.mEnd;
6117b92da258a480284dcc15a518ea570072329a31dErik                int which = -1;
6127b92da258a480284dcc15a518ea570072329a31dErik                switch (mModification) {
6137b92da258a480284dcc15a518ea570072329a31dErik                    case Utils.MODIFY_SELECTED:
6147b92da258a480284dcc15a518ea570072329a31dErik                        which = DeleteEventHelper.DELETE_SELECTED;
6157b92da258a480284dcc15a518ea570072329a31dErik                        break;
6167b92da258a480284dcc15a518ea570072329a31dErik                    case Utils.MODIFY_ALL_FOLLOWING:
6177b92da258a480284dcc15a518ea570072329a31dErik                        which = DeleteEventHelper.DELETE_ALL_FOLLOWING;
6187b92da258a480284dcc15a518ea570072329a31dErik                        break;
6197b92da258a480284dcc15a518ea570072329a31dErik                    case Utils.MODIFY_ALL:
6207b92da258a480284dcc15a518ea570072329a31dErik                        which = DeleteEventHelper.DELETE_ALL;
6217b92da258a480284dcc15a518ea570072329a31dErik                        break;
6227b92da258a480284dcc15a518ea570072329a31dErik                }
6237b92da258a480284dcc15a518ea570072329a31dErik                DeleteEventHelper deleteHelper = new DeleteEventHelper(mContext, mContext,
6245f62079ab9daefe95ede87631766e99e8b4a2220Erik                        true /* exitWhenDone */);
6257b92da258a480284dcc15a518ea570072329a31dErik                // TODO update delete helper to use the model instead of the cursor
6267b92da258a480284dcc15a518ea570072329a31dErik                deleteHelper.delete(begin, end, mModel, which);
62779f228124de7d98146ca526d743436f6419e2365Erik            }
6287b92da258a480284dcc15a518ea570072329a31dErik
6297b92da258a480284dcc15a518ea570072329a31dErik            if ((mCode & Utils.DONE_EXIT) != 0) {
6307b92da258a480284dcc15a518ea570072329a31dErik                // This will exit the edit event screen, should be called
6317b92da258a480284dcc15a518ea570072329a31dErik                // when we want to return to the main calendar views
6325f62079ab9daefe95ede87631766e99e8b4a2220Erik                EditEventFragment.this.getActivity().finish();
6337b92da258a480284dcc15a518ea570072329a31dErik            }
6347b92da258a480284dcc15a518ea570072329a31dErik
6355c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa            // Hide a software keyboard so that user won't see it even after this Fragment's
6365c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa            // disappearing.
6375c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa            final View focusedView = mContext.getCurrentFocus();
6385c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa            if (focusedView != null) {
6395c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa                mInputMethodManager.hideSoftInputFromWindow(focusedView.getWindowToken(), 0);
6405c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa                focusedView.clearFocus();
6415c0dec1dbf64687e36e1a26dbd9526eefa963848Daisuke Miyakawa            }
64279f228124de7d98146ca526d743436f6419e2365Erik        }
64379f228124de7d98146ca526d743436f6419e2365Erik    }
64479f228124de7d98146ca526d743436f6419e2365Erik
64579f228124de7d98146ca526d743436f6419e2365Erik    @Override
64679f228124de7d98146ca526d743436f6419e2365Erik    public void onDestroy() {
647ee212201f3b7dd290eb9ca99de5b4d0b9c62acfdDmitri Plotnikov        if (mView != null) {
648ee212201f3b7dd290eb9ca99de5b4d0b9c62acfdDmitri Plotnikov            mView.setModel(null);
649ee212201f3b7dd290eb9ca99de5b4d0b9c62acfdDmitri Plotnikov        }
65079f228124de7d98146ca526d743436f6419e2365Erik        if (mModifyDialog != null) {
65179f228124de7d98146ca526d743436f6419e2365Erik            mModifyDialog.dismiss();
65279f228124de7d98146ca526d743436f6419e2365Erik            mModifyDialog = null;
65379f228124de7d98146ca526d743436f6419e2365Erik        }
6547b92da258a480284dcc15a518ea570072329a31dErik
6557b92da258a480284dcc15a518ea570072329a31dErik        super.onDestroy();
65679f228124de7d98146ca526d743436f6419e2365Erik    }
657dd95df57c8c5a58a85c4c0effad5652dec14f621Erik
658dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    @Override
659dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    public void eventsChanged() {
660dd95df57c8c5a58a85c4c0effad5652dec14f621Erik        // TODO Requery to see if event has changed
661dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    }
662dd95df57c8c5a58a85c4c0effad5652dec14f621Erik
663dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    @Override
66459ead671b50514b49749fcd6a1d4186a270239d2Erik    public void onSaveInstanceState(Bundle outState) {
66559ead671b50514b49749fcd6a1d4186a270239d2Erik        mView.prepareForSave();
66659ead671b50514b49749fcd6a1d4186a270239d2Erik        outState.putSerializable(BUNDLE_KEY_MODEL, mModel);
66759ead671b50514b49749fcd6a1d4186a270239d2Erik        outState.putInt(BUNDLE_KEY_EDIT_STATE, mModification);
668c130d9d5e0d178585721428e394df0c8e0a6729fErik        if (mEventBundle == null && mEvent != null) {
669c130d9d5e0d178585721428e394df0c8e0a6729fErik            mEventBundle = new EventBundle();
670c130d9d5e0d178585721428e394df0c8e0a6729fErik            mEventBundle.id = mEvent.id;
671c130d9d5e0d178585721428e394df0c8e0a6729fErik            if (mEvent.startTime != null) {
672c130d9d5e0d178585721428e394df0c8e0a6729fErik                mEventBundle.start = mEvent.startTime.toMillis(true);
673c130d9d5e0d178585721428e394df0c8e0a6729fErik            }
674c130d9d5e0d178585721428e394df0c8e0a6729fErik            if (mEvent.endTime != null) {
675c130d9d5e0d178585721428e394df0c8e0a6729fErik                mEventBundle.end = mEvent.startTime.toMillis(true);
676c130d9d5e0d178585721428e394df0c8e0a6729fErik            }
677c130d9d5e0d178585721428e394df0c8e0a6729fErik        }
678c130d9d5e0d178585721428e394df0c8e0a6729fErik
679c130d9d5e0d178585721428e394df0c8e0a6729fErik        outState.putSerializable(BUNDLE_KEY_EVENT, mEventBundle);
68059ead671b50514b49749fcd6a1d4186a270239d2Erik    }
68159ead671b50514b49749fcd6a1d4186a270239d2Erik
68259ead671b50514b49749fcd6a1d4186a270239d2Erik    @Override
683dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    public long getSupportedEventTypes() {
6847b92da258a480284dcc15a518ea570072329a31dErik        return EventType.USER_HOME;
685dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    }
686dd95df57c8c5a58a85c4c0effad5652dec14f621Erik
687dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    @Override
688dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    public void handleEvent(EventInfo event) {
6897b92da258a480284dcc15a518ea570072329a31dErik        // It's currently unclear if we want to save the event or not when home
6907b92da258a480284dcc15a518ea570072329a31dErik        // is pressed. When creating a new event we shouldn't save since we
6917b92da258a480284dcc15a518ea570072329a31dErik        // can't get the id of the new event easily.
6927b92da258a480284dcc15a518ea570072329a31dErik        if ((false && event.eventType == EventType.USER_HOME) || (event.eventType == EventType.GO_TO
6937b92da258a480284dcc15a518ea570072329a31dErik                && mSaveOnDetach)) {
6947b92da258a480284dcc15a518ea570072329a31dErik            if (mView != null && mView.prepareForSave()) {
6957b92da258a480284dcc15a518ea570072329a31dErik                mOnDone.setDoneCode(Utils.DONE_SAVE);
6967b92da258a480284dcc15a518ea570072329a31dErik                mOnDone.run();
6977b92da258a480284dcc15a518ea570072329a31dErik            }
6987b92da258a480284dcc15a518ea570072329a31dErik        }
699dd95df57c8c5a58a85c4c0effad5652dec14f621Erik    }
700c130d9d5e0d178585721428e394df0c8e0a6729fErik
701c130d9d5e0d178585721428e394df0c8e0a6729fErik    private class EventBundle implements Serializable {
702c130d9d5e0d178585721428e394df0c8e0a6729fErik        long id = -1;
703c130d9d5e0d178585721428e394df0c8e0a6729fErik        long start = -1;
704c130d9d5e0d178585721428e394df0c8e0a6729fErik        long end = -1;
705c130d9d5e0d178585721428e394df0c8e0a6729fErik    }
70679f228124de7d98146ca526d743436f6419e2365Erik}
707