12bebde787f9490408ceaf14166de4b016a10daf1Mason Tang/*
22bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * Copyright (C) 2010 The Android Open Source Project
32bebde787f9490408ceaf14166de4b016a10daf1Mason Tang *
42bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * Licensed under the Apache License, Version 2.0 (the "License");
52bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * you may not use this file except in compliance with the License.
62bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * You may obtain a copy of the License at
72bebde787f9490408ceaf14166de4b016a10daf1Mason Tang *
82bebde787f9490408ceaf14166de4b016a10daf1Mason Tang *      http://www.apache.org/licenses/LICENSE-2.0
92bebde787f9490408ceaf14166de4b016a10daf1Mason Tang *
102bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * Unless required by applicable law or agreed to in writing, software
112bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * distributed under the License is distributed on an "AS IS" BASIS,
122bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * See the License for the specific language governing permissions and
142bebde787f9490408ceaf14166de4b016a10daf1Mason Tang * limitations under the License.
152bebde787f9490408ceaf14166de4b016a10daf1Mason Tang */
162bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
172bebde787f9490408ceaf14166de4b016a10daf1Mason Tangpackage com.android.calendar;
182bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
192c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport static android.provider.CalendarContract.EXTRA_EVENT_ALL_DAY;
202c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport static android.provider.CalendarContract.EXTRA_EVENT_BEGIN_TIME;
212c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport static android.provider.CalendarContract.EXTRA_EVENT_END_TIME;
222c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport static com.android.calendar.CalendarController.EVENT_EDIT_ON_LAUNCH;
232bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
248f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelsonimport android.animation.Animator;
258f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelsonimport android.animation.AnimatorListenerAdapter;
268f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelsonimport android.animation.ObjectAnimator;
272bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.app.Activity;
2871d08836af4cf5fc45d340b1883044a9f8290232Michael Chanimport android.app.Dialog;
2971d08836af4cf5fc45d340b1883044a9f8290232Michael Chanimport android.app.DialogFragment;
30ef31a98202852807f460af49ae3313d1ccf5e288Andy McFaddenimport android.app.Service;
312bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.ActivityNotFoundException;
32364309f0bb9c3aeee8efd0c24faf478f7c62c6d7Erikimport android.content.ContentProviderOperation;
332bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.ContentResolver;
342bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.ContentUris;
352bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.ContentValues;
362bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.Context;
37b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelsonimport android.content.DialogInterface;
382bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.Intent;
391ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelsonimport android.content.SharedPreferences;
402c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport android.content.pm.ApplicationInfo;
412c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport android.content.pm.PackageManager;
422c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport android.content.pm.PackageManager.NameNotFoundException;
432bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.content.res.Resources;
442bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.database.Cursor;
452bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.graphics.Rect;
462c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport android.graphics.drawable.Drawable;
472bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.net.Uri;
482bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.os.Bundle;
49a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract;
50a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
51a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars;
52a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Events;
531ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelsonimport android.provider.CalendarContract.Reminders;
54cb81189e4868769ea016253eca104e46df2f033aErikimport android.provider.ContactsContract;
552bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.provider.ContactsContract.CommonDataKinds;
562bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.provider.ContactsContract.Intents;
572bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.provider.ContactsContract.QuickContact;
588ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chanimport android.text.Spannable;
5973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFaddenimport android.text.SpannableString;
608ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chanimport android.text.SpannableStringBuilder;
6173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFaddenimport android.text.Spanned;
622bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.text.TextUtils;
632bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.text.format.Time;
6473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFaddenimport android.text.method.LinkMovementMethod;
6573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFaddenimport android.text.method.MovementMethod;
668ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chanimport android.text.style.ForegroundColorSpan;
6773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFaddenimport android.text.style.URLSpan;
682bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.text.util.Linkify;
692bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.text.util.Rfc822Token;
702bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.util.Log;
7171d08836af4cf5fc45d340b1883044a9f8290232Michael Chanimport android.view.Gravity;
722bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.view.LayoutInflater;
7360f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelsonimport android.view.Menu;
7460f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelsonimport android.view.MenuInflater;
7560f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelsonimport android.view.MenuItem;
762bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.view.MotionEvent;
772bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.view.View;
78cb81189e4868769ea016253eca104e46df2f033aErikimport android.view.View.OnClickListener;
79cb81189e4868769ea016253eca104e46df2f033aErikimport android.view.View.OnTouchListener;
802bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.view.ViewGroup;
8171d08836af4cf5fc45d340b1883044a9f8290232Michael Chanimport android.view.Window;
8271d08836af4cf5fc45d340b1883044a9f8290232Michael Chanimport android.view.WindowManager;
83259b8f9a21fffd3858218581e9daaf689b6b888fErikimport android.view.accessibility.AccessibilityEvent;
84259b8f9a21fffd3858218581e9daaf689b6b888fErikimport android.view.accessibility.AccessibilityManager;
852bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.widget.AdapterView;
868b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErikimport android.widget.AdapterView.OnItemSelectedListener;
878ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chanimport android.widget.Button;
881ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelsonimport android.widget.LinearLayout;
89259b8f9a21fffd3858218581e9daaf689b6b888fErikimport android.widget.RadioButton;
90f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chanimport android.widget.RadioGroup;
91f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chanimport android.widget.RadioGroup.OnCheckedChangeListener;
928b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErikimport android.widget.ScrollView;
932bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.widget.TextView;
942bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport android.widget.Toast;
952bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
962c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.CalendarController.EventInfo;
972c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.CalendarController.EventType;
982c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.CalendarEventModel.Attendee;
992c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.CalendarEventModel.ReminderEntry;
1007da27670d2a62e213e230989b250f047012a3bbdSara Tingimport com.android.calendar.alerts.QuickResponseActivity;
1012c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.event.AttendeesView;
1022c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.event.EditEventActivity;
1032c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.event.EditEventHelper;
1042c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chanimport com.android.calendar.event.EventViewUtils;
1058a528adbba5d46fe0d566f474bc3be190511198eMichael Chanimport com.android.calendarcommon2.EventRecurrence;
1062c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
1072bebde787f9490408ceaf14166de4b016a10daf1Mason Tangimport java.util.ArrayList;
1081ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelsonimport java.util.Arrays;
1091ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelsonimport java.util.Collections;
110259b8f9a21fffd3858218581e9daaf689b6b888fErikimport java.util.List;
1118b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErikimport java.util.regex.Pattern;
112f6f797769a5cac9f9796574fe6c5ca767b1c269aIsaac Katzenelson
113f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chanpublic class EventInfoFragment extends DialogFragment implements OnCheckedChangeListener,
114b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson        CalendarController.EventHandler, OnClickListener, DeleteEventHelper.DeleteNotifyListener {
11583efa2d50deca53c9937b19a379045c31b541cb7Michael Chan
116d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    public static final boolean DEBUG = false;
1172bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1182c7c851a4e40afa83a741ec39d44425b705a712eMichael Chan    public static final String TAG = "EventInfoFragment";
1192bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
12060f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    protected static final String BUNDLE_KEY_EVENT_ID = "key_event_id";
12160f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    protected static final String BUNDLE_KEY_START_MILLIS = "key_start_millis";
12260f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    protected static final String BUNDLE_KEY_END_MILLIS = "key_end_millis";
12360f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    protected static final String BUNDLE_KEY_IS_DIALOG = "key_fragment_is_dialog";
124b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson    protected static final String BUNDLE_KEY_DELETE_DIALOG_VISIBLE = "key_delete_dialog_visible";
1257ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    protected static final String BUNDLE_KEY_WINDOW_STYLE = "key_window_style";
12660f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    protected static final String BUNDLE_KEY_ATTENDEE_RESPONSE = "key_attendee_response";
12771d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
128259b8f9a21fffd3858218581e9daaf689b6b888fErik    private static final String PERIOD_SPACE = ". ";
129259b8f9a21fffd3858218581e9daaf689b6b888fErik
1302bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    /**
1312bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * These are the corresponding indices into the array of strings
1322bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * "R.array.change_response_labels" in the resource file.
1332bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     */
1342bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final int UPDATE_SINGLE = 0;
1352bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final int UPDATE_ALL = 1;
1362bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1377ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    // Style of view
1387ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    public static final int FULL_WINDOW_STYLE = 0;
1397ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    public static final int DIALOG_WINDOW_STYLE = 1;
1407ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson
1417ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    private int mWindowStyle = DIALOG_WINDOW_STYLE;
1427ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson
1432bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    // Query tokens for QueryHandler
144259b8f9a21fffd3858218581e9daaf689b6b888fErik    private static final int TOKEN_QUERY_EVENT = 1 << 0;
145259b8f9a21fffd3858218581e9daaf689b6b888fErik    private static final int TOKEN_QUERY_CALENDARS = 1 << 1;
146259b8f9a21fffd3858218581e9daaf689b6b888fErik    private static final int TOKEN_QUERY_ATTENDEES = 1 << 2;
147259b8f9a21fffd3858218581e9daaf689b6b888fErik    private static final int TOKEN_QUERY_DUPLICATE_CALENDARS = 1 << 3;
1481ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int TOKEN_QUERY_REMINDERS = 1 << 4;
1496aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting    private static final int TOKEN_QUERY_VISIBLE_CALENDARS = 1 << 5;
150259b8f9a21fffd3858218581e9daaf689b6b888fErik    private static final int TOKEN_QUERY_ALL = TOKEN_QUERY_DUPLICATE_CALENDARS
1511ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            | TOKEN_QUERY_ATTENDEES | TOKEN_QUERY_CALENDARS | TOKEN_QUERY_EVENT
1526aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting            | TOKEN_QUERY_REMINDERS | TOKEN_QUERY_VISIBLE_CALENDARS;
1536aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting
154259b8f9a21fffd3858218581e9daaf689b6b888fErik    private int mCurrentQuery = 0;
1552bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final String[] EVENT_PROJECTION = new String[] {
1572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events._ID,                  // 0  do not remove; used in DeleteEventHelper
1582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.TITLE,                // 1  do not remove; used in DeleteEventHelper
1592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.RRULE,                // 2  do not remove; used in DeleteEventHelper
1602bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.ALL_DAY,              // 3  do not remove; used in DeleteEventHelper
1612bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.CALENDAR_ID,          // 4  do not remove; used in DeleteEventHelper
1622bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.DTSTART,              // 5  do not remove; used in DeleteEventHelper
1632bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events._SYNC_ID,             // 6  do not remove; used in DeleteEventHelper
1642bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.EVENT_TIMEZONE,       // 7  do not remove; used in DeleteEventHelper
1652bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.DESCRIPTION,          // 8
1662bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Events.EVENT_LOCATION,       // 9
167693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan        Calendars.CALENDAR_ACCESS_LEVEL, // 10
168693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan        Events.DISPLAY_COLOR,        // 11 If SDK < 16, set to Calendars.CALENDAR_COLOR.
16971b221ae5d0f514352584a955630f5494f686c51Michael Chan        Events.HAS_ATTENDEE_DATA,    // 12
17071b221ae5d0f514352584a955630f5494f686c51Michael Chan        Events.ORGANIZER,            // 13
1711ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Events.HAS_ALARM,            // 14
1721ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Calendars.MAX_REMINDERS,     //15
1731ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Calendars.ALLOWED_REMINDERS, // 16
1742c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        Events.CUSTOM_APP_PACKAGE,   // 17
1752c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        Events.CUSTOM_APP_URI,       // 18
1762c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        Events.ORIGINAL_SYNC_ID,     // 19 do not remove; used in DeleteEventHelper
1772bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    };
1782bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_ID = 0;
1792bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_TITLE = 1;
1802bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_RRULE = 2;
1812bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_ALL_DAY = 3;
1822bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_CALENDAR_ID = 4;
1832bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_SYNC_ID = 6;
1842bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_EVENT_TIMEZONE = 7;
1852bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_DESCRIPTION = 8;
1862bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int EVENT_INDEX_EVENT_LOCATION = 9;
18771b221ae5d0f514352584a955630f5494f686c51Michael Chan    private static final int EVENT_INDEX_ACCESS_LEVEL = 10;
18871b221ae5d0f514352584a955630f5494f686c51Michael Chan    private static final int EVENT_INDEX_COLOR = 11;
18971b221ae5d0f514352584a955630f5494f686c51Michael Chan    private static final int EVENT_INDEX_HAS_ATTENDEE_DATA = 12;
19071b221ae5d0f514352584a955630f5494f686c51Michael Chan    private static final int EVENT_INDEX_ORGANIZER = 13;
1911ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int EVENT_INDEX_HAS_ALARM = 14;
1921ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int EVENT_INDEX_MAX_REMINDERS = 15;
1931ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int EVENT_INDEX_ALLOWED_REMINDERS = 16;
1942c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan    private static final int EVENT_INDEX_CUSTOM_APP_PACKAGE = 17;
1952c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan    private static final int EVENT_INDEX_CUSTOM_APP_URI = 18;
1961ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
1972bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final String[] ATTENDEES_PROJECTION = new String[] {
1982bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Attendees._ID,                      // 0
1992bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Attendees.ATTENDEE_NAME,            // 1
2002bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Attendees.ATTENDEE_EMAIL,           // 2
2012bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Attendees.ATTENDEE_RELATIONSHIP,    // 3
2022bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Attendees.ATTENDEE_STATUS,          // 4
203ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        Attendees.ATTENDEE_IDENTITY,        // 5
204ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        Attendees.ATTENDEE_ID_NAMESPACE     // 6
2052bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    };
2062bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int ATTENDEES_INDEX_ID = 0;
2072bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int ATTENDEES_INDEX_NAME = 1;
2082bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int ATTENDEES_INDEX_EMAIL = 2;
2092bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int ATTENDEES_INDEX_RELATIONSHIP = 3;
2102bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final int ATTENDEES_INDEX_STATUS = 4;
211ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting    private static final int ATTENDEES_INDEX_IDENTITY = 5;
212ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting    private static final int ATTENDEES_INDEX_ID_NAMESPACE = 6;
2132bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
214693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan    static {
215fac2d1594f7ecae8e50dc7790ce67de0c9b70d22Sara Ting        if (!Utils.isJellybeanOrLater()) {
216693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            EVENT_PROJECTION[EVENT_INDEX_COLOR] = Calendars.CALENDAR_COLOR;
217693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            EVENT_PROJECTION[EVENT_INDEX_CUSTOM_APP_PACKAGE] = Events._ID; // dummy value
218693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            EVENT_PROJECTION[EVENT_INDEX_CUSTOM_APP_URI] = Events._ID; // dummy value
219693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan
220693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            ATTENDEES_PROJECTION[ATTENDEES_INDEX_IDENTITY] = Attendees._ID; // dummy value
221693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            ATTENDEES_PROJECTION[ATTENDEES_INDEX_ID_NAMESPACE] = Attendees._ID; // dummy value
222693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan        }
223693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan    }
224693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan
2252bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
2262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private static final String ATTENDEES_SORT_ORDER = Attendees.ATTENDEE_NAME + " ASC, "
2282bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            + Attendees.ATTENDEE_EMAIL + " ASC";
2292bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2301ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final String[] REMINDERS_PROJECTION = new String[] {
2311ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Reminders._ID,                      // 0
2321ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Reminders.MINUTES,            // 1
2331ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Reminders.METHOD           // 2
2341ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    };
2351ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int REMINDERS_INDEX_ID = 0;
2361ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int REMINDERS_MINUTES_ID = 1;
2371ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final int REMINDERS_METHOD_ID = 2;
2381ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
2391ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static final String REMINDERS_WHERE = Reminders.EVENT_ID + "=?";
2401ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
2412bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final String[] CALENDARS_PROJECTION = new String[] {
2422bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Calendars._ID,           // 0
243ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik        Calendars.CALENDAR_DISPLAY_NAME,  // 1
2442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Calendars.OWNER_ACCOUNT, // 2
24542896f76d81dbae873614340a3a78b29e7d463d2Sara Ting        Calendars.CAN_ORGANIZER_RESPOND, // 3
24642896f76d81dbae873614340a3a78b29e7d463d2Sara Ting        Calendars.ACCOUNT_NAME // 4
2472bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    };
2482bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final int CALENDARS_INDEX_DISPLAY_NAME = 1;
2492bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final int CALENDARS_INDEX_OWNER_ACCOUNT = 2;
2502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final int CALENDARS_INDEX_OWNER_CAN_RESPOND = 3;
25142896f76d81dbae873614340a3a78b29e7d463d2Sara Ting    static final int CALENDARS_INDEX_ACCOUNT_NAME = 4;
2522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2532bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    static final String CALENDARS_WHERE = Calendars._ID + "=?";
254ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik    static final String CALENDARS_DUPLICATE_NAME_WHERE = Calendars.CALENDAR_DISPLAY_NAME + "=?";
2556aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting    static final String CALENDARS_VISIBLE_WHERE = Calendars.VISIBLE + "=?";
2562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
257fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    private static final String NANP_ALLOWED_SYMBOLS = "()+-*#.";
258fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    private static final int NANP_MIN_DIGITS = 7;
259fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    private static final int NANP_MAX_DIGITS = 11;
260fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
261fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
2622bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private View mView;
2632bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2642bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private Uri mUri;
2652bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private long mEventId;
2662bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private Cursor mEventCursor;
2672bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private Cursor mAttendeesCursor;
2682bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private Cursor mCalendarsCursor;
2691ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private Cursor mRemindersCursor;
2701ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
2710a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan    private static float mScale = 0; // Used for supporting different screen densities
2722bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2732c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan    private static int mCustomAppIconSize = 32;
2742c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
2752bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private long mStartMillis;
2762bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private long mEndMillis;
2778b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan    private boolean mAllDay;
2782bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2792bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean mHasAttendeeData;
28083efa2d50deca53c9937b19a379045c31b541cb7Michael Chan    private String mEventOrganizerEmail;
28183efa2d50deca53c9937b19a379045c31b541cb7Michael Chan    private String mEventOrganizerDisplayName = "";
2822bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean mIsOrganizer;
283d845fbe558d5229102b58cce70a1b29fe6cb6967Erik    private long mCalendarOwnerAttendeeId = EditEventHelper.ATTENDEE_ID_NONE;
284352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan    private boolean mOwnerCanRespond;
28542896f76d81dbae873614340a3a78b29e7d463d2Sara Ting    private String mSyncAccountName;
2862bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private String mCalendarOwnerAccount;
2872bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean mCanModifyCalendar;
28865eeb79e62034d706503ce29d88c0e05ebd726feRoboErik    private boolean mCanModifyEvent;
2892bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean mIsBusyFreeCalendar;
2902bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private int mNumOfAttendees;
2912bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private EditResponseHelper mEditResponseHelper;
292b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson    private boolean mDeleteDialogVisible = false;
293b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson    private DeleteEventHelper mDeleteHelper;
2942bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
2952bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private int mOriginalAttendeeResponse;
2966bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson    private int mAttendeeResponseFromIntent = Attendees.ATTENDEE_STATUS_NONE;
2976bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson    private int mUserSetResponse = Attendees.ATTENDEE_STATUS_NONE;
2982bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean mIsRepeating;
2991ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private boolean mHasAlarm;
3001ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private int mMaxReminders;
3011ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private String mCalendarAllowedReminders;
302b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson    // Used to prevent saving changes in event if it is being deleted.
303b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson    private boolean mEventDeletionStarted = false;
3042bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
305259b8f9a21fffd3858218581e9daaf689b6b888fErik    private TextView mTitle;
30675f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting    private TextView mWhenDateTime;
307259b8f9a21fffd3858218581e9daaf689b6b888fErik    private TextView mWhere;
30899704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan    private ExpandableTextView mDesc;
309c0624ee90e59386b06a01b3415d0bb4e38f40db7Isaac Katzenelson    private AttendeesView mLongAttendees;
3107ffa24cba2977925b737e6bd39be59ba39609611Sara Ting    private Button emailAttendeesButton;
311d8353fb85ef59a88580125207be9c914a8586758RoboErik    private Menu mMenu = null;
312fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson    private View mHeadlines;
3131ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private ScrollView mScrollView;
3148f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson    private View mLoadingMsgView;
3158f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson    private ObjectAnimator mAnimateAlpha;
316263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson    private long mLoadingMsgStartTime;
3178f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson    private static final int FADE_IN_TIME = 300;   // in milliseconds
318263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson    private static final int LOADING_MSG_DELAY = 600;   // in milliseconds
319263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson    private static final int LOADING_MSG_MIN_DISPLAY_TIME = 600;
32080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    private boolean mNoCrossFade = false;  // Used to prevent repeated cross-fade
3218f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
322259b8f9a21fffd3858218581e9daaf689b6b888fErik
32373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    private static final Pattern mWildcardPattern = Pattern.compile("^.*$");
3242bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
3252bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    ArrayList<Attendee> mAcceptedAttendees = new ArrayList<Attendee>();
3262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    ArrayList<Attendee> mDeclinedAttendees = new ArrayList<Attendee>();
3272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    ArrayList<Attendee> mTentativeAttendees = new ArrayList<Attendee>();
3282bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    ArrayList<Attendee> mNoResponseAttendees = new ArrayList<Attendee>();
329cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting    ArrayList<String> mToEmails = new ArrayList<String>();
330cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting    ArrayList<String> mCcEmails = new ArrayList<String>();
3312bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private int mColor;
3322bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
3331ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
3341ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private int mDefaultReminderMinutes;
335ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson    private final ArrayList<LinearLayout> mReminderViews = new ArrayList<LinearLayout>(0);
3361ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    public ArrayList<ReminderEntry> mReminders;
3377f078b716fa7f1d374af9af3dad05d2e249e18c8RoboErik    public ArrayList<ReminderEntry> mOriginalReminders = new ArrayList<ReminderEntry>();
3387f078b716fa7f1d374af9af3dad05d2e249e18c8RoboErik    public ArrayList<ReminderEntry> mUnsupportedReminders = new ArrayList<ReminderEntry>();
3398b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik    private boolean mUserModifiedReminders = false;
3401ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
3411ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    /**
3421ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * Contents of the "minutes" spinner.  This has default values from the XML file, augmented
3431ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * with any additional values that were already associated with the event.
3441ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     */
3451ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private ArrayList<Integer> mReminderMinuteValues;
3461ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private ArrayList<String> mReminderMinuteLabels;
3471ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
3481ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    /**
3491ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * Contents of the "methods" spinner.  The "values" list specifies the method constant
3501ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * (e.g. {@link Reminders#METHOD_ALERT}) associated with the labels.  Any methods that
3511ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * aren't allowed by the Calendar will be removed.
3521ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     */
3531ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private ArrayList<Integer> mReminderMethodValues;
3541ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private ArrayList<String> mReminderMethodLabels;
3551ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
3562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private QueryHandler mHandler;
3572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
358b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson
359ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson    private final Runnable mTZUpdater = new Runnable() {
360cb81189e4868769ea016253eca104e46df2f033aErik        @Override
361cb81189e4868769ea016253eca104e46df2f033aErik        public void run() {
362cb81189e4868769ea016253eca104e46df2f033aErik            updateEvent(mView);
363cb81189e4868769ea016253eca104e46df2f033aErik        }
364cb81189e4868769ea016253eca104e46df2f033aErik    };
365cb81189e4868769ea016253eca104e46df2f033aErik
366ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson    private final Runnable mLoadingMsgAlphaUpdater = new Runnable() {
367263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson        @Override
368263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson        public void run() {
369263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson            // Since this is run after a delay, make sure to only show the message
370263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson            // if the event's data is not shown yet.
371263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson            if (!mAnimateAlpha.isRunning() && mScrollView.getAlpha() == 0) {
372263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                mLoadingMsgStartTime = System.currentTimeMillis();
373263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                mLoadingMsgView.setAlpha(1);
374263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson            }
375263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson        }
376263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson    };
377263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson
3788b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik    private OnItemSelectedListener mReminderChangeListener;
3798b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik
3807ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    private static int mDialogWidth = 500;
3817ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson    private static int mDialogHeight = 600;
3820aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson    private static int DIALOG_TOP_MARGIN = 8;
38371d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    private boolean mIsDialog = false;
3847c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    private boolean mIsPaused = true;
3857c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    private boolean mDismissOnResume = false;
38671d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    private int mX = -1;
38771d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    private int mY = -1;
3880aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson    private int mMinTop;         // Dialog cannot be above this location
38910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson    private boolean mIsTabletConfig;
39010b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson    private Activity mActivity;
391be2a432034e96c9f2fbf333cd7fe6489312bbeaaMichael Chan    private Context mContext;
39271d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
3932bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private class QueryHandler extends AsyncQueryService {
3942bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        public QueryHandler(Context context) {
3952bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            super(context);
3962bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
3972bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
3982bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        @Override
3992bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
4004003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            // if the activity is finishing, then close the cursor and return
4014003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            final Activity activity = getActivity();
4024003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            if (activity == null || activity.isFinishing()) {
40347f6cc6909665e4f6f8d85f29bfd588688463c66Isaac Katzenelson                if (cursor != null) {
40447f6cc6909665e4f6f8d85f29bfd588688463c66Isaac Katzenelson                    cursor.close();
40547f6cc6909665e4f6f8d85f29bfd588688463c66Isaac Katzenelson                }
4064003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang                return;
4074003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            }
4084003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
4092bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            switch (token) {
4102bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case TOKEN_QUERY_EVENT:
4112bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mEventCursor = Utils.matrixCursorFromCursor(cursor);
4122bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                if (initEventCursor()) {
4132bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    // The cursor is empty. This can happen if the event was
4142bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    // deleted.
4152bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    // FRAG_TODO we should no longer rely on Activity.finish()
4161df2ca65a852fda463b1d787cd4f81680103b6a2Mason Tang                    activity.finish();
4172bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    return;
4182bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                }
4192bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                updateEvent(mView);
420e35a032c939f357ce435711b2fd8de1887a05011RoboErik                prepareReminders();
4212bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
4222bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                // start calendar query
4232bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                Uri uri = Calendars.CONTENT_URI;
4242bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                String[] args = new String[] {
4252bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        Long.toString(mEventCursor.getLong(EVENT_INDEX_CALENDAR_ID))};
4262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                startQuery(TOKEN_QUERY_CALENDARS, null, uri, CALENDARS_PROJECTION,
4272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        CALENDARS_WHERE, args, null);
4282bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                break;
4292bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case TOKEN_QUERY_CALENDARS:
4302bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mCalendarsCursor = Utils.matrixCursorFromCursor(cursor);
4312bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                updateCalendar(mView);
4324003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang                // FRAG_TODO fragments shouldn't set the title anymore
4332bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                updateTitle();
4342bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
435352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                if (!mIsBusyFreeCalendar) {
436352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    args = new String[] { Long.toString(mEventId) };
437352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
438352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    // start attendees query
439352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    uri = Attendees.CONTENT_URI;
440352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    startQuery(TOKEN_QUERY_ATTENDEES, null, uri, ATTENDEES_PROJECTION,
441352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                            ATTENDEES_WHERE, args, ATTENDEES_SORT_ORDER);
442259b8f9a21fffd3858218581e9daaf689b6b888fErik                } else {
443259b8f9a21fffd3858218581e9daaf689b6b888fErik                    sendAccessibilityEventIfQueryDone(TOKEN_QUERY_ATTENDEES);
4442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                }
4451ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                if (mHasAlarm) {
4461ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                    // start reminders query
4471ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                    args = new String[] { Long.toString(mEventId) };
4481ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                    uri = Reminders.CONTENT_URI;
4491ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                    startQuery(TOKEN_QUERY_REMINDERS, null, uri,
4501ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                            REMINDERS_PROJECTION, REMINDERS_WHERE, args, null);
4511ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                } else {
4521ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                    sendAccessibilityEventIfQueryDone(TOKEN_QUERY_REMINDERS);
4531ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                }
4542bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                break;
4552bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case TOKEN_QUERY_ATTENDEES:
4562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mAttendeesCursor = Utils.matrixCursorFromCursor(cursor);
4572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                initAttendeesCursor(mView);
4582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                updateResponse(mView);
4592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                break;
4601ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            case TOKEN_QUERY_REMINDERS:
4611ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                mRemindersCursor = Utils.matrixCursorFromCursor(cursor);
4621ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                initReminders(mView, mRemindersCursor);
4631ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                break;
4646aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting            case TOKEN_QUERY_VISIBLE_CALENDARS:
4656aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                if (cursor.getCount() > 1) {
4666aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    // Start duplicate calendars query to detect whether to add the calendar
4676aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    // email to the calendar owner display.
4686aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    String displayName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME);
4696aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    mHandler.startQuery(TOKEN_QUERY_DUPLICATE_CALENDARS, null,
4706aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                            Calendars.CONTENT_URI, CALENDARS_PROJECTION,
4716aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                            CALENDARS_DUPLICATE_NAME_WHERE, new String[] {displayName}, null);
4726aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                } else {
4736aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    // Don't need to display the calendar owner when there is only a single
4746aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    // calendar.  Skip the duplicate calendars query.
4756aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    setVisibilityCommon(mView, R.id.calendar_container, View.GONE);
4766aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    mCurrentQuery |= TOKEN_QUERY_DUPLICATE_CALENDARS;
4776aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                }
4786aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                break;
4792bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case TOKEN_QUERY_DUPLICATE_CALENDARS:
48071b221ae5d0f514352584a955630f5494f686c51Michael Chan                Resources res = activity.getResources();
48171b221ae5d0f514352584a955630f5494f686c51Michael Chan                SpannableStringBuilder sb = new SpannableStringBuilder();
48271b221ae5d0f514352584a955630f5494f686c51Michael Chan
48371b221ae5d0f514352584a955630f5494f686c51Michael Chan                // Calendar display name
4842bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                String calendarName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME);
48571b221ae5d0f514352584a955630f5494f686c51Michael Chan                sb.append(calendarName);
48671b221ae5d0f514352584a955630f5494f686c51Michael Chan
48771b221ae5d0f514352584a955630f5494f686c51Michael Chan                // Show email account if display name is not unique and
48871b221ae5d0f514352584a955630f5494f686c51Michael Chan                // display name != email
48971b221ae5d0f514352584a955630f5494f686c51Michael Chan                String email = mCalendarsCursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT);
4906aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                if (cursor.getCount() > 1 && !calendarName.equalsIgnoreCase(email) &&
4916aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                        Utils.isValidEmail(email)) {
49271b221ae5d0f514352584a955630f5494f686c51Michael Chan                    sb.append(" (").append(email).append(")");
49371b221ae5d0f514352584a955630f5494f686c51Michael Chan                }
49471b221ae5d0f514352584a955630f5494f686c51Michael Chan
4956aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                setVisibilityCommon(mView, R.id.calendar_container, View.VISIBLE);
4966aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                setTextCommon(mView, R.id.calendar_name, sb);
4972bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                break;
4982bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            }
4992bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            cursor.close();
500259b8f9a21fffd3858218581e9daaf689b6b888fErik            sendAccessibilityEventIfQueryDone(token);
5016aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting
5026aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting            // All queries are done, show the view.
503263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson            if (mCurrentQuery == TOKEN_QUERY_ALL) {
504263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                if (mLoadingMsgView.getAlpha() == 1) {
505263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                    // Loading message is showing, let it stay a bit more (to prevent
506263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                    // flashing) by adding a start delay to the event animation
507263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                    long timeDiff = LOADING_MSG_MIN_DISPLAY_TIME - (System.currentTimeMillis() -
508263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                            mLoadingMsgStartTime);
509263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                    if (timeDiff > 0) {
510263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                        mAnimateAlpha.setStartDelay(timeDiff);
511263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                    }
512263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                }
51380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                if (!mAnimateAlpha.isRunning() &&!mAnimateAlpha.isStarted() && !mNoCrossFade) {
51480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                    mAnimateAlpha.start();
51580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                } else {
51680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                    mScrollView.setAlpha(1);
51780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                    mLoadingMsgView.setVisibility(View.GONE);
51880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                }
519263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson            }
5202bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
5212bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
5222bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
523259b8f9a21fffd3858218581e9daaf689b6b888fErik    private void sendAccessibilityEventIfQueryDone(int token) {
524259b8f9a21fffd3858218581e9daaf689b6b888fErik        mCurrentQuery |= token;
525259b8f9a21fffd3858218581e9daaf689b6b888fErik        if (mCurrentQuery == TOKEN_QUERY_ALL) {
526259b8f9a21fffd3858218581e9daaf689b6b888fErik            sendAccessibilityEvent();
527259b8f9a21fffd3858218581e9daaf689b6b888fErik        }
528259b8f9a21fffd3858218581e9daaf689b6b888fErik    }
529259b8f9a21fffd3858218581e9daaf689b6b888fErik
5300a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan    public EventInfoFragment(Context context, Uri uri, long startMillis, long endMillis,
5317ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            int attendeeResponse, boolean isDialog, int windowStyle) {
5327ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson
5332c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        Resources r = context.getResources();
5342c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        if (mScale == 0) {
5352c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            mScale = context.getResources().getDisplayMetrics().density;
5362c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (mScale != 1) {
5372c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                mCustomAppIconSize *= mScale;
5382c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                if (isDialog) {
5397ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson                    DIALOG_TOP_MARGIN *= mScale;
5407ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson                }
5410a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan            }
5420a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan        }
543363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan        if (isDialog) {
544363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan            setDialogSize(r);
545363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan        }
54660f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        mIsDialog = isDialog;
547c0624ee90e59386b06a01b3415d0bb4e38f40db7Isaac Katzenelson
5482fc6b79dfb06812baf2e6c547f3ffee83b5c3e9aMichael Chan        setStyle(DialogFragment.STYLE_NO_TITLE, 0);
5492bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mUri = uri;
5502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mStartMillis = startMillis;
5512bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mEndMillis = endMillis;
5522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mAttendeeResponseFromIntent = attendeeResponse;
5537ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        mWindowStyle = windowStyle;
5542bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
5552bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
556ef31a98202852807f460af49ae3313d1ccf5e288Andy McFadden    // This is currently required by the fragment manager.
55760f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    public EventInfoFragment() {
55860f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    }
55960f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson
56060f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson
56160f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson
5620a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan    public EventInfoFragment(Context context, long eventId, long startMillis, long endMillis,
5637ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            int attendeeResponse, boolean isDialog, int windowStyle) {
5640a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan        this(context, ContentUris.withAppendedId(Events.CONTENT_URI, eventId), startMillis,
5657ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson                endMillis, attendeeResponse, isDialog, windowStyle);
5664003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        mEventId = eventId;
5674003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang    }
5684003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
56971d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    @Override
57071d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    public void onActivityCreated(Bundle savedInstanceState) {
57171d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        super.onActivityCreated(savedInstanceState);
57271d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
5738b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik        mReminderChangeListener = new OnItemSelectedListener() {
5748b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            @Override
5758b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
5768b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                Integer prevValue = (Integer) parent.getTag();
5778b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                if (prevValue == null || prevValue != position) {
5788b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    parent.setTag(position);
5798b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mUserModifiedReminders = true;
5808b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                }
5818b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            }
5828b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik
5838b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            @Override
5848b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            public void onNothingSelected(AdapterView<?> parent) {
5858b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                // do nothing
5868b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            }
5878b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik
5888b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik        };
5898b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik
59071d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        if (savedInstanceState != null) {
59171d08836af4cf5fc45d340b1883044a9f8290232Michael Chan            mIsDialog = savedInstanceState.getBoolean(BUNDLE_KEY_IS_DIALOG, false);
5927ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            mWindowStyle = savedInstanceState.getInt(BUNDLE_KEY_WINDOW_STYLE,
5937ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson                    DIALOG_WINDOW_STYLE);
59471d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        }
59571d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
59671d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        if (mIsDialog) {
59771d08836af4cf5fc45d340b1883044a9f8290232Michael Chan            applyDialogParams();
59871d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        }
599825b8ca1ea39c0da4620f5aaaeeb1fa40e7e8efdMichael Chan        mContext = getActivity();
60071d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    }
60171d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
60271d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    private void applyDialogParams() {
60371d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        Dialog dialog = getDialog();
60471d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        dialog.setCanceledOnTouchOutside(true);
60571d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
60671d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        Window window = dialog.getWindow();
60771d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
60871d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
60971d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        WindowManager.LayoutParams a = window.getAttributes();
61071d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        a.dimAmount = .4f;
61171d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
6127ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        a.width = mDialogWidth;
6137ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        a.height = mDialogHeight;
61471d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
6150b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson
6160b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson        // On tablets , do smart positioning of dialog
6170b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson        // On phones , use the whole screen
6180b1bd10dbf90e55821a555c68a8a444854e31252Isaac Katzenelson
61960f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        if (mX != -1 || mY != -1) {
6207ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            a.x = mX - mDialogWidth / 2;
6217ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            a.y = mY - mDialogHeight / 2;
6220aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson            if (a.y < mMinTop) {
6230aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson                a.y = mMinTop + DIALOG_TOP_MARGIN;
6240a01fd383c6c3ae46e28c89fa1a55cc0132a15f7Michael Chan            }
62560f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson            a.gravity = Gravity.LEFT | Gravity.TOP;
62671d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        }
62771d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        window.setAttributes(a);
62871d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    }
62971d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
6300aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson    public void setDialogParams(int x, int y, int minTop) {
63171d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        mX = x;
63271d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        mY = y;
6330aa0c61fcd2464f034d15f33db265b6d080f4af9Isaac Katzenelson        mMinTop = minTop;
63471d08836af4cf5fc45d340b1883044a9f8290232Michael Chan    }
63571d08836af4cf5fc45d340b1883044a9f8290232Michael Chan
636f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan    // Implements OnCheckedChangeListener
637f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan    @Override
638f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan    public void onCheckedChanged(RadioGroup group, int checkedId) {
6392bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // If this is not a repeating event, then don't display the dialog
6402bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // asking which events to change.
6415afc08352fb7e2679ed00d41e6e5763ad333a7ecRoboErik        mUserSetResponse = getResponseFromButtonId(checkedId);
6422bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (!mIsRepeating) {
6432bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return;
6442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
6452bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
6462bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // If the selection is the same as the original, then don't display the
6472bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // dialog asking which events to change.
648f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        if (checkedId == findButtonIdForResponse(mOriginalAttendeeResponse)) {
6492bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return;
6502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
6512bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
6522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // This is a repeating event. We need to ask the user if they mean to
6532bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // change just this one instance or all instances.
6542bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mEditResponseHelper.showDialog(mEditResponseHelper.getWhichEvents());
6552bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
6562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
6572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    public void onNothingSelected(AdapterView<?> parent) {
6582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
6592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
6602bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    @Override
6612bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    public void onAttach(Activity activity) {
6622bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        super.onAttach(activity);
66310b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        mActivity = activity;
6642bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mEditResponseHelper = new EditResponseHelper(activity);
66586550ce5323f7e3971977702fca259986c048bf6RoboErik
66686550ce5323f7e3971977702fca259986c048bf6RoboErik        if (mAttendeeResponseFromIntent != Attendees.ATTENDEE_STATUS_NONE) {
66786550ce5323f7e3971977702fca259986c048bf6RoboErik            mEditResponseHelper.setWhichEvents(UPDATE_ALL);
66886550ce5323f7e3971977702fca259986c048bf6RoboErik        }
6692bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mHandler = new QueryHandler(activity);
67060f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        if (!mIsDialog) {
67160f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson            setHasOptionsMenu(true);
67260f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        }
6732bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
6742bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
6752bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    @Override
6762bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    public View onCreateView(LayoutInflater inflater, ViewGroup container,
6772bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            Bundle savedInstanceState) {
678320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson
679320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson        if (savedInstanceState != null) {
680320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson            mIsDialog = savedInstanceState.getBoolean(BUNDLE_KEY_IS_DIALOG, false);
681320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson            mWindowStyle = savedInstanceState.getInt(BUNDLE_KEY_WINDOW_STYLE,
682320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson                    DIALOG_WINDOW_STYLE);
683320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson            mDeleteDialogVisible =
684320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson                savedInstanceState.getBoolean(BUNDLE_KEY_DELETE_DIALOG_VISIBLE,false);
685320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson
686320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson        }
687320c1b11a8238ef299a401655d1ae06ffad45a47Isaac Katzenelson
6887ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        if (mWindowStyle == DIALOG_WINDOW_STYLE) {
689cba7f1fd22e1d7ee9d8d0828f37bc08512bf6b75Michael Chan            mView = inflater.inflate(R.layout.event_info_dialog, container, false);
6907ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        } else {
6917ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            mView = inflater.inflate(R.layout.event_info, container, false);
6927ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        }
6931ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mScrollView = (ScrollView) mView.findViewById(R.id.event_info_scroll_view);
6948f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        mLoadingMsgView = mView.findViewById(R.id.event_info_loading_msg);
695259b8f9a21fffd3858218581e9daaf689b6b888fErik        mTitle = (TextView) mView.findViewById(R.id.title);
69675f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting        mWhenDateTime = (TextView) mView.findViewById(R.id.when_datetime);
697259b8f9a21fffd3858218581e9daaf689b6b888fErik        mWhere = (TextView) mView.findViewById(R.id.where);
69899704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        mDesc = (ExpandableTextView) mView.findViewById(R.id.description);
699fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        mHeadlines = mView.findViewById(R.id.event_info_headline);
700c0624ee90e59386b06a01b3415d0bb4e38f40db7Isaac Katzenelson        mLongAttendees = (AttendeesView)mView.findViewById(R.id.long_attendee_list);
70110b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        mIsTabletConfig = Utils.getConfigBool(mActivity, R.bool.tablet_config);
7022bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
7034003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        if (mUri == null) {
7044003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            // restore event ID from bundle
7054003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mEventId = savedInstanceState.getLong(BUNDLE_KEY_EVENT_ID);
7064003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mUri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventId);
7074003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mStartMillis = savedInstanceState.getLong(BUNDLE_KEY_START_MILLIS);
7084003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mEndMillis = savedInstanceState.getLong(BUNDLE_KEY_END_MILLIS);
7094003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        }
7104003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
7118f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        mAnimateAlpha = ObjectAnimator.ofFloat(mScrollView, "Alpha", 0, 1);
7128f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        mAnimateAlpha.setDuration(FADE_IN_TIME);
7138f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        mAnimateAlpha.addListener(new AnimatorListenerAdapter() {
7148f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            int defLayerType;
7158f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
7168f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            @Override
7178f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            public void onAnimationStart(Animator animation) {
7188f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                // Use hardware layer for better performance during animation
7198f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                defLayerType = mScrollView.getLayerType();
7208f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                mScrollView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
7218f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                // Ensure that the loading message is gone before showing the
7228f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                // event info
723263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson                mLoadingMsgView.removeCallbacks(mLoadingMsgAlphaUpdater);
7248f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                mLoadingMsgView.setVisibility(View.GONE);
7258f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            }
7268f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
7278f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            @Override
7288f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            public void onAnimationCancel(Animator animation) {
7298f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                mScrollView.setLayerType(defLayerType, null);
7308f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            }
7318f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
7328f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            @Override
7338f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            public void onAnimationEnd(Animator animation) {
7348f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson                mScrollView.setLayerType(defLayerType, null);
73580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                // Do not cross fade after the first time
73680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                mNoCrossFade = true;
7378f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson            }
7388f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        });
7398f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
7408f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        mLoadingMsgView.setAlpha(0);
7418f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson        mScrollView.setAlpha(0);
742263b0291b701dc2b5df7ebab53f8e6808e7be9a8Isaac Katzenelson        mLoadingMsgView.postDelayed(mLoadingMsgAlphaUpdater, LOADING_MSG_DELAY);
7438f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
7442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // start loading the data
7458f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson
7462bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mHandler.startQuery(TOKEN_QUERY_EVENT, null, mUri, EVENT_PROJECTION,
7472bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                null, null, null);
7482bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
749d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson        View b = mView.findViewById(R.id.delete);
7508ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan        b.setOnClickListener(new OnClickListener() {
7518ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan            @Override
7528ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan            public void onClick(View v) {
75369be855eccf7d1e0a4c93377db66eb4b843a1403RoboErik                if (!mCanModifyCalendar) {
75469be855eccf7d1e0a4c93377db66eb4b843a1403RoboErik                    return;
75569be855eccf7d1e0a4c93377db66eb4b843a1403RoboErik                }
756d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson                mDeleteHelper =
757d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson                        new DeleteEventHelper(mContext, mActivity, !mIsDialog && !mIsTabletConfig /* exitWhenDone */);
758b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                mDeleteHelper.setDeleteNotificationListener(EventInfoFragment.this);
759b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                mDeleteHelper.setOnDismissListener(createDeleteOnDismissListener());
760b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                mDeleteDialogVisible = true;
761b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                mDeleteHelper.delete(mStartMillis, mEndMillis, mEventId, -1, onDeleteRunnable);
762d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson            }
763d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson        });
7648ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan
76510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        // Hide Edit/Delete buttons if in full screen mode on a phone
7667ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        if (!mIsDialog && !mIsTabletConfig || mWindowStyle == EventInfoFragment.FULL_WINDOW_STYLE) {
76760f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson            mView.findViewById(R.id.event_info_buttons_container).setVisibility(View.GONE);
76860f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        }
76960f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson
770cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        // Create a listener for the email guests button
7717ffa24cba2977925b737e6bd39be59ba39609611Sara Ting        emailAttendeesButton = (Button) mView.findViewById(R.id.email_attendees_button);
772cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        if (emailAttendeesButton != null) {
773cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting            emailAttendeesButton.setOnClickListener(new View.OnClickListener() {
774cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting                @Override
775cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting                public void onClick(View v) {
776cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting                    emailAttendees();
777cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting                }
778cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting            });
779cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        }
7801ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
781cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        // Create a listener for the add reminder button
782b20942b3087dbef5483669b76e00e9b8b4d5a7b1Michael Chan        View reminderAddButton = mView.findViewById(R.id.reminder_add);
7831ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        View.OnClickListener addReminderOnClickListener = new View.OnClickListener() {
7841ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            @Override
7851ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            public void onClick(View v) {
7861ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                addReminder();
7878b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                mUserModifiedReminders = true;
7881ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            }
7891ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        };
7901ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        reminderAddButton.setOnClickListener(addReminderOnClickListener);
7911ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
7921ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // Set reminders variables
7931ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
7941ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(mActivity);
7951ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        String defaultReminderString = prefs.getString(
7961ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                GeneralPreferences.KEY_DEFAULT_REMINDER, GeneralPreferences.NO_REMINDER_STRING);
7971ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mDefaultReminderMinutes = Integer.parseInt(defaultReminderString);
7981ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        prepareReminders();
7991ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
8002bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        return mView;
8012bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
8022bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
803ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson    private final Runnable onDeleteRunnable = new Runnable() {
80489ad0822f104015625f4ca88bfdf5c1d522b6e74Erik        @Override
80589ad0822f104015625f4ca88bfdf5c1d522b6e74Erik        public void run() {
8067c6236d5553dc9f3d004ebbed794249713a11d19RoboErik            if (EventInfoFragment.this.mIsPaused) {
8077c6236d5553dc9f3d004ebbed794249713a11d19RoboErik                mDismissOnResume = true;
8087c6236d5553dc9f3d004ebbed794249713a11d19RoboErik                return;
8097c6236d5553dc9f3d004ebbed794249713a11d19RoboErik            }
81089ad0822f104015625f4ca88bfdf5c1d522b6e74Erik            if (EventInfoFragment.this.isVisible()) {
81189ad0822f104015625f4ca88bfdf5c1d522b6e74Erik                EventInfoFragment.this.dismiss();
81289ad0822f104015625f4ca88bfdf5c1d522b6e74Erik            }
81389ad0822f104015625f4ca88bfdf5c1d522b6e74Erik        }
81489ad0822f104015625f4ca88bfdf5c1d522b6e74Erik    };
81589ad0822f104015625f4ca88bfdf5c1d522b6e74Erik
8162bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void updateTitle() {
8172bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Resources res = getActivity().getResources();
8182bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mCanModifyCalendar && !mIsOrganizer) {
8192bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            getActivity().setTitle(res.getString(R.string.event_info_title_invite));
8202bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        } else {
8212bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            getActivity().setTitle(res.getString(R.string.event_info_title));
8222bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
8232bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
8242bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
8252bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    /**
8262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * Initializes the event cursor, which is expected to point to the first
8272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * (and only) result from a query.
8282bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * @return true if the cursor is empty.
8292bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     */
8302bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean initEventCursor() {
8312bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if ((mEventCursor == null) || (mEventCursor.getCount() == 0)) {
8322bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return true;
8332bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
8342bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mEventCursor.moveToFirst();
8352bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mEventId = mEventCursor.getInt(EVENT_INDEX_ID);
8362bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        String rRule = mEventCursor.getString(EVENT_INDEX_RRULE);
83766b2067e0a389180f909eb0a528bea5f6becca23Michael Chan        mIsRepeating = !TextUtils.isEmpty(rRule);
8381ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mHasAlarm = (mEventCursor.getInt(EVENT_INDEX_HAS_ALARM) == 1)?true:false;
8391ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mMaxReminders = mEventCursor.getInt(EVENT_INDEX_MAX_REMINDERS);
8401ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mCalendarAllowedReminders =  mEventCursor.getString(EVENT_INDEX_ALLOWED_REMINDERS);
8412bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        return false;
8422bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
8432bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
8442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    @SuppressWarnings("fallthrough")
8452bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void initAttendeesCursor(View view) {
8466bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        mOriginalAttendeeResponse = Attendees.ATTENDEE_STATUS_NONE;
847d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        mCalendarOwnerAttendeeId = EditEventHelper.ATTENDEE_ID_NONE;
8482bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mNumOfAttendees = 0;
8492bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mAttendeesCursor != null) {
8502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mNumOfAttendees = mAttendeesCursor.getCount();
8512bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            if (mAttendeesCursor.moveToFirst()) {
8522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mAcceptedAttendees.clear();
8532bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mDeclinedAttendees.clear();
8542bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mTentativeAttendees.clear();
8552bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mNoResponseAttendees.clear();
8562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
8572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                do {
8582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    int status = mAttendeesCursor.getInt(ATTENDEES_INDEX_STATUS);
8592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    String name = mAttendeesCursor.getString(ATTENDEES_INDEX_NAME);
8602bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    String email = mAttendeesCursor.getString(ATTENDEES_INDEX_EMAIL);
8612bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
86283efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                    if (mAttendeesCursor.getInt(ATTENDEES_INDEX_RELATIONSHIP) ==
86383efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                            Attendees.RELATIONSHIP_ORGANIZER) {
86483efa2d50deca53c9937b19a379045c31b541cb7Michael Chan
86583efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                        // Overwrites the one from Event table if available
86683efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                        if (!TextUtils.isEmpty(name)) {
86783efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                            mEventOrganizerDisplayName = name;
86883efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                            if (!mIsOrganizer) {
86983efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                                setVisibilityCommon(view, R.id.organizer_container, View.VISIBLE);
87083efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                                setTextCommon(view, R.id.organizer, mEventOrganizerDisplayName);
87183efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                            }
87283efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                        }
87383efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                    }
87483efa2d50deca53c9937b19a379045c31b541cb7Michael Chan
875d845fbe558d5229102b58cce70a1b29fe6cb6967Erik                    if (mCalendarOwnerAttendeeId == EditEventHelper.ATTENDEE_ID_NONE &&
8762bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                            mCalendarOwnerAccount.equalsIgnoreCase(email)) {
8772bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        mCalendarOwnerAttendeeId = mAttendeesCursor.getInt(ATTENDEES_INDEX_ID);
8782bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        mOriginalAttendeeResponse = mAttendeesCursor.getInt(ATTENDEES_INDEX_STATUS);
8792bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    } else {
880693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan                        String identity = null;
881693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan                        String idNamespace = null;
882693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan
883fac2d1594f7ecae8e50dc7790ce67de0c9b70d22Sara Ting                        if (Utils.isJellybeanOrLater()) {
884693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan                            identity = mAttendeesCursor.getString(ATTENDEES_INDEX_IDENTITY);
885693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan                            idNamespace = mAttendeesCursor.getString(ATTENDEES_INDEX_ID_NAMESPACE);
886693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan                        }
887ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting
8882bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        // Don't show your own status in the list because:
8892bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        //  1) it doesn't make sense for event without other guests.
8902bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        //  2) there's a spinner for that for events with guests.
8912bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        switch(status) {
8922bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                            case Attendees.ATTENDEE_STATUS_ACCEPTED:
893fe25c502fa0822a57201c7be8b00f0f26b22a385Isaac Katzenelson                                mAcceptedAttendees.add(new Attendee(name, email,
894ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        Attendees.ATTENDEE_STATUS_ACCEPTED, identity,
895ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        idNamespace));
8962bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                                break;
8972bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                            case Attendees.ATTENDEE_STATUS_DECLINED:
898fe25c502fa0822a57201c7be8b00f0f26b22a385Isaac Katzenelson                                mDeclinedAttendees.add(new Attendee(name, email,
899ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        Attendees.ATTENDEE_STATUS_DECLINED, identity,
900ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        idNamespace));
9012bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                                break;
9028ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                            case Attendees.ATTENDEE_STATUS_TENTATIVE:
903fe25c502fa0822a57201c7be8b00f0f26b22a385Isaac Katzenelson                                mTentativeAttendees.add(new Attendee(name, email,
904ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        Attendees.ATTENDEE_STATUS_TENTATIVE, identity,
905ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        idNamespace));
9068ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                                break;
9078ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                            default:
908fe25c502fa0822a57201c7be8b00f0f26b22a385Isaac Katzenelson                                mNoResponseAttendees.add(new Attendee(name, email,
909ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        Attendees.ATTENDEE_STATUS_NONE, identity,
910ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                                        idNamespace));
9112bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        }
9122bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    }
9132bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                } while (mAttendeesCursor.moveToNext());
9142bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                mAttendeesCursor.moveToFirst();
9152bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
9162bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                updateAttendees(view);
9172bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            }
9182bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
9192bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
9202bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
9212bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    @Override
9224003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang    public void onSaveInstanceState(Bundle outState) {
9234003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        super.onSaveInstanceState(outState);
9244003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        outState.putLong(BUNDLE_KEY_EVENT_ID, mEventId);
9254003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        outState.putLong(BUNDLE_KEY_START_MILLIS, mStartMillis);
9264003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        outState.putLong(BUNDLE_KEY_END_MILLIS, mEndMillis);
92771d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        outState.putBoolean(BUNDLE_KEY_IS_DIALOG, mIsDialog);
9287ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        outState.putInt(BUNDLE_KEY_WINDOW_STYLE, mWindowStyle);
929b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        outState.putBoolean(BUNDLE_KEY_DELETE_DIALOG_VISIBLE, mDeleteDialogVisible);
93060f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        outState.putInt(BUNDLE_KEY_ATTENDEE_RESPONSE, mAttendeeResponseFromIntent);
93160f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    }
93260f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson
93360f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson
93460f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    @Override
93560f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
93660f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        super.onCreateOptionsMenu(menu, inflater);
9377ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        // Show edit/delete buttons only in non-dialog configuration
9387ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        if (!mIsDialog && !mIsTabletConfig || mWindowStyle == EventInfoFragment.FULL_WINDOW_STYLE) {
93960f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson            inflater.inflate(R.menu.event_info_title_bar, menu);
940d8353fb85ef59a88580125207be9c914a8586758RoboErik            mMenu = menu;
941d8353fb85ef59a88580125207be9c914a8586758RoboErik            updateMenu();
94260f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        }
9434003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang    }
9444003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
945d8353fb85ef59a88580125207be9c914a8586758RoboErik    @Override
946d8353fb85ef59a88580125207be9c914a8586758RoboErik    public boolean onOptionsItemSelected(MenuItem item) {
947d8353fb85ef59a88580125207be9c914a8586758RoboErik
9487ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        // If we're a dialog we don't want to handle menu buttons
9497ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson        if (mIsDialog) {
950d8353fb85ef59a88580125207be9c914a8586758RoboErik            return false;
951d8353fb85ef59a88580125207be9c914a8586758RoboErik        }
952d8353fb85ef59a88580125207be9c914a8586758RoboErik        // Handles option menu selections:
953d8353fb85ef59a88580125207be9c914a8586758RoboErik        // Home button - close event info activity and start the main calendar
954d8353fb85ef59a88580125207be9c914a8586758RoboErik        // one
955d8353fb85ef59a88580125207be9c914a8586758RoboErik        // Edit button - start the event edit activity and close the info
956d8353fb85ef59a88580125207be9c914a8586758RoboErik        // activity
957d8353fb85ef59a88580125207be9c914a8586758RoboErik        // Delete button - start a delete query that calls a runnable that close
958d8353fb85ef59a88580125207be9c914a8586758RoboErik        // the info activity
959d8353fb85ef59a88580125207be9c914a8586758RoboErik
960bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        final int itemId = item.getItemId();
961bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        if (itemId == android.R.id.home) {
962bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            Utils.returnToCalendarHome(mContext);
963bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mActivity.finish();
964bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            return true;
965bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        } else if (itemId == R.id.info_action_edit) {
966bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventId);
967bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            Intent intent = new Intent(Intent.ACTION_EDIT, uri);
968bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            intent.putExtra(EXTRA_EVENT_BEGIN_TIME, mStartMillis);
969bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            intent.putExtra(EXTRA_EVENT_END_TIME, mEndMillis);
970bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            intent.putExtra(EXTRA_EVENT_ALL_DAY, mAllDay);
971bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            intent.setClass(mActivity, EditEventActivity.class);
972bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            intent.putExtra(EVENT_EDIT_ON_LAUNCH, true);
973bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            startActivity(intent);
974bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mActivity.finish();
975bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        } else if (itemId == R.id.info_action_delete) {
976bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mDeleteHelper =
977bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan                    new DeleteEventHelper(mActivity, mActivity, true /* exitWhenDone */);
978bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mDeleteHelper.setDeleteNotificationListener(EventInfoFragment.this);
979bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mDeleteHelper.setOnDismissListener(createDeleteOnDismissListener());
980bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mDeleteDialogVisible = true;
981bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            mDeleteHelper.delete(mStartMillis, mEndMillis, mEventId, -1, onDeleteRunnable);
982d8353fb85ef59a88580125207be9c914a8586758RoboErik        }
983d8353fb85ef59a88580125207be9c914a8586758RoboErik        return super.onOptionsItemSelected(item);
984d8353fb85ef59a88580125207be9c914a8586758RoboErik    }
9854003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
9864003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang    @Override
9874003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang    public void onDestroyView() {
988ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson
989b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson        if (!mEventDeletionStarted) {
990ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson            boolean responseSaved = saveResponse();
991ac4350b25b794d1b2935266cf8c480e4fbf97b8fIsaac Katzenelson            if (saveReminders() || responseSaved) {
992b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson                Toast.makeText(getActivity(), R.string.saving_event, Toast.LENGTH_SHORT).show();
993b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson            }
9942bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
9954003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        super.onDestroyView();
9962bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
9972bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
9982bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    @Override
9992bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    public void onDestroy() {
10002bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mEventCursor != null) {
10012bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mEventCursor.close();
10022bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10032bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mCalendarsCursor != null) {
10042bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mCalendarsCursor.close();
10052bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10062bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mAttendeesCursor != null) {
10072bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mAttendeesCursor.close();
10082bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
100971d08836af4cf5fc45d340b1883044a9f8290232Michael Chan        super.onDestroy();
10102bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
10112bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10122bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    /**
10132bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * Asynchronously saves the response to an invitation if the user changed
10142bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * the response. Returns true if the database will be updated.
10152bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     *
10162bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * @return true if the database will be changed
10172bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     */
10182bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private boolean saveResponse() {
10192bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mAttendeesCursor == null || mEventCursor == null) {
10202bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return false;
10212bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
1022f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan
1023f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        RadioGroup radioGroup = (RadioGroup) getView().findViewById(R.id.response_value);
1024f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        int status = getResponseFromButtonId(radioGroup.getCheckedRadioButtonId());
1025f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        if (status == Attendees.ATTENDEE_STATUS_NONE) {
10262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return false;
10272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10282bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10292bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // If the status has not changed, then don't update the database
10302bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (status == mOriginalAttendeeResponse) {
10312bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return false;
10322bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10332bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10342bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // If we never got an owner attendee id we can't set the status
1035d845fbe558d5229102b58cce70a1b29fe6cb6967Erik        if (mCalendarOwnerAttendeeId == EditEventHelper.ATTENDEE_ID_NONE) {
10362bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return false;
10372bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10382bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10392bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (!mIsRepeating) {
10402bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            // This is a non-repeating event
10412bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            updateResponse(mEventId, mCalendarOwnerAttendeeId, status);
10422bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return true;
10432bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10452bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // This is a repeating event
10462bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        int whichEvents = mEditResponseHelper.getWhichEvents();
10472bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        switch (whichEvents) {
10482bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case -1:
10492bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                return false;
10502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case UPDATE_SINGLE:
1051c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden                createExceptionResponse(mEventId, status);
10522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                return true;
10532bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            case UPDATE_ALL:
10542bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                updateResponse(mEventId, mCalendarOwnerAttendeeId, status);
10552bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                return true;
10562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            default:
10572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                Log.e(TAG, "Unexpected choice for updating invitation response");
10582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                break;
10592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10602bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        return false;
10612bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
10622bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10632bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void updateResponse(long eventId, long attendeeId, int status) {
10642bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // Update the attendee status in the attendees table.  the provider
10652bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // takes care of updating the self attendance status.
10662bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        ContentValues values = new ContentValues();
10672bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10682bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (!TextUtils.isEmpty(mCalendarOwnerAccount)) {
10692bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            values.put(Attendees.ATTENDEE_EMAIL, mCalendarOwnerAccount);
10702bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
10712bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        values.put(Attendees.ATTENDEE_STATUS, status);
10722bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        values.put(Attendees.EVENT_ID, eventId);
10732bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10742bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        Uri uri = ContentUris.withAppendedId(Attendees.CONTENT_URI, attendeeId);
10752bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
10762bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mHandler.startUpdate(mHandler.getNextToken(), null, uri, values,
10772bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                null, null, Utils.UNDO_DELAY);
10782bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
10792bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1080c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden    /**
1081c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     * Creates an exception to a recurring event.  The only change we're making is to the
1082c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     * "self attendee status" value.  The provider will take care of updating the corresponding
1083c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     * Attendees.attendeeStatus entry.
1084c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     *
1085c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     * @param eventId The recurring event.
1086c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     * @param status The new value for selfAttendeeStatus.
1087c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden     */
1088c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden    private void createExceptionResponse(long eventId, int status) {
10892bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        ContentValues values = new ContentValues();
10902bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        values.put(Events.ORIGINAL_INSTANCE_TIME, mStartMillis);
10912bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        values.put(Events.SELF_ATTENDEE_STATUS, status);
1092c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden        values.put(Events.STATUS, Events.STATUS_CONFIRMED);
10932bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1094364309f0bb9c3aeee8efd0c24faf478f7c62c6d7Erik        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
109579b2c8c946c29ea9107957fe72a9fa9f560da345Andy McFadden        Uri exceptionUri = Uri.withAppendedPath(Events.CONTENT_EXCEPTION_URI,
1096c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden                String.valueOf(eventId));
1097c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden        ops.add(ContentProviderOperation.newInsert(exceptionUri).withValues(values).build());
1098364309f0bb9c3aeee8efd0c24faf478f7c62c6d7Erik
1099c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden        mHandler.startBatch(mHandler.getNextToken(), null, CalendarContract.AUTHORITY, ops,
1100c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden                Utils.UNDO_DELAY);
1101c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden   }
11022bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1103f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan    public static int getResponseFromButtonId(int buttonId) {
1104f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        int response;
1105bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        if (buttonId == R.id.response_yes) {
1106bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            response = Attendees.ATTENDEE_STATUS_ACCEPTED;
1107bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        } else if (buttonId == R.id.response_maybe) {
1108bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            response = Attendees.ATTENDEE_STATUS_TENTATIVE;
1109bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        } else if (buttonId == R.id.response_no) {
1110bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            response = Attendees.ATTENDEE_STATUS_DECLINED;
1111bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan        } else {
1112bb6d9279d8c0f0fb746160ad428da4738ece175eMichael Chan            response = Attendees.ATTENDEE_STATUS_NONE;
11132bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
1114f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        return response;
1115f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan    }
1116f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan
1117f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan    public static int findButtonIdForResponse(int response) {
1118f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        int buttonId;
1119f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        switch (response) {
1120f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan            case Attendees.ATTENDEE_STATUS_ACCEPTED:
1121f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                buttonId = R.id.response_yes;
1122f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                break;
1123f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan            case Attendees.ATTENDEE_STATUS_TENTATIVE:
1124f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                buttonId = R.id.response_maybe;
1125f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                break;
1126f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan            case Attendees.ATTENDEE_STATUS_DECLINED:
1127f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                buttonId = R.id.response_no;
1128f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                break;
1129f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                default:
1130f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan                    buttonId = -1;
1131f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        }
1132f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        return buttonId;
11332bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
11342bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
11352bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void doEdit() {
1136c41b99be504e395b8c7264a0d626906ccbff1c57Erik        Context c = getActivity();
1137c41b99be504e395b8c7264a0d626906ccbff1c57Erik        // This ensures that we aren't in the process of closing and have been
1138c41b99be504e395b8c7264a0d626906ccbff1c57Erik        // unattached already
1139c41b99be504e395b8c7264a0d626906ccbff1c57Erik        if (c != null) {
1140c41b99be504e395b8c7264a0d626906ccbff1c57Erik            CalendarController.getInstance(c).sendEventRelatedEvent(
114161bf59383cc3d38ef0447635ed65ab986796d7deMichael Chan                    this, EventType.EDIT_EVENT, mEventId, mStartMillis, mEndMillis, 0
114260f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                    , 0, -1);
1143c41b99be504e395b8c7264a0d626906ccbff1c57Erik        }
11442bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
11452bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
11462bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void updateEvent(View view) {
1147b7762cf45d4606916b54edca5f31fd225e4a2b03Isaac Katzenelson        if (mEventCursor == null || view == null) {
11482bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return;
11492bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
11502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
11515f5ef752bfd4640016c4dedef53be47c5b8842afMichael Chan        Context context = view.getContext();
11525f5ef752bfd4640016c4dedef53be47c5b8842afMichael Chan        if (context == null) {
11535f5ef752bfd4640016c4dedef53be47c5b8842afMichael Chan            return;
11545f5ef752bfd4640016c4dedef53be47c5b8842afMichael Chan        }
11555f5ef752bfd4640016c4dedef53be47c5b8842afMichael Chan
11562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        String eventName = mEventCursor.getString(EVENT_INDEX_TITLE);
11572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (eventName == null || eventName.length() == 0) {
11582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            eventName = getActivity().getString(R.string.no_title_label);
11592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
11602bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
11618b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan        mAllDay = mEventCursor.getInt(EVENT_INDEX_ALL_DAY) != 0;
11622bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        String location = mEventCursor.getString(EVENT_INDEX_EVENT_LOCATION);
11632bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        String description = mEventCursor.getString(EVENT_INDEX_DESCRIPTION);
11642bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        String rRule = mEventCursor.getString(EVENT_INDEX_RRULE);
1165f6f797769a5cac9f9796574fe6c5ca767b1c269aIsaac Katzenelson        String eventTimezone = mEventCursor.getString(EVENT_INDEX_EVENT_TIMEZONE);
11662bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
11674acb2fd087308dea146b8b10f5278c59df387680RoboErik        mColor = Utils.getDisplayColorFromColor(mEventCursor.getInt(EVENT_INDEX_COLOR));
1168fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        mHeadlines.setBackgroundColor(mColor);
11692bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
11704e92627c5eb10de50c49c57e116b080d48360c70Sara Ting        // What
11714e92627c5eb10de50c49c57e116b080d48360c70Sara Ting        if (eventName != null) {
11724e92627c5eb10de50c49c57e116b080d48360c70Sara Ting            setTextCommon(view, R.id.title, eventName);
11734e92627c5eb10de50c49c57e116b080d48360c70Sara Ting        }
11744e92627c5eb10de50c49c57e116b080d48360c70Sara Ting
11752bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // When
1176fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        // Set the date and repeats (if any)
117775f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting        String localTimezone = Utils.getTimeZone(mActivity, mTZUpdater);
11785f5ef752bfd4640016c4dedef53be47c5b8842afMichael Chan
117923acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        Resources resources = context.getResources();
118023acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        String displayedDatetime = Utils.getDisplayedDatetime(mStartMillis, mEndMillis,
118123acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting                System.currentTimeMillis(), localTimezone, mAllDay, context);
1182e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan
1183e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan        String displayedTimezone = null;
1184e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan        if (!mAllDay) {
1185e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan            displayedTimezone = Utils.getDisplayedTimezone(mStartMillis, localTimezone,
1186e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan                    eventTimezone);
118723acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        }
118823acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        // Display the datetime.  Make the timezone (if any) transparent.
118923acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        if (displayedTimezone == null) {
119023acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting            setTextCommon(view, R.id.when_datetime, displayedDatetime);
119123acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        } else {
1192e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan            int timezoneIndex = displayedDatetime.length();
1193e8e557260ec1f907d257dcbb08c49bc5d0926795Michael Chan            displayedDatetime += "  " + displayedTimezone;
119423acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting            SpannableStringBuilder sb = new SpannableStringBuilder(displayedDatetime);
119523acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting            ForegroundColorSpan transparentColorSpan = new ForegroundColorSpan(
119623acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting                    resources.getColor(R.color.event_info_headline_transparent_color));
119723acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting            sb.setSpan(transparentColorSpan, timezoneIndex, displayedDatetime.length(),
119823acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting                    Spannable.SPAN_INCLUSIVE_INCLUSIVE);
119923acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting            setTextCommon(view, R.id.when_datetime, sb);
120023acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting        }
1201fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson
120275f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting        // Display the repeat string (if any)
1203fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        String repeatString = null;
1204fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        if (!TextUtils.isEmpty(rRule)) {
1205fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            EventRecurrence eventRecurrence = new EventRecurrence();
1206fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            eventRecurrence.parse(rRule);
120775f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting            Time date = new Time(localTimezone);
120875f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting            date.set(mStartMillis);
12098b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan            if (mAllDay) {
1210fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson                date.timezone = Time.TIMEZONE_UTC;
1211fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            }
1212fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            eventRecurrence.setStartDate(date);
121323acd2668d65c2282f7aa922b4e86a7713d9b2faSara Ting            repeatString = EventRecurrenceFormatter.getRepeatString(resources, eventRecurrence);
1214fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        }
121575f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting        if (repeatString == null) {
121675f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting            view.findViewById(R.id.when_repeat).setVisibility(View.GONE);
12172bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        } else {
121875f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting            setTextCommon(view, R.id.when_repeat, repeatString);
1219f6f797769a5cac9f9796574fe6c5ca767b1c269aIsaac Katzenelson        }
1220f6f797769a5cac9f9796574fe6c5ca767b1c269aIsaac Katzenelson
12212e46cff640b123ba5f7a67c934ae98e6b02a905fIsaac Katzenelson        // Organizer view is setup in the updateCalendar method
12222e46cff640b123ba5f7a67c934ae98e6b02a905fIsaac Katzenelson
12232bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
12242bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // Where
1225ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan        if (location == null || location.trim().length() == 0) {
12262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            setVisibilityCommon(view, R.id.where, View.GONE);
12272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        } else {
1228259b8f9a21fffd3858218581e9daaf689b6b888fErik            final TextView textView = mWhere;
12292bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            if (textView != null) {
1230ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                textView.setAutoLinkMask(0);
1231ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                textView.setText(location.trim());
1232af577fd49d334060f34d3e40e48c762ff5f0de4fAndy McFadden                try {
1233af577fd49d334060f34d3e40e48c762ff5f0de4fAndy McFadden                    linkifyTextView(textView);
1234af577fd49d334060f34d3e40e48c762ff5f0de4fAndy McFadden                } catch (Exception ex) {
1235af577fd49d334060f34d3e40e48c762ff5f0de4fAndy McFadden                    // unexpected
1236af577fd49d334060f34d3e40e48c762ff5f0de4fAndy McFadden                    Log.e(TAG, "Linkification failed", ex);
1237af577fd49d334060f34d3e40e48c762ff5f0de4fAndy McFadden                }
123873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
1239ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                textView.setOnTouchListener(new OnTouchListener() {
1240c928e3d4ce097389b59eea82a5ca9827a44a8c9cAndy McFadden                    @Override
1241ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                    public boolean onTouch(View v, MotionEvent event) {
1242ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                        try {
1243ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                            return v.onTouchEvent(event);
1244ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                        } catch (ActivityNotFoundException e) {
1245ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                            // ignore
1246ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                            return true;
12472bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                        }
1248ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                    }
1249ddfb59d54494c97c0c0b5326821a9594b1fe8896Michael Chan                });
12502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            }
12512bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
12522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
12532bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // Description
1254352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan        if (description != null && description.length() != 0) {
125599704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan            mDesc.setText(description);
12562bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
12572bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
12582c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        // Launch Custom App
1259fac2d1594f7ecae8e50dc7790ce67de0c9b70d22Sara Ting        if (Utils.isJellybeanOrLater()) {
1260693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan            updateCustomAppButton();
1261693ca60d79650af15ab226f7ce6958f61fb7de39Michael Chan        }
12622c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan    }
12632c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12642c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan    private void updateCustomAppButton() {
12652c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        buttonSetup: {
12662c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            final Button launchButton = (Button) mView.findViewById(R.id.launch_custom_app_button);
12672c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (launchButton == null)
12682c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                break buttonSetup;
12692c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12702c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            final String customAppPackage = mEventCursor.getString(EVENT_INDEX_CUSTOM_APP_PACKAGE);
12712c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            final String customAppUri = mEventCursor.getString(EVENT_INDEX_CUSTOM_APP_URI);
12722c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12732c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (TextUtils.isEmpty(customAppPackage) || TextUtils.isEmpty(customAppUri))
12742c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                break buttonSetup;
12752c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12762c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            PackageManager pm = mContext.getPackageManager();
12772c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (pm == null)
12782c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                break buttonSetup;
12792c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12802c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            ApplicationInfo info;
12812c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            try {
12822c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                info = pm.getApplicationInfo(customAppPackage, 0);
12832c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                if (info == null)
12842c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                    break buttonSetup;
12852c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            } catch (NameNotFoundException e) {
12862c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                break buttonSetup;
12872c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            }
12882c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12892c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventId);
12902c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            final Intent intent = new Intent(CalendarContract.ACTION_HANDLE_CUSTOM_EVENT, uri);
12912c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            intent.setPackage(customAppPackage);
12922c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            intent.putExtra(CalendarContract.EXTRA_CUSTOM_APP_URI, customAppUri);
12932c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            intent.putExtra(EXTRA_EVENT_BEGIN_TIME, mStartMillis);
12942c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12952c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            // See if we have a taker for our intent
12962c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (pm.resolveActivity(intent, 0) == null)
12972c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                break buttonSetup;
12982c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
12992c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            Drawable icon = pm.getApplicationIcon(info);
13002c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (icon != null) {
13012c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
13022c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                Drawable[] d = launchButton.getCompoundDrawables();
13032c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                icon.setBounds(0, 0, mCustomAppIconSize, mCustomAppIconSize);
13042c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                launchButton.setCompoundDrawables(icon, d[1], d[2], d[3]);
13052c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            }
13062c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
13072c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            CharSequence label = pm.getApplicationLabel(info);
13082c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            if (label != null && label.length() != 0) {
13092c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                launchButton.setText(label);
13102c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            } else if (icon == null) {
13112c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                // No icon && no label. Hide button?
13122c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                break buttonSetup;
13132c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            }
13142c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
13152c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            // Launch custom app
13162c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            launchButton.setOnClickListener(new View.OnClickListener() {
13172c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                @Override
13182c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                public void onClick(View v) {
13192c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                    try {
13202c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                        startActivityForResult(intent, 0);
13212c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                    } catch (ActivityNotFoundException e) {
13222c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                        // Shouldn't happen as we checked it already
13232c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                        setVisibilityCommon(mView, R.id.launch_custom_app_container, View.GONE);
13242c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                    }
13252c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan                }
13262c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            });
13272c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
13282c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            setVisibilityCommon(mView, R.id.launch_custom_app_container, View.VISIBLE);
13292c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan            return;
13302c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
13312c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        }
13322c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan
13332c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        setVisibilityCommon(mView, R.id.launch_custom_app_container, View.GONE);
13342c8485c84855545a0a8a0a7cb26d7c401a32cdd5Michael Chan        return;
13358f4d969064ceeec166f709b81cc7b8427686154eIsaac Katzenelson    }
133675f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting
133773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    /**
1338fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * Finds North American Numbering Plan (NANP) phone numbers in the input text.
1339fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     *
1340fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * @param text The text to scan.
1341fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * @return A list of [start, end) pairs indicating the positions of phone numbers in the input.
1342fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     */
1343fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    // @VisibleForTesting
1344fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    static int[] findNanpPhoneNumbers(CharSequence text) {
1345fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        ArrayList<Integer> list = new ArrayList<Integer>();
1346fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1347fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int startPos = 0;
1348fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int endPos = text.length() - NANP_MIN_DIGITS + 1;
1349fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        if (endPos < 0) {
1350fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            return new int[] {};
1351fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        }
1352fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1353fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        /*
1354fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * We can't just strip the whitespace out and crunch it down, because the whitespace
1355fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * is significant.  March through, trying to figure out where numbers start and end.
1356fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         */
1357fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        while (startPos < endPos) {
1358fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            // skip whitespace
1359fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            while (Character.isWhitespace(text.charAt(startPos)) && startPos < endPos) {
1360fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                startPos++;
1361fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            }
1362fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            if (startPos == endPos) {
1363fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                break;
1364fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            }
1365fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1366fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            // check for a match at this position
1367fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            int matchEnd = findNanpMatchEnd(text, startPos);
1368fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            if (matchEnd > startPos) {
1369fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                list.add(startPos);
1370fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                list.add(matchEnd);
1371fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                startPos = matchEnd;    // skip past match
1372fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            } else {
1373fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                // skip to next whitespace char
1374fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                while (!Character.isWhitespace(text.charAt(startPos)) && startPos < endPos) {
1375fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    startPos++;
1376fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                }
1377fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            }
1378fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        }
1379fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1380fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int[] result = new int[list.size()];
1381fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        for (int i = list.size() - 1; i >= 0; i--) {
1382fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            result[i] = list.get(i);
1383fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        }
1384fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        return result;
1385fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    }
1386fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1387fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    /**
1388fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * Checks to see if there is a valid phone number in the input, starting at the specified
1389fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * offset.  If so, the index of the last character + 1 is returned.  The input is assumed
1390fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * to begin with a non-whitespace character.
1391fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     *
1392fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     * @return Exclusive end position, or -1 if not a match.
1393fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden     */
1394fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    private static int findNanpMatchEnd(CharSequence text, int startPos) {
1395fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        /*
1396fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * A few interesting cases:
1397fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   94043                              # too short, ignore
1398fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   123456789012                       # too long, ignore
1399fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   +1 (650) 555-1212                  # 11 digits, spaces
1400c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein         *   (650) 555 5555                     # Second space, only when first is present.
1401fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   (650) 555-1212, (650) 555-1213     # two numbers, return first
1402fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   1-650-555-1212                     # 11 digits with leading '1'
1403fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   *#650.555.1212#*!                  # 10 digits, include #*, ignore trailing '!'
1404fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *   555.1212                           # 7 digits
1405fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *
1406fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * For the most part we want to break on whitespace, but it's common to leave a space
1407fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * between the initial '1' and/or after the area code.
1408fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         */
1409fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1410c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein        // Check for "tel:" URI prefix.
1411c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein        if (text.length() > startPos+4
1412c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                && text.subSequence(startPos, startPos+4).toString().equalsIgnoreCase("tel:")) {
1413c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein            startPos += 4;
1414c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein        }
1415c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein
1416fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int endPos = text.length();
1417fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int curPos = startPos;
1418fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int foundDigits = 0;
1419fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        char firstDigit = 'x';
1420c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein        boolean foundWhiteSpaceAfterAreaCode = false;
1421fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1422fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        while (curPos <= endPos) {
1423fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            char ch;
1424fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            if (curPos < endPos) {
1425fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                ch = text.charAt(curPos);
1426fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            } else {
1427fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                ch = 27;    // fake invalid symbol at end to trigger loop break
1428fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            }
1429fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1430fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            if (Character.isDigit(ch)) {
1431fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                if (foundDigits == 0) {
1432fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    firstDigit = ch;
1433fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                }
1434fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                foundDigits++;
1435fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                if (foundDigits > NANP_MAX_DIGITS) {
1436fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    // too many digits, stop early
1437fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    return -1;
1438fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                }
1439fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            } else if (Character.isWhitespace(ch)) {
1440c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                if ( (firstDigit == '1' && foundDigits == 4) ||
1441c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                        (foundDigits == 3)) {
1442c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                    foundWhiteSpaceAfterAreaCode = true;
1443c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                } else if (firstDigit == '1' && foundDigits == 1) {
1444c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                } else if (foundWhiteSpaceAfterAreaCode
1445c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                        && ( (firstDigit == '1' && (foundDigits == 7)) || (foundDigits == 6))) {
1446c5cbf21580877c3ab4732f146bf81f6631464e6dSam Blitzstein                } else {
1447fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    break;
1448fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                }
1449fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            } else if (NANP_ALLOWED_SYMBOLS.indexOf(ch) == -1) {
1450fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                break;
1451fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            }
1452fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            // else it's an allowed symbol
1453fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1454fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            curPos++;
1455fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        }
1456fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1457fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        if ((firstDigit != '1' && (foundDigits == 7 || foundDigits == 10)) ||
1458fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                (firstDigit == '1' && foundDigits == 11)) {
1459fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            // match
1460fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            return curPos;
1461fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        }
1462fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
1463fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        return -1;
1464fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    }
1465fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden
146609e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting    private static int indexFirstNonWhitespaceChar(CharSequence str) {
146709e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        for (int i = 0; i < str.length(); i++) {
146809e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            if (!Character.isWhitespace(str.charAt(i))) {
146909e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                return i;
147009e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            }
147109e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        }
147209e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        return -1;
147309e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting    }
147409e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting
147509e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting    private static int indexLastNonWhitespaceChar(CharSequence str) {
147609e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        for (int i = str.length() - 1; i >= 0; i--) {
147709e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            if (!Character.isWhitespace(str.charAt(i))) {
147809e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                return i;
147909e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            }
148009e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        }
148109e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        return -1;
148209e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting    }
148309e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting
1484fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden    /**
148573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     * Replaces stretches of text that look like addresses and phone numbers with clickable
148673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     * links.
148773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     * <p>
148873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     * This is really just an enhanced version of Linkify.addLinks().
148973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     */
149073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    private static void linkifyTextView(TextView textView) {
149173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        /*
149273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * If the text includes a street address like "1600 Amphitheater Parkway, 94043",
149373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * the current Linkify code will identify "94043" as a phone number and invite
149409e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         * you to dial it (and not provide a map link for the address).  For outside US,
149509e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         * use Linkify result iff it spans the entire text.  Otherwise send the user to maps.
149609e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         */
149709e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        String defaultPhoneRegion = System.getProperty("user.region", "US");
149809e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        if (!defaultPhoneRegion.equals("US")) {
149909e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            CharSequence origText = textView.getText();
150009e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            Linkify.addLinks(textView, Linkify.ALL);
150109e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting
150209e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            // If Linkify links the entire text, use that result.
150309e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            if (textView.getText() instanceof Spannable) {
150409e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                Spannable spanText = (Spannable) textView.getText();
150509e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                URLSpan[] spans = spanText.getSpans(0, spanText.length(), URLSpan.class);
150609e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                if (spans.length == 1) {
150709e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                    int linkStart = spanText.getSpanStart(spans[0]);
150809e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                    int linkEnd = spanText.getSpanEnd(spans[0]);
150909e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                    if (linkStart <= indexFirstNonWhitespaceChar(origText) &&
151009e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                            linkEnd >= indexLastNonWhitespaceChar(origText) + 1) {
151109e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                        return;
151209e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                    }
151309e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting                }
151409e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            }
151509e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting
151609e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            // Otherwise default to geo.
151709e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            textView.setText(origText);
151809e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            Linkify.addLinks(textView, mWildcardPattern, "geo:0,0?q=");
151909e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting            return;
152009e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        }
152109e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting
152209e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting        /*
152309e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         * For within US, we want to have better recognition of phone numbers without losing
152409e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         * any of the existing annotations.  Ideally this would be addressed by improving Linkify.
152509e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         * For now we manage it as a second pass over the text.
152673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         *
152773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * URIs and e-mail addresses are pretty easy to pick out of text.  Phone numbers
152873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * are a bit tricky because they have radically different formats in different
152973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * countries, in terms of both the digits and the way in which they are commonly
153073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * written or presented (e.g. the punctuation and spaces in "(650) 555-1212").
153173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * The expected format of a street address is defined in WebView.findAddress().  It's
153273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * pretty narrowly defined, so it won't often match.
153373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         *
153473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * The RFC 3966 specification defines the format of a "tel:" URI.
153509e8b5ada4553fcf1214dd9163dac418c16fade0Sara Ting         *
153673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * Start by letting Linkify find anything that isn't a phone number.  We have to let it
153773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * run first because every invocation removes all previous URLSpan annotations.
1538fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         *
1539fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * Ideally we'd use the external/libphonenumber routines, but those aren't available
1540fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * to unbundled applications.
154173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         */
154273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        boolean linkifyFoundLinks = Linkify.addLinks(textView,
154373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                Linkify.ALL & ~(Linkify.PHONE_NUMBERS));
154473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
154573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        /*
154673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * Search for phone numbers.
154773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         *
1548fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * Some URIs contain strings of digits that look like phone numbers.  If both the URI
1549fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * scanner and the phone number scanner find them, we want the URI link to win.  Since
1550fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden         * the URI scanner runs first, we just need to avoid creating overlapping spans.
155173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         */
155273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        CharSequence text = textView.getText();
1553fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        int[] phoneSequences = findNanpPhoneNumbers(text);
155473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
155573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        /*
155673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * If the contents of the TextView are already Spannable (which will be the case if
155773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * Linkify found stuff, but might not be otherwise), we can just add annotations
155873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * to what's there.  If it's not, and we find phone numbers, we need to convert it to
155973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * a Spannable form.  (This mimics the behavior of Linkable.addLinks().)
156073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         */
156173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        Spannable spanText;
156273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        if (text instanceof SpannableString) {
156373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            spanText = (SpannableString) text;
156473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        } else {
156573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            spanText = SpannableString.valueOf(text);
156673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        }
156773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
156873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        /*
156973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * Get a list of any spans created by Linkify, for the overlapping span check.
157073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         */
157173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        URLSpan[] existingSpans = spanText.getSpans(0, spanText.length(), URLSpan.class);
157273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
157373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        /*
157473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         * Insert spans for the numbers we found.  We generate "tel:" URIs.
157573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden         */
157673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        int phoneCount = 0;
1577fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden        for (int match = 0; match < phoneSequences.length / 2; match++) {
1578fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            int start = phoneSequences[match*2];
1579fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden            int end = phoneSequences[match*2 + 1];
158073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
158173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            if (spanWillOverlap(spanText, existingSpans, start, end)) {
158273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                if (Log.isLoggable(TAG, Log.VERBOSE)) {
1583fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    CharSequence seq = text.subSequence(start, end);
1584fd8ce5e0d40a4a55e9425fe95e9c1ebdf6f9cee9Andy McFadden                    Log.v(TAG, "Not linkifying " + seq + " as phone number due to overlap");
158573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                }
158673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                continue;
158773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            }
158873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
158973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            /*
159073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden             * The Linkify code takes the matching span and strips out everything that isn't a
159173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden             * digit or '+' sign.  We do the same here.  Extension numbers will get appended
159273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden             * without a separator, but the dialer wasn't doing anything useful with ";ext="
159373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden             * anyway.
159473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden             */
159573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
159673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            //String dialStr = phoneUtil.format(match.number(),
159773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            //        PhoneNumberUtil.PhoneNumberFormat.RFC3966);
159873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            StringBuilder dialBuilder = new StringBuilder();
159973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            for (int i = start; i < end; i++) {
160073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                char ch = spanText.charAt(i);
160173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                if (ch == '+' || Character.isDigit(ch)) {
160273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                    dialBuilder.append(ch);
160373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                }
160473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            }
160573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            URLSpan span = new URLSpan("tel:" + dialBuilder.toString());
160673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
160773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            spanText.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
160873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            phoneCount++;
160973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        }
161073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
161173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        if (phoneCount != 0) {
161273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            // If we had to "upgrade" to Spannable, store the object into the TextView.
161373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            if (spanText != text) {
161473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                textView.setText(spanText);
161573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            }
161673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
161773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            // Linkify.addLinks() sets the TextView movement method if it finds any links.  We
161873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            // want to do the same here.  (This is cloned from Linkify.addLinkMovementMethod().)
161973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            MovementMethod mm = textView.getMovementMethod();
162073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
162173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            if ((mm == null) || !(mm instanceof LinkMovementMethod)) {
162273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                if (textView.getLinksClickable()) {
162373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                    textView.setMovementMethod(LinkMovementMethod.getInstance());
162473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                }
162573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            }
162673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        }
162773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
162873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        if (!linkifyFoundLinks && phoneCount == 0) {
162973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            if (Log.isLoggable(TAG, Log.VERBOSE)) {
163073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                Log.v(TAG, "No linkification matches, using geo default");
163173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            }
163273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            Linkify.addLinks(textView, mWildcardPattern, "geo:0,0?q=");
163373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        }
163473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    }
163573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
163673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    /**
163773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     * Determines whether a new span at [start,end) will overlap with any existing span.
163873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden     */
163973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    private static boolean spanWillOverlap(Spannable spanText, URLSpan[] spanList, int start,
164073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            int end) {
164173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        if (start == end) {
164273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            // empty span, ignore
164373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            return false;
164473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        }
164573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        for (URLSpan span : spanList) {
164673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            int existingStart = spanText.getSpanStart(span);
164773b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            int existingEnd = spanText.getSpanEnd(span);
164873b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            if ((start >= existingStart && start < existingEnd) ||
164973b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                    end > existingStart && end <= existingEnd) {
165073b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden                return true;
165173b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden            }
165273b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        }
165373b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
165473b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden        return false;
165573b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden    }
165673b07655afcea1ba2ce8ed580a50992bf0baf857Andy McFadden
1657259b8f9a21fffd3858218581e9daaf689b6b888fErik    private void sendAccessibilityEvent() {
1658ef31a98202852807f460af49ae3313d1ccf5e288Andy McFadden        AccessibilityManager am =
1659ef31a98202852807f460af49ae3313d1ccf5e288Andy McFadden            (AccessibilityManager) getActivity().getSystemService(Service.ACCESSIBILITY_SERVICE);
1660259b8f9a21fffd3858218581e9daaf689b6b888fErik        if (!am.isEnabled()) {
1661259b8f9a21fffd3858218581e9daaf689b6b888fErik            return;
1662259b8f9a21fffd3858218581e9daaf689b6b888fErik        }
1663259b8f9a21fffd3858218581e9daaf689b6b888fErik
1664259b8f9a21fffd3858218581e9daaf689b6b888fErik        AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_FOCUSED);
1665259b8f9a21fffd3858218581e9daaf689b6b888fErik        event.setClassName(getClass().getName());
1666259b8f9a21fffd3858218581e9daaf689b6b888fErik        event.setPackageName(getActivity().getPackageName());
1667259b8f9a21fffd3858218581e9daaf689b6b888fErik        List<CharSequence> text = event.getText();
1668259b8f9a21fffd3858218581e9daaf689b6b888fErik
166999704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        addFieldToAccessibilityEvent(text, mTitle, null);
167075f53668f94c3ced9d3cc8583d7e45ce725ff9deSara Ting        addFieldToAccessibilityEvent(text, mWhenDateTime, null);
167199704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        addFieldToAccessibilityEvent(text, mWhere, null);
167299704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        addFieldToAccessibilityEvent(text, null, mDesc);
1673259b8f9a21fffd3858218581e9daaf689b6b888fErik
1674259b8f9a21fffd3858218581e9daaf689b6b888fErik        RadioGroup response = (RadioGroup) getView().findViewById(R.id.response_value);
1675259b8f9a21fffd3858218581e9daaf689b6b888fErik        if (response.getVisibility() == View.VISIBLE) {
1676259b8f9a21fffd3858218581e9daaf689b6b888fErik            int id = response.getCheckedRadioButtonId();
1677259b8f9a21fffd3858218581e9daaf689b6b888fErik            if (id != View.NO_ID) {
1678259b8f9a21fffd3858218581e9daaf689b6b888fErik                text.add(((TextView) getView().findViewById(R.id.response_label)).getText());
1679259b8f9a21fffd3858218581e9daaf689b6b888fErik                text.add((((RadioButton) (response.findViewById(id))).getText() + PERIOD_SPACE));
1680259b8f9a21fffd3858218581e9daaf689b6b888fErik            }
1681259b8f9a21fffd3858218581e9daaf689b6b888fErik        }
1682259b8f9a21fffd3858218581e9daaf689b6b888fErik
1683259b8f9a21fffd3858218581e9daaf689b6b888fErik        am.sendAccessibilityEvent(event);
1684259b8f9a21fffd3858218581e9daaf689b6b888fErik    }
1685259b8f9a21fffd3858218581e9daaf689b6b888fErik
168699704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan    private void addFieldToAccessibilityEvent(List<CharSequence> text, TextView tv,
168799704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan            ExpandableTextView etv) {
16883389397186b93936747d4009a35f5bae605c246eMichael Chan        CharSequence cs;
168999704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        if (tv != null) {
16903389397186b93936747d4009a35f5bae605c246eMichael Chan            cs = tv.getText();
169199704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        } else if (etv != null) {
16923389397186b93936747d4009a35f5bae605c246eMichael Chan            cs = etv.getText();
169399704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan        } else {
16949ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson            return;
16959ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson        }
169699704a2787158bf670fa4a7b4e4f89ace10afa00Michael Chan
16973389397186b93936747d4009a35f5bae605c246eMichael Chan        if (!TextUtils.isEmpty(cs)) {
16983389397186b93936747d4009a35f5bae605c246eMichael Chan            cs = cs.toString().trim();
16993389397186b93936747d4009a35f5bae605c246eMichael Chan            if (cs.length() > 0) {
17003389397186b93936747d4009a35f5bae605c246eMichael Chan                text.add(cs);
17013389397186b93936747d4009a35f5bae605c246eMichael Chan                text.add(PERIOD_SPACE);
17023389397186b93936747d4009a35f5bae605c246eMichael Chan            }
1703259b8f9a21fffd3858218581e9daaf689b6b888fErik        }
1704259b8f9a21fffd3858218581e9daaf689b6b888fErik    }
1705259b8f9a21fffd3858218581e9daaf689b6b888fErik
17062bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void updateCalendar(View view) {
17072bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        mCalendarOwnerAccount = "";
17082bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (mCalendarsCursor != null && mEventCursor != null) {
17092bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mCalendarsCursor.moveToFirst();
17102bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            String tempAccount = mCalendarsCursor.getString(CALENDARS_INDEX_OWNER_ACCOUNT);
17112bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mCalendarOwnerAccount = (tempAccount == null) ? "" : tempAccount;
1712352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            mOwnerCanRespond = mCalendarsCursor.getInt(CALENDARS_INDEX_OWNER_CAN_RESPOND) != 0;
171342896f76d81dbae873614340a3a78b29e7d463d2Sara Ting            mSyncAccountName = mCalendarsCursor.getString(CALENDARS_INDEX_ACCOUNT_NAME);
17142bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
17152bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            String displayName = mCalendarsCursor.getString(CALENDARS_INDEX_DISPLAY_NAME);
17162bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
17176aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting            // start visible calendars query
17186aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting            mHandler.startQuery(TOKEN_QUERY_VISIBLE_CALENDARS, null, Calendars.CONTENT_URI,
17196aad0ffcbdda48fc895543e2780b1d1c9fef3942Sara Ting                    CALENDARS_PROJECTION, CALENDARS_VISIBLE_WHERE, new String[] {"1"}, null);
17202bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
172183efa2d50deca53c9937b19a379045c31b541cb7Michael Chan            mEventOrganizerEmail = mEventCursor.getString(EVENT_INDEX_ORGANIZER);
172283efa2d50deca53c9937b19a379045c31b541cb7Michael Chan            mIsOrganizer = mCalendarOwnerAccount.equalsIgnoreCase(mEventOrganizerEmail);
172383efa2d50deca53c9937b19a379045c31b541cb7Michael Chan
17240c0da940484dc8966576634475daa126b4a6ede2Sara Ting            if (!TextUtils.isEmpty(mEventOrganizerEmail) &&
17250c0da940484dc8966576634475daa126b4a6ede2Sara Ting                    !mEventOrganizerEmail.endsWith(Utils.MACHINE_GENERATED_ADDRESS)) {
172683efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                mEventOrganizerDisplayName = mEventOrganizerEmail;
172783efa2d50deca53c9937b19a379045c31b541cb7Michael Chan            }
172883efa2d50deca53c9937b19a379045c31b541cb7Michael Chan
172983efa2d50deca53c9937b19a379045c31b541cb7Michael Chan            if (!mIsOrganizer && !TextUtils.isEmpty(mEventOrganizerDisplayName)) {
173083efa2d50deca53c9937b19a379045c31b541cb7Michael Chan                setTextCommon(view, R.id.organizer, mEventOrganizerDisplayName);
1731b7762cf45d4606916b54edca5f31fd225e4a2b03Isaac Katzenelson                setVisibilityCommon(view, R.id.organizer_container, View.VISIBLE);
1732b7762cf45d4606916b54edca5f31fd225e4a2b03Isaac Katzenelson            } else {
1733b7762cf45d4606916b54edca5f31fd225e4a2b03Isaac Katzenelson                setVisibilityCommon(view, R.id.organizer_container, View.GONE);
1734b7762cf45d4606916b54edca5f31fd225e4a2b03Isaac Katzenelson            }
17352bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mHasAttendeeData = mEventCursor.getInt(EVENT_INDEX_HAS_ATTENDEE_DATA) != 0;
173665eeb79e62034d706503ce29d88c0e05ebd726feRoboErik            mCanModifyCalendar = mEventCursor.getInt(EVENT_INDEX_ACCESS_LEVEL)
173765eeb79e62034d706503ce29d88c0e05ebd726feRoboErik                    >= Calendars.CAL_ACCESS_CONTRIBUTOR;
173865eeb79e62034d706503ce29d88c0e05ebd726feRoboErik            // TODO add "|| guestCanModify" after b/1299071 is fixed
173965eeb79e62034d706503ce29d88c0e05ebd726feRoboErik            mCanModifyEvent = mCanModifyCalendar && mIsOrganizer;
17402bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            mIsBusyFreeCalendar =
1741ef2add9145f058ea103ade2870a8ba899b9ed1c9RoboErik                    mEventCursor.getInt(EVENT_INDEX_ACCESS_LEVEL) == Calendars.CAL_ACCESS_FREEBUSY;
1742352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
1743352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan            if (!mIsBusyFreeCalendar) {
1744d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson
1745d4e45fa96c8c377d91271fbb368db64dc1fd5b48Isaac Katzenelson                View b = mView.findViewById(R.id.edit);
1746352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                b.setEnabled(true);
17478ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                b.setOnClickListener(new OnClickListener() {
17488ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                    @Override
17498ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                    public void onClick(View v) {
17508ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan                        doEdit();
175110b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                        // For dialogs, just close the fragment
175210b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                        // For full screen, close activity on phone, leave it for tablet
175360f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                        if (mIsDialog) {
175460f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                            EventInfoFragment.this.dismiss();
175560f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                        }
175610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                        else if (!mIsTabletConfig){
175760f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                            getActivity().finish();
175860f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                        }
1759352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                    }
1760352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                });
17618ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan            }
1762dd15169500bc687107370366c3bbd8339bbcaa74Mindy Pereira            View button;
176342896f76d81dbae873614340a3a78b29e7d463d2Sara Ting            if (mCanModifyCalendar) {
1764dd15169500bc687107370366c3bbd8339bbcaa74Mindy Pereira                button = mView.findViewById(R.id.delete);
1765dd15169500bc687107370366c3bbd8339bbcaa74Mindy Pereira                if (button != null) {
176642896f76d81dbae873614340a3a78b29e7d463d2Sara Ting                    button.setEnabled(true);
176742896f76d81dbae873614340a3a78b29e7d463d2Sara Ting                    button.setVisibility(View.VISIBLE);
176865eeb79e62034d706503ce29d88c0e05ebd726feRoboErik                }
1769dd15169500bc687107370366c3bbd8339bbcaa74Mindy Pereira            }
177042896f76d81dbae873614340a3a78b29e7d463d2Sara Ting            if (mCanModifyEvent) {
1771dd15169500bc687107370366c3bbd8339bbcaa74Mindy Pereira                button = mView.findViewById(R.id.edit);
1772dd15169500bc687107370366c3bbd8339bbcaa74Mindy Pereira                if (button != null) {
177342896f76d81dbae873614340a3a78b29e7d463d2Sara Ting                    button.setEnabled(true);
177442896f76d81dbae873614340a3a78b29e7d463d2Sara Ting                    button.setVisibility(View.VISIBLE);
177560f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson                }
1776d8353fb85ef59a88580125207be9c914a8586758RoboErik            }
177742896f76d81dbae873614340a3a78b29e7d463d2Sara Ting
17787ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            if ((!mIsDialog && !mIsTabletConfig ||
17797ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson                    mWindowStyle == EventInfoFragment.FULL_WINDOW_STYLE) && mMenu != null) {
1780d8353fb85ef59a88580125207be9c914a8586758RoboErik                mActivity.invalidateOptionsMenu();
178169be855eccf7d1e0a4c93377db66eb4b843a1403RoboErik            }
17822bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        } else {
178371b221ae5d0f514352584a955630f5494f686c51Michael Chan            setVisibilityCommon(view, R.id.calendar, View.GONE);
1784259b8f9a21fffd3858218581e9daaf689b6b888fErik            sendAccessibilityEventIfQueryDone(TOKEN_QUERY_DUPLICATE_CALENDARS);
17852bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
17862bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
17872bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1788d8353fb85ef59a88580125207be9c914a8586758RoboErik    /**
1789d8353fb85ef59a88580125207be9c914a8586758RoboErik     *
1790d8353fb85ef59a88580125207be9c914a8586758RoboErik     */
1791d8353fb85ef59a88580125207be9c914a8586758RoboErik    private void updateMenu() {
1792d8353fb85ef59a88580125207be9c914a8586758RoboErik        if (mMenu == null) {
1793d8353fb85ef59a88580125207be9c914a8586758RoboErik            return;
1794d8353fb85ef59a88580125207be9c914a8586758RoboErik        }
1795d8353fb85ef59a88580125207be9c914a8586758RoboErik        MenuItem delete = mMenu.findItem(R.id.info_action_delete);
1796d8353fb85ef59a88580125207be9c914a8586758RoboErik        MenuItem edit = mMenu.findItem(R.id.info_action_edit);
1797d8353fb85ef59a88580125207be9c914a8586758RoboErik        if (delete != null) {
1798d8353fb85ef59a88580125207be9c914a8586758RoboErik            delete.setVisible(mCanModifyCalendar);
1799d8353fb85ef59a88580125207be9c914a8586758RoboErik            delete.setEnabled(mCanModifyCalendar);
1800d8353fb85ef59a88580125207be9c914a8586758RoboErik        }
1801d8353fb85ef59a88580125207be9c914a8586758RoboErik        if (edit != null) {
180265eeb79e62034d706503ce29d88c0e05ebd726feRoboErik            edit.setVisible(mCanModifyEvent);
180365eeb79e62034d706503ce29d88c0e05ebd726feRoboErik            edit.setEnabled(mCanModifyEvent);
1804d8353fb85ef59a88580125207be9c914a8586758RoboErik        }
1805d8353fb85ef59a88580125207be9c914a8586758RoboErik    }
1806d8353fb85ef59a88580125207be9c914a8586758RoboErik
18072bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void updateAttendees(View view) {
1808fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson        if (mAcceptedAttendees.size() + mDeclinedAttendees.size() +
1809fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson                mTentativeAttendees.size() + mNoResponseAttendees.size() > 0) {
1810c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik            mLongAttendees.clearAttendees();
18114acb2fd087308dea146b8b10f5278c59df387680RoboErik            (mLongAttendees).addAttendees(mAcceptedAttendees);
18124acb2fd087308dea146b8b10f5278c59df387680RoboErik            (mLongAttendees).addAttendees(mDeclinedAttendees);
18134acb2fd087308dea146b8b10f5278c59df387680RoboErik            (mLongAttendees).addAttendees(mTentativeAttendees);
18144acb2fd087308dea146b8b10f5278c59df387680RoboErik            (mLongAttendees).addAttendees(mNoResponseAttendees);
1815fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            mLongAttendees.setEnabled(false);
1816fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            mLongAttendees.setVisibility(View.VISIBLE);
181760f01c23282284e691fcd24918ea67087540f95dIsaac Katzenelson        } else {
1818fae6d5c17df988e957af421498124cf600ded523Isaac Katzenelson            mLongAttendees.setVisibility(View.GONE);
181971b221ae5d0f514352584a955630f5494f686c51Michael Chan        }
1820cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting
18217ffa24cba2977925b737e6bd39be59ba39609611Sara Ting        if (hasEmailableAttendees()) {
18227da27670d2a62e213e230989b250f047012a3bbdSara Ting            setVisibilityCommon(mView, R.id.email_attendees_container, View.VISIBLE);
18237ffa24cba2977925b737e6bd39be59ba39609611Sara Ting            if (emailAttendeesButton != null) {
18247ffa24cba2977925b737e6bd39be59ba39609611Sara Ting                emailAttendeesButton.setText(R.string.email_guests_label);
18257ffa24cba2977925b737e6bd39be59ba39609611Sara Ting            }
18267ffa24cba2977925b737e6bd39be59ba39609611Sara Ting        } else if (hasEmailableOrganizer()) {
18277ffa24cba2977925b737e6bd39be59ba39609611Sara Ting            setVisibilityCommon(mView, R.id.email_attendees_container, View.VISIBLE);
18287ffa24cba2977925b737e6bd39be59ba39609611Sara Ting            if (emailAttendeesButton != null) {
18297ffa24cba2977925b737e6bd39be59ba39609611Sara Ting                emailAttendeesButton.setText(R.string.email_organizer_label);
18307ffa24cba2977925b737e6bd39be59ba39609611Sara Ting            }
18317da27670d2a62e213e230989b250f047012a3bbdSara Ting        } else {
18327da27670d2a62e213e230989b250f047012a3bbdSara Ting            setVisibilityCommon(mView, R.id.email_attendees_container, View.GONE);
18337da27670d2a62e213e230989b250f047012a3bbdSara Ting        }
1834cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting    }
1835cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting
1836cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting    /**
18377da27670d2a62e213e230989b250f047012a3bbdSara Ting     * Returns true if there is at least 1 attendee that is not the viewer.
1838cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting     */
18397ffa24cba2977925b737e6bd39be59ba39609611Sara Ting    private boolean hasEmailableAttendees() {
1840cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        for (Attendee attendee : mAcceptedAttendees) {
18417da27670d2a62e213e230989b250f047012a3bbdSara Ting            if (Utils.isEmailableFrom(attendee.mEmail, mSyncAccountName)) {
18427da27670d2a62e213e230989b250f047012a3bbdSara Ting                return true;
18437da27670d2a62e213e230989b250f047012a3bbdSara Ting            }
1844cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        }
1845cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        for (Attendee attendee : mTentativeAttendees) {
18467da27670d2a62e213e230989b250f047012a3bbdSara Ting            if (Utils.isEmailableFrom(attendee.mEmail, mSyncAccountName)) {
18477da27670d2a62e213e230989b250f047012a3bbdSara Ting                return true;
18487da27670d2a62e213e230989b250f047012a3bbdSara Ting            }
1849cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        }
1850cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        for (Attendee attendee : mNoResponseAttendees) {
18517da27670d2a62e213e230989b250f047012a3bbdSara Ting            if (Utils.isEmailableFrom(attendee.mEmail, mSyncAccountName)) {
18527da27670d2a62e213e230989b250f047012a3bbdSara Ting                return true;
18537da27670d2a62e213e230989b250f047012a3bbdSara Ting            }
1854cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        }
18557da27670d2a62e213e230989b250f047012a3bbdSara Ting        for (Attendee attendee : mDeclinedAttendees) {
18567da27670d2a62e213e230989b250f047012a3bbdSara Ting            if (Utils.isEmailableFrom(attendee.mEmail, mSyncAccountName)) {
18577da27670d2a62e213e230989b250f047012a3bbdSara Ting                return true;
18587da27670d2a62e213e230989b250f047012a3bbdSara Ting            }
1859cb5f5688a4080e6a20f4f7a52adef1ed971035cbSara Ting        }
18607ffa24cba2977925b737e6bd39be59ba39609611Sara Ting        return false;
18617ffa24cba2977925b737e6bd39be59ba39609611Sara Ting    }
18627ffa24cba2977925b737e6bd39be59ba39609611Sara Ting
18637ffa24cba2977925b737e6bd39be59ba39609611Sara Ting    private boolean hasEmailableOrganizer() {
18647da27670d2a62e213e230989b250f047012a3bbdSara Ting        return mEventOrganizerEmail != null &&
18657da27670d2a62e213e230989b250f047012a3bbdSara Ting                Utils.isEmailableFrom(mEventOrganizerEmail, mSyncAccountName);
18668ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan    }
18678ce3b7db4d7644ecc8c358fd16a06c4d9af48904Michael Chan
18681ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    public void initReminders(View view, Cursor cursor) {
18691ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
18701ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // Add reminders
1871c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik        mOriginalReminders.clear();
1872c08957b48e755d34f1496d3937a24d60bdd24904RoboErik        mUnsupportedReminders.clear();
18731ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        while (cursor.moveToNext()) {
18741ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            int minutes = cursor.getInt(EditEventHelper.REMINDERS_INDEX_MINUTES);
18751ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            int method = cursor.getInt(EditEventHelper.REMINDERS_INDEX_METHOD);
1876e35a032c939f357ce435711b2fd8de1887a05011RoboErik
1877c08957b48e755d34f1496d3937a24d60bdd24904RoboErik            if (method != Reminders.METHOD_DEFAULT && !mReminderMethodValues.contains(method)) {
1878e35a032c939f357ce435711b2fd8de1887a05011RoboErik                // Stash unsupported reminder types separately so we don't alter
1879e35a032c939f357ce435711b2fd8de1887a05011RoboErik                // them in the UI
1880e35a032c939f357ce435711b2fd8de1887a05011RoboErik                mUnsupportedReminders.add(ReminderEntry.valueOf(minutes, method));
1881e35a032c939f357ce435711b2fd8de1887a05011RoboErik            } else {
1882e35a032c939f357ce435711b2fd8de1887a05011RoboErik                mOriginalReminders.add(ReminderEntry.valueOf(minutes, method));
1883e35a032c939f357ce435711b2fd8de1887a05011RoboErik            }
18841ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        }
18851ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // Sort appropriately for display (by time, then type)
18861ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Collections.sort(mOriginalReminders);
18871ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
18888b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik        if (mUserModifiedReminders) {
18898b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            // If the user has changed the list of reminders don't change what's
18908b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            // shown.
18918b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik            return;
18928b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik        }
18938b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik
18945d40a380fca9da181dfaf0c7756d4f53cbd2d3d3RoboErik        LinearLayout parent = (LinearLayout) mScrollView
18955d40a380fca9da181dfaf0c7756d4f53cbd2d3d3RoboErik                .findViewById(R.id.reminder_items_container);
18965d40a380fca9da181dfaf0c7756d4f53cbd2d3d3RoboErik        if (parent != null) {
18975d40a380fca9da181dfaf0c7756d4f53cbd2d3d3RoboErik            parent.removeAllViews();
18985d40a380fca9da181dfaf0c7756d4f53cbd2d3d3RoboErik        }
1899c08957b48e755d34f1496d3937a24d60bdd24904RoboErik        if (mReminderViews != null) {
1900c08957b48e755d34f1496d3937a24d60bdd24904RoboErik            mReminderViews.clear();
1901c08957b48e755d34f1496d3937a24d60bdd24904RoboErik        }
19025d40a380fca9da181dfaf0c7756d4f53cbd2d3d3RoboErik
19031ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        if (mHasAlarm) {
19041ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            ArrayList<ReminderEntry> reminders = mOriginalReminders;
19051ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            // Insert any minute values that aren't represented in the minutes list.
19061ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            for (ReminderEntry re : reminders) {
19071ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                EventViewUtils.addMinutesToList(
19081ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                        mActivity, mReminderMinuteValues, mReminderMinuteLabels, re.getMinutes());
19091ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            }
19101ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            // Create a UI element for each reminder.  We display all of the reminders we get
19111ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            // from the provider, even if the count exceeds the calendar maximum.  (Also, for
19121ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            // a new event, we won't have a maxReminders value available.)
19131ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            for (ReminderEntry re : reminders) {
1914e35a032c939f357ce435711b2fd8de1887a05011RoboErik                EventViewUtils.addReminder(mActivity, mScrollView, this, mReminderViews,
1915e35a032c939f357ce435711b2fd8de1887a05011RoboErik                        mReminderMinuteValues, mReminderMinuteLabels, mReminderMethodValues,
19168b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                        mReminderMethodLabels, re, Integer.MAX_VALUE, mReminderChangeListener);
19171ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            }
191806f3d6d0d3bd6d194f5a3822efd63830098284dcSara Ting            EventViewUtils.updateAddReminderButton(mView, mReminderViews, mMaxReminders);
1919e35a032c939f357ce435711b2fd8de1887a05011RoboErik            // TODO show unsupported reminder types in some fashion.
19201ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        }
19211ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    }
19221ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
19232bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    void updateResponse(View view) {
19242bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // we only let the user accept/reject/etc. a meeting if:
19252bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // a) you can edit the event's containing calendar AND
19262bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // b) you're not the organizer and only attendee AND
19272bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // c) organizerCanRespond is enabled for the calendar
19282bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // (if the attendee data has been hidden, the visible number of attendees
19292bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // will be 1 -- the calendar owner's).
19302bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // (there are more cases involved to be 100% accurate, such as
19312bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // paying attention to whether or not an attendee status was
19322bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // included in the feed, but we're currently omitting those corner cases
19332bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // for simplicity).
1934352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan
1935352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan        // TODO Switch to EditEventHelper.canRespond when this class uses CalendarEventModel.
1936d785cd533f6a3c23813c15315aed74efa9a116f5Michael Chan        if (!mCanModifyCalendar || (mHasAttendeeData && mIsOrganizer && mNumOfAttendees <= 1) ||
1937352e1a2f834460bd54e03ce94cadd36a46debacbMichael Chan                (mIsOrganizer && !mOwnerCanRespond)) {
19382bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            setVisibilityCommon(view, R.id.response_container, View.GONE);
19392bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return;
19402bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
19412bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
19422bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        setVisibilityCommon(view, R.id.response_container, View.VISIBLE);
19432bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
1944f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan
1945f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        int response;
19466bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        if (mUserSetResponse != Attendees.ATTENDEE_STATUS_NONE) {
19475afc08352fb7e2679ed00d41e6e5763ad333a7ecRoboErik            response = mUserSetResponse;
19486bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        } else if (mAttendeeResponseFromIntent != Attendees.ATTENDEE_STATUS_NONE) {
1949f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan            response = mAttendeeResponseFromIntent;
19502bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        } else {
1951f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan            response = mOriginalAttendeeResponse;
19522bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
1953f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan
1954f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        int buttonToCheck = findButtonIdForResponse(response);
1955f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        RadioGroup radioGroup = (RadioGroup) view.findViewById(R.id.response_value);
1956f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        radioGroup.check(buttonToCheck); // -1 clear all radio buttons
1957f92f46b20316e71f7291f35f4cd1b64500bebf12Michael Chan        radioGroup.setOnCheckedChangeListener(this);
19582bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
19592bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
19602bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void setTextCommon(View view, int id, CharSequence text) {
19612bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        TextView textView = (TextView) view.findViewById(id);
19622bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (textView == null)
19632bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            return;
19642bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        textView.setText(text);
19652bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
19662bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
19672bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    private void setVisibilityCommon(View view, int id, int visibility) {
19682bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        View v = view.findViewById(id);
19692bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (v != null) {
19702bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            v.setVisibility(visibility);
19712bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
19722bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        return;
19732bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
19742bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
19752bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    /**
19762bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * Taken from com.google.android.gm.HtmlConversationActivity
19772bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     *
19782bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     * Send the intent that shows the Contact info corresponding to the email address.
19792bebde787f9490408ceaf14166de4b016a10daf1Mason Tang     */
19802bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    public void showContactInfo(Attendee attendee, Rect rect) {
19812bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        // First perform lookup query to find existing contact
19822bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        final ContentResolver resolver = getActivity().getContentResolver();
19832bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        final String address = attendee.mEmail;
19842bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        final Uri dataUri = Uri.withAppendedPath(CommonDataKinds.Email.CONTENT_FILTER_URI,
19852bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                Uri.encode(address));
19862bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        final Uri lookupUri = ContactsContract.Data.getContactLookupUri(resolver, dataUri);
19872bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
19882bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        if (lookupUri != null) {
19892bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            // Found matching contact, trigger QuickContact
19902bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            QuickContact.showQuickContact(getActivity(), rect, lookupUri,
19912bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                    QuickContact.MODE_MEDIUM, null);
19922bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        } else {
19932bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            // No matching contact, ask user to create one
19942bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            final Uri mailUri = Uri.fromParts("mailto", address, null);
19952bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, mailUri);
19962bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
19972bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            // Pass along full E-mail string for possible create dialog
19982bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            Rfc822Token sender = new Rfc822Token(attendee.mName, attendee.mEmail, null);
19992bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            intent.putExtra(Intents.EXTRA_CREATE_DESCRIPTION, sender.toString());
20002bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
20012bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            // Only provide personal name hint if we have one
20022bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            final String senderPersonal = attendee.mName;
20032bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            if (!TextUtils.isEmpty(senderPersonal)) {
20042bebde787f9490408ceaf14166de4b016a10daf1Mason Tang                intent.putExtra(Intents.Insert.NAME, senderPersonal);
20052bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            }
20062bebde787f9490408ceaf14166de4b016a10daf1Mason Tang
20072bebde787f9490408ceaf14166de4b016a10daf1Mason Tang            startActivity(intent);
20082bebde787f9490408ceaf14166de4b016a10daf1Mason Tang        }
20092bebde787f9490408ceaf14166de4b016a10daf1Mason Tang    }
2010cb81189e4868769ea016253eca104e46df2f033aErik
2011cb81189e4868769ea016253eca104e46df2f033aErik    @Override
20127c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    public void onPause() {
20137c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        mIsPaused = true;
20147c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        mHandler.removeCallbacks(onDeleteRunnable);
20157c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        super.onPause();
2016b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        // Remove event deletion alert box since it is being rebuild in the OnResume
2017b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        // This is done to get the same behavior on OnResume since the AlertDialog is gone on
2018b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        // rotation but not if you press the HOME key
2019b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        if (mDeleteDialogVisible && mDeleteHelper != null) {
2020b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson            mDeleteHelper.dismissAlertDialog();
2021b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson            mDeleteHelper = null;
2022b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        }
20237c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    }
20247c6236d5553dc9f3d004ebbed794249713a11d19RoboErik
20257c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    @Override
20267c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    public void onResume() {
20277c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        super.onResume();
2028363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan        if (mIsDialog) {
2029363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan            setDialogSize(getActivity().getResources());
2030363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan            applyDialogParams();
2031363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan        }
20327c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        mIsPaused = false;
20337c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        if (mDismissOnResume) {
20347c6236d5553dc9f3d004ebbed794249713a11d19RoboErik            mHandler.post(onDeleteRunnable);
20357c6236d5553dc9f3d004ebbed794249713a11d19RoboErik        }
2036b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        // Display the "delete confirmation" dialog if needed
2037b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        if (mDeleteDialogVisible) {
2038b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson            mDeleteHelper = new DeleteEventHelper(
2039b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                    mContext, mActivity,
2040b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                    !mIsDialog && !mIsTabletConfig /* exitWhenDone */);
2041b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson            mDeleteHelper.setOnDismissListener(createDeleteOnDismissListener());
2042b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson            mDeleteHelper.delete(mStartMillis, mEndMillis, mEventId, -1, onDeleteRunnable);
2043b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        }
20447c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    }
20457c6236d5553dc9f3d004ebbed794249713a11d19RoboErik
20467c6236d5553dc9f3d004ebbed794249713a11d19RoboErik    @Override
2047cb81189e4868769ea016253eca104e46df2f033aErik    public void eventsChanged() {
2048cb81189e4868769ea016253eca104e46df2f033aErik    }
2049cb81189e4868769ea016253eca104e46df2f033aErik
2050cb81189e4868769ea016253eca104e46df2f033aErik    @Override
2051cb81189e4868769ea016253eca104e46df2f033aErik    public long getSupportedEventTypes() {
2052cb81189e4868769ea016253eca104e46df2f033aErik        return EventType.EVENTS_CHANGED;
2053cb81189e4868769ea016253eca104e46df2f033aErik    }
2054cb81189e4868769ea016253eca104e46df2f033aErik
2055cb81189e4868769ea016253eca104e46df2f033aErik    @Override
2056cb81189e4868769ea016253eca104e46df2f033aErik    public void handleEvent(EventInfo event) {
2057f836d4af478310abc9b63f1afa6ab964e2478fedRoboErik        if (event.eventType == EventType.EVENTS_CHANGED && mHandler != null) {
2058cb81189e4868769ea016253eca104e46df2f033aErik            // reload the data
205980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            reloadEvents();
2060cb81189e4868769ea016253eca104e46df2f033aErik        }
2061cb81189e4868769ea016253eca104e46df2f033aErik    }
20621ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
206380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    public void reloadEvents() {
206480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        mHandler.startQuery(TOKEN_QUERY_EVENT, null, mUri, EVENT_PROJECTION,
206580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                null, null, null);
206680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    }
20671ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
20681ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    @Override
20691ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    public void onClick(View view) {
20701ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
20711ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // This must be a click on one of the "remove reminder" buttons
20721ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        LinearLayout reminderItem = (LinearLayout) view.getParent();
20731ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        LinearLayout parent = (LinearLayout) reminderItem.getParent();
20741ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        parent.removeView(reminderItem);
20751ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mReminderViews.remove(reminderItem);
20768b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik        mUserModifiedReminders = true;
207706f3d6d0d3bd6d194f5a3822efd63830098284dcSara Ting        EventViewUtils.updateAddReminderButton(mView, mReminderViews, mMaxReminders);
20781ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    }
20791ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
20801ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
20811ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    /**
20821ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * Add a new reminder when the user hits the "add reminder" button.  We use the default
20831ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * reminder time and method.
20841ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     */
20851ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private void addReminder() {
20861ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // TODO: when adding a new reminder, make it different from the
20871ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // last one in the list (if any).
20881ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        if (mDefaultReminderMinutes == GeneralPreferences.NO_REMINDER) {
20891ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            EventViewUtils.addReminder(mActivity, mScrollView, this, mReminderViews,
20908b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mReminderMinuteValues, mReminderMinuteLabels, mReminderMethodValues,
20918b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mReminderMethodLabels,
20928b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    ReminderEntry.valueOf(GeneralPreferences.REMINDER_DEFAULT_TIME), mMaxReminders,
20938b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mReminderChangeListener);
20941ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        } else {
20951ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            EventViewUtils.addReminder(mActivity, mScrollView, this, mReminderViews,
20968b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mReminderMinuteValues, mReminderMinuteLabels, mReminderMethodValues,
20978b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mReminderMethodLabels, ReminderEntry.valueOf(mDefaultReminderMinutes),
20988b5743c1bcff53f13b4890ba05fb013bbf8f29bcRoboErik                    mMaxReminders, mReminderChangeListener);
20991ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        }
21001ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
210106f3d6d0d3bd6d194f5a3822efd63830098284dcSara Ting        EventViewUtils.updateAddReminderButton(mView, mReminderViews, mMaxReminders);
210206f3d6d0d3bd6d194f5a3822efd63830098284dcSara Ting    }
21031ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
2104e35a032c939f357ce435711b2fd8de1887a05011RoboErik    synchronized private void prepareReminders() {
2105e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // Nothing to do if we've already built these lists _and_ we aren't
2106e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // removing not allowed methods
2107e35a032c939f357ce435711b2fd8de1887a05011RoboErik        if (mReminderMinuteValues != null && mReminderMinuteLabels != null
2108e35a032c939f357ce435711b2fd8de1887a05011RoboErik                && mReminderMethodValues != null && mReminderMethodLabels != null
2109e35a032c939f357ce435711b2fd8de1887a05011RoboErik                && mCalendarAllowedReminders == null) {
2110e35a032c939f357ce435711b2fd8de1887a05011RoboErik            return;
2111e35a032c939f357ce435711b2fd8de1887a05011RoboErik        }
2112e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // Load the labels and corresponding numeric values for the minutes and methods lists
2113e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // from the assets.  If we're switching calendars, we need to clear and re-populate the
2114e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // lists (which may have elements added and removed based on calendar properties).  This
2115e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // is mostly relevant for "methods", since we shouldn't have any "minutes" values in a
2116e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // new event that aren't in the default set.
21171ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Resources r = mActivity.getResources();
21181ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mReminderMinuteValues = loadIntegerArray(r, R.array.reminder_minutes_values);
21191ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mReminderMinuteLabels = loadStringArray(r, R.array.reminder_minutes_labels);
21201ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mReminderMethodValues = loadIntegerArray(r, R.array.reminder_methods_values);
21211ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mReminderMethodLabels = loadStringArray(r, R.array.reminder_methods_labels);
2122e35a032c939f357ce435711b2fd8de1887a05011RoboErik
2123e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // Remove any reminder methods that aren't allowed for this calendar.  If this is
2124e35a032c939f357ce435711b2fd8de1887a05011RoboErik        // a new event, mCalendarAllowedReminders may not be set the first time we're called.
2125e35a032c939f357ce435711b2fd8de1887a05011RoboErik        if (mCalendarAllowedReminders != null) {
2126e35a032c939f357ce435711b2fd8de1887a05011RoboErik            EventViewUtils.reduceMethodList(mReminderMethodValues, mReminderMethodLabels,
2127e35a032c939f357ce435711b2fd8de1887a05011RoboErik                    mCalendarAllowedReminders);
2128e35a032c939f357ce435711b2fd8de1887a05011RoboErik        }
2129e35a032c939f357ce435711b2fd8de1887a05011RoboErik        if (mView != null) {
2130e35a032c939f357ce435711b2fd8de1887a05011RoboErik            mView.invalidate();
2131e35a032c939f357ce435711b2fd8de1887a05011RoboErik        }
21321ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    }
21331ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21341ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21351ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private boolean saveReminders() {
21361ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(3);
21371ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21381ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // Read reminders from UI
21391ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        mReminders = EventViewUtils.reminderItemsToReminders(mReminderViews,
21401ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                mReminderMinuteValues, mReminderMethodValues);
2141e35a032c939f357ce435711b2fd8de1887a05011RoboErik        mOriginalReminders.addAll(mUnsupportedReminders);
2142e35a032c939f357ce435711b2fd8de1887a05011RoboErik        Collections.sort(mOriginalReminders);
2143e35a032c939f357ce435711b2fd8de1887a05011RoboErik        mReminders.addAll(mUnsupportedReminders);
2144e35a032c939f357ce435711b2fd8de1887a05011RoboErik        Collections.sort(mReminders);
21451ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21461ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // Check if there are any changes in the reminder
21471ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        boolean changed = EditEventHelper.saveReminders(ops, mEventId, mReminders,
21481ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson                mOriginalReminders, false /* no force save */);
21491ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21501ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        if (!changed) {
21511ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            return false;
21521ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        }
21531ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21541ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // save new reminders
21551ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        AsyncQueryService service = new AsyncQueryService(getActivity());
21561ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        service.startBatch(0, null, Calendars.CONTENT_URI.getAuthority(), ops, 0);
21571ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        // Update the "hasAlarm" field for the event
21581ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, mEventId);
21591ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        int len = mReminders.size();
21601ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        boolean hasAlarm = len > 0;
21611ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        if (hasAlarm != mHasAlarm) {
21621ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            ContentValues values = new ContentValues();
21631ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            values.put(Events.HAS_ALARM, hasAlarm ? 1 : 0);
21641ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            service.startUpdate(0, null, uri, values, null, null, 0);
21651ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        }
21661ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        return true;
21671ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    }
21681ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21691ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    /**
217042896f76d81dbae873614340a3a78b29e7d463d2Sara Ting     * Email all the attendees of the event, except for the viewer (so as to not email
217142896f76d81dbae873614340a3a78b29e7d463d2Sara Ting     * himself) and resources like conference rooms.
217242896f76d81dbae873614340a3a78b29e7d463d2Sara Ting     */
217342896f76d81dbae873614340a3a78b29e7d463d2Sara Ting    private void emailAttendees() {
21747da27670d2a62e213e230989b250f047012a3bbdSara Ting        Intent i = new Intent(getActivity(), QuickResponseActivity.class);
21757da27670d2a62e213e230989b250f047012a3bbdSara Ting        i.putExtra(QuickResponseActivity.EXTRA_EVENT_ID, mEventId);
21767da27670d2a62e213e230989b250f047012a3bbdSara Ting        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
21777da27670d2a62e213e230989b250f047012a3bbdSara Ting        startActivity(i);
217842896f76d81dbae873614340a3a78b29e7d463d2Sara Ting    }
217942896f76d81dbae873614340a3a78b29e7d463d2Sara Ting
218042896f76d81dbae873614340a3a78b29e7d463d2Sara Ting    /**
21811ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * Loads an integer array asset into a list.
21821ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     */
21831ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static ArrayList<Integer> loadIntegerArray(Resources r, int resNum) {
21841ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        int[] vals = r.getIntArray(resNum);
21851ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        int size = vals.length;
21861ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        ArrayList<Integer> list = new ArrayList<Integer>(size);
21871ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21881ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        for (int i = 0; i < size; i++) {
21891ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson            list.add(vals[i]);
21901ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        }
21911ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
21921ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        return list;
21931ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    }
21941ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    /**
21951ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     * Loads a String array asset into a list.
21961ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson     */
21971ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    private static ArrayList<String> loadStringArray(Resources r, int resNum) {
21981ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        String[] labels = r.getStringArray(resNum);
21991ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        ArrayList<String> list = new ArrayList<String>(Arrays.asList(labels));
22001ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson        return list;
22011ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson    }
22021ce35aadf71e3d68b72940bc327f285530a85032Isaac Katzenelson
2203b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson    public void onDeleteStarted() {
2204b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson        mEventDeletionStarted = true;
2205b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson    }
2206b33cdf41092c79ca3502868d494bc284f4090267Isaac Katzenelson
2207b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson    private Dialog.OnDismissListener createDeleteOnDismissListener() {
2208b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson        return new Dialog.OnDismissListener() {
2209b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                    @Override
2210b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                    public void onDismiss(DialogInterface dialog) {
2211b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                        // Since OnPause will force the dialog to dismiss , do
2212b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                        // not change the dialog status
2213b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                        if (!mIsPaused) {
2214b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                            mDeleteDialogVisible = false;
2215b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                        }
2216b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                    }
2217b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson                };
2218b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson    }
2219b0a313a3c216e3eeceebd81d3edc6fc60357a055Isaac Katzenelson
222080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    public long getEventId() {
222180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        return mEventId;
222280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    }
222380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
222480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    public long getStartMillis() {
222580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        return mStartMillis;
222680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    }
222780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    public long getEndMillis() {
222880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        return mEndMillis;
222980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    }
2230363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan    private void setDialogSize(Resources r) {
2231363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan        mDialogWidth = (int)r.getDimension(R.dimen.event_info_dialog_width);
2232363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan        mDialogHeight = (int)r.getDimension(R.dimen.event_info_dialog_height);
2233363aa9c237a33e9e1a40bdfd9039dcaaa855a5a0Michael Chan    }
223480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
223580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
22362bebde787f9490408ceaf14166de4b016a10daf1Mason Tang}
2237