14c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson /*
2bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Copyright (C) 2010 The Android Open Source Project
3bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa *
4bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
5bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * you may not use this file except in compliance with the License.
6bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * You may obtain a copy of the License at
7bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa *
8bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
9bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa *
10bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
11bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
12bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * See the License for the specific language governing permissions and
14bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa * limitations under the License.
15bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa */
16bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
17bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawapackage com.android.calendar.event;
18bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
19bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.CalendarEventModel.Attendee;
20bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.ContactsAsyncHelper;
21bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.R;
22ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport com.android.calendar.Utils;
23bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.calendar.event.EditEventHelper.AttendeeItem;
24bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport com.android.common.Rfc822Validator;
25bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
26bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.AsyncQueryHandler;
27bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.ContentResolver;
28bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.ContentUris;
29bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.Context;
30bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.content.res.Resources;
31bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.database.Cursor;
324c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelsonimport android.graphics.ColorMatrix;
334c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelsonimport android.graphics.ColorMatrixColorFilter;
34bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.graphics.Paint;
35bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.graphics.drawable.Drawable;
36bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.net.Uri;
37a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
38bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Email;
39ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport android.provider.ContactsContract.CommonDataKinds.Identity;
40bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.provider.ContactsContract.Contacts;
41ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport android.provider.ContactsContract.Data;
42ddbc002f3471e224fc112d406116e396ee1c50aeSara Tingimport android.provider.ContactsContract.RawContacts;
43bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.text.TextUtils;
44bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.text.util.Rfc822Token;
45bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.util.AttributeSet;
46bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.util.Log;
47bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.view.LayoutInflater;
48bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.view.View;
49bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.ImageButton;
50bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.LinearLayout;
51bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.QuickContactBadge;
52bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport android.widget.TextView;
53bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
54bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport java.util.ArrayList;
55bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport java.util.HashMap;
56bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawaimport java.util.LinkedHashSet;
57bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
58bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawapublic class AttendeesView extends LinearLayout implements View.OnClickListener {
59bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private static final String TAG = "AttendeesView";
60bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private static final boolean DEBUG = false;
61bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
628fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann    private static final int EMAIL_PROJECTION_CONTACT_ID_INDEX = 0;
638fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann    private static final int EMAIL_PROJECTION_CONTACT_LOOKUP_INDEX = 1;
648fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann    private static final int EMAIL_PROJECTION_PHOTO_ID_INDEX = 2;
65bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
66ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting    private static final String[] PROJECTION = new String[] {
67ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        RawContacts.CONTACT_ID,     // 0
688fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        Contacts.LOOKUP_KEY,        // 1
69ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        Contacts.PHOTO_ID,          // 2
70bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    };
71bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
72bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final Context mContext;
73bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final LayoutInflater mInflater;
74bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final PresenceQueryHandler mPresenceQueryHandler;
75bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final Drawable mDefaultBadge;
764c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    private final ColorMatrixColorFilter mGrayscaleFilter;
77bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
78bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // TextView shown at the top of each type of attendees
79bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // e.g.
80bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // Yes  <-- divider
81bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // example_for_yes <exampleyes@example.com>
82bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // No <-- divider
83bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // example_for_no <exampleno@example.com>
844c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    private final CharSequence[] mEntries;
85bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final View mDividerForYes;
86bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final View mDividerForNo;
87bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final View mDividerForMaybe;
88bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private final View mDividerForNoResponse;
894c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    private final int mNoResponsePhotoAlpha;
904c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    private final int mDefaultPhotoAlpha;
91bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private Rfc822Validator mValidator;
92bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
93bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // Number of attendees responding or not responding.
94bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private int mYes;
95bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private int mNo;
96bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private int mMaybe;
97bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private int mNoResponse;
98bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
9980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    // Cache for loaded photos
10080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson    HashMap<String, Drawable> mRecycledPhotos;
10180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
102bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public AttendeesView(Context context, AttributeSet attrs) {
103bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        super(context, attrs);
104bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        mContext = context;
105ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
106bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        mPresenceQueryHandler = new PresenceQueryHandler(context.getContentResolver());
107bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
108bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final Resources resources = context.getResources();
109bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        mDefaultBadge = resources.getDrawable(R.drawable.ic_contact_picture);
1104c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mNoResponsePhotoAlpha =
1114c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            resources.getInteger(R.integer.noresponse_attendee_photo_alpha_level);
1124c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mDefaultPhotoAlpha = resources.getInteger(R.integer.default_attendee_photo_alpha_level);
1134c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson
1144c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        // Create dividers between groups of attendees (accepted, declined, etc...)
1154c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mEntries = resources.getTextArray(R.array.response_labels1);
1164c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mDividerForYes = constructDividerView(mEntries[1]);
1174c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mDividerForNo = constructDividerView(mEntries[3]);
1184c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mDividerForMaybe = constructDividerView(mEntries[2]);
1194c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mDividerForNoResponse = constructDividerView(mEntries[0]);
1204c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson
1214c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        // Create a filter to convert photos of declined attendees to grayscale.
1224c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        ColorMatrix matrix = new ColorMatrix();
1234c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        matrix.setSaturation(0);
1244c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        mGrayscaleFilter = new ColorMatrixColorFilter(matrix);
125bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
126bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
127bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
1284c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    // Disable/enable removal of attendings
129ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan    @Override
130ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan    public void setEnabled(boolean enabled) {
131ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        super.setEnabled(enabled);
132ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        int visibility = isEnabled() ? View.VISIBLE : View.GONE;
133ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        int count = getChildCount();
134ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        for (int i = 0; i < count; i++) {
135ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            View child = getChildAt(i);
136ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            View minusButton = child.findViewById(R.id.contact_remove);
137ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            if (minusButton != null) {
138ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                minusButton.setVisibility(visibility);
139ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            }
140ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        }
141ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan    }
142ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan
143bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public void setRfc822Validator(Rfc822Validator validator) {
144bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        mValidator = validator;
145bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
146bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
147bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private View constructDividerView(CharSequence label) {
14810b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        final TextView textView =
14910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson            (TextView)mInflater.inflate(R.layout.event_info_label, this, false);
150bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        textView.setText(label);
151bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        textView.setClickable(false);
152bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        return textView;
153bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
154bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
1554c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    // Add the number of attendees in the specific status (corresponding to the divider) in
1564c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    // parenthesis next to the label
1574c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    private void updateDividerViewLabel(View divider, CharSequence label, int count) {
1584c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        if (count <= 0) {
1594c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            ((TextView)divider).setText(label);
1604c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        }
1614c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        else {
1624c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            ((TextView)divider).setText(label + " (" + count + ")");
1634c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        }
1644c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson    }
1654c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson
1664c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson
167bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    /**
168bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     * Inflates a layout for a given attendee view and set up each element in it, and returns
169bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     * the constructed View object. The object is also stored in {@link AttendeeItem#mView}.
170bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     */
171bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private View constructAttendeeView(AttendeeItem item) {
172bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        item.mView = mInflater.inflate(R.layout.contact_item, null);
173bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        return updateAttendeeView(item);
174bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
175bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
176bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    /**
177bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     * Set up each element in {@link AttendeeItem#mView} using the latest information. View
178bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     * object is reused.
179bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     */
180bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private View updateAttendeeView(AttendeeItem item) {
181bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final Attendee attendee = item.mAttendee;
182bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final View view = item.mView;
183ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        final TextView nameView = (TextView) view.findViewById(R.id.name);
184bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        nameView.setText(TextUtils.isEmpty(attendee.mName) ? attendee.mEmail : attendee.mName);
185bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        if (item.mRemoved) {
186bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            nameView.setPaintFlags(Paint.STRIKE_THRU_TEXT_FLAG | nameView.getPaintFlags());
187bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        } else {
188bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            nameView.setPaintFlags((~Paint.STRIKE_THRU_TEXT_FLAG) & nameView.getPaintFlags());
189bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
190bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
191ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        // Set up the Image button even if the view is disabled
192ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        // Everything will be ready when the view is enabled later
193ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        final ImageButton button = (ImageButton) view.findViewById(R.id.contact_remove);
1949f5268d5bdfafe5c20dba64fbca124fcf25d68d9Erik        button.setVisibility(isEnabled() ? View.VISIBLE : View.GONE);
195bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        button.setTag(item);
196bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        if (item.mRemoved) {
19767c0ac313280bbe0ae4c2e191cf64d926995c7c7Michael Chan            button.setImageResource(R.drawable.ic_menu_add_field_holo_light);
1989ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson            button.setContentDescription(mContext.getString(R.string.accessibility_add_attendee));
199bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        } else {
20067c0ac313280bbe0ae4c2e191cf64d926995c7c7Michael Chan            button.setImageResource(R.drawable.ic_menu_remove_field_holo_light);
2019ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson            button.setContentDescription(mContext.
2029ceed1f3df98c5fc85441da0c6e7e5d45cf17a1eIsaac Katzenelson                    getString(R.string.accessibility_remove_attendee));
203bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
204bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        button.setOnClickListener(this);
205bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
2068fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        final QuickContactBadge badgeView = (QuickContactBadge) view.findViewById(R.id.badge);
20780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
20880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        Drawable badge = null;
20980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        // Search for photo in recycled photos
21080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        if (mRecycledPhotos != null) {
21180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            badge = mRecycledPhotos.get(item.mAttendee.mEmail);
21280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        }
21380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        if (badge != null) {
21480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            item.mBadge = badge;
21580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        }
21680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        badgeView.setImageDrawable(item.mBadge);
21780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
2184c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        if (item.mAttendee.mStatus == Attendees.ATTENDEE_STATUS_NONE) {
2194c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            item.mBadge.setAlpha(mNoResponsePhotoAlpha);
2204c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        } else {
2214c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            item.mBadge.setAlpha(mDefaultPhotoAlpha);
2224c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        }
2234c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        if (item.mAttendee.mStatus == Attendees.ATTENDEE_STATUS_DECLINED) {
2244c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            item.mBadge.setColorFilter(mGrayscaleFilter);
2254c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        } else {
2264c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson            item.mBadge.setColorFilter(null);
2274c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson        }
22880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
2298fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        // If we know the lookup-uri of the contact, it is a good idea to set this here. This
2308fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        // allows QuickContact to be started without an extra database lookup. If we don't know
2318fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        // the lookup uri (yet), we can set Email and QuickContact will lookup once tapped.
2328fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        if (item.mContactLookupUri != null) {
2338fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann            badgeView.assignContactUri(item.mContactLookupUri);
2348fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        } else {
2358fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann            badgeView.assignContactFromEmail(item.mAttendee.mEmail, true);
2368fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        }
2378fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann        badgeView.setMaxHeight(60);
238bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
239bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        return view;
240bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
241bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
242bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public boolean contains(Attendee attendee) {
243bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final int size = getChildCount();
244bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        for (int i = 0; i < size; i++) {
245bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            final View view = getChildAt(i);
246ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            if (view instanceof TextView) { // divider
247bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                continue;
248bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
249ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            AttendeeItem attendeeItem = (AttendeeItem) view.getTag();
250bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            if (TextUtils.equals(attendee.mEmail, attendeeItem.mAttendee.mEmail)) {
251bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                return true;
252bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
253bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
254bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        return false;
255bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
256bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
257c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik    public void clearAttendees() {
25880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
25980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        // Before clearing the views, save all the badges. The updateAtendeeView will use the saved
26080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        // photo instead of the default badge thus prevent switching between the two while the
26180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        // most current photo is loaded in the background.
26280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        mRecycledPhotos = new HashMap<String, Drawable>  ();
26380d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        final int size = getChildCount();
26480d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        for (int i = 0; i < size; i++) {
26580d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            final View view = getChildAt(i);
26680d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            if (view instanceof TextView) { // divider
26780d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson                continue;
26880d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            }
26980d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            AttendeeItem attendeeItem = (AttendeeItem) view.getTag();
27080d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson            mRecycledPhotos.put(attendeeItem.mAttendee.mEmail, attendeeItem.mBadge);
27180d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson        }
27280d640f3edc455d053a0e71a419f222a6f03385eIsaac Katzenelson
273c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik        removeAllViews();
274c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik        mYes = 0;
275c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik        mNo = 0;
276c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik        mMaybe = 0;
277c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik        mNoResponse = 0;
278c7f3c3896f1bc4cad43aa7f0bca1dee603704613RoboErik    }
2794c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson
280bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private void addOneAttendee(Attendee attendee) {
281bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        if (contains(attendee)) {
282bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            return;
283bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
2841784d2de8ee81c6759bef7199a902e13de3b300fRoboErik        final AttendeeItem item = new AttendeeItem(attendee, mDefaultBadge);
285bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final int status = attendee.mStatus;
286bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final int index;
28710b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        boolean firstAttendeeInCategory = false;
288bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        switch (status) {
289ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            case Attendees.ATTENDEE_STATUS_ACCEPTED: {
290ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                final int startIndex = 0;
2914c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson                updateDividerViewLabel(mDividerForYes, mEntries[1], mYes + 1);
292ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                if (mYes == 0) {
293ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                    addView(mDividerForYes, startIndex);
29410b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                    firstAttendeeInCategory = true;
295ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                }
296ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                mYes++;
297ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                index = startIndex + mYes;
298ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                break;
299bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
300ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            case Attendees.ATTENDEE_STATUS_DECLINED: {
301ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                final int startIndex = (mYes == 0 ? 0 : 1 + mYes);
3024c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson                updateDividerViewLabel(mDividerForNo, mEntries[3], mNo + 1);
303ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                if (mNo == 0) {
304ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                    addView(mDividerForNo, startIndex);
30510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                    firstAttendeeInCategory = true;
306ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                }
307ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                mNo++;
308ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                index = startIndex + mNo;
309ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                break;
310bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
311ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            case Attendees.ATTENDEE_STATUS_TENTATIVE: {
312ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                final int startIndex = (mYes == 0 ? 0 : 1 + mYes) + (mNo == 0 ? 0 : 1 + mNo);
3134c5475e6d27497be020d3098c4554fe353d19d38Isaac Katzenelson                updateDividerViewLabel(mDividerForMaybe, mEntries[2], mMaybe + 1);
314ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                if (mMaybe == 0) {
315ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                    addView(mDividerForMaybe, startIndex);
31610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                    firstAttendeeInCategory = true;
317ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                }
318ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                mMaybe++;
319ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                index = startIndex + mMaybe;
320ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                break;
321ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            }
322ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan            default: {
323ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                final int startIndex = (mYes == 0 ? 0 : 1 + mYes) + (mNo == 0 ? 0 : 1 + mNo)
324ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                        + (mMaybe == 0 ? 0 : 1 + mMaybe);
32510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                updateDividerViewLabel(mDividerForNoResponse, mEntries[0], mNoResponse + 1);
32610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                if (mNoResponse == 0) {
32710b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                    addView(mDividerForNoResponse, startIndex);
32810b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                    firstAttendeeInCategory = true;
32910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                }
330ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                mNoResponse++;
33110b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                index = startIndex + mNoResponse;
332ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan                break;
333bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
334bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
335bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
336bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final View view = constructAttendeeView(item);
337bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        view.setTag(item);
338bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        addView(view, index);
33910b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        // Show separator between Attendees
34010b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson        if (!firstAttendeeInCategory) {
34110b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson            View prevItem = getChildAt(index - 1);
34210b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson            if (prevItem != null) {
34310b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                View Separator = prevItem.findViewById(R.id.contact_separator);
34410b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                if (Separator != null) {
34510b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                    Separator.setVisibility(View.VISIBLE);
34610b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson                }
34710b60216d349641dd03eb65407807539b0b626dfIsaac Katzenelson            }
348bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
349bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
350ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        Uri uri;
351ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        String selection = null;
352ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        String[] selectionArgs = null;
353ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        if (attendee.mIdentity != null && attendee.mIdNamespace != null) {
354ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            // Query by identity + namespace
355ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            uri = Data.CONTENT_URI;
356ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            selection = Data.MIMETYPE + "=? AND " + Identity.IDENTITY + "=? AND " +
357ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                    Identity.NAMESPACE + "=?";
358ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            selectionArgs = new String[] {Identity.CONTENT_ITEM_TYPE, attendee.mIdentity,
359ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                    attendee.mIdNamespace};
360ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        } else {
361ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            // Query by email
362ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting            uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(attendee.mEmail));
363ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        }
364ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting
365ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting        mPresenceQueryHandler.startQuery(item.mUpdateCounts + 1, item, uri, PROJECTION, selection,
366ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                selectionArgs, null);
367bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
368bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
369bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public void addAttendees(ArrayList<Attendee> attendees) {
370bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        synchronized (this) {
371bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            for (final Attendee attendee : attendees) {
372bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                addOneAttendee(attendee);
373bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
374bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
375bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
376bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
377bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public void addAttendees(HashMap<String, Attendee> attendees) {
378bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        synchronized (this) {
379bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            for (final Attendee attendee : attendees.values()) {
380bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                addOneAttendee(attendee);
381bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
382bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
383bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
384bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
385bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public void addAttendees(String attendees) {
386bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final LinkedHashSet<Rfc822Token> addresses =
387bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                EditEventHelper.getAddressesFromList(attendees, mValidator);
388bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        synchronized (this) {
389bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            for (final Rfc822Token address : addresses) {
390bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                final Attendee attendee = new Attendee(address.getName(), address.getAddress());
391bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                if (TextUtils.isEmpty(attendee.mName)) {
392bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                    attendee.mName = attendee.mEmail;
393bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                }
394bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                addOneAttendee(attendee);
395bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
396bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
397bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
398bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
399bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    /**
400bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     * Returns true when the attendee at that index is marked as "removed" (the name of
401bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     * the attendee is shown with a strike through line).
402bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa     */
403bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public boolean isMarkAsRemoved(int index) {
404bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final View view = getChildAt(index);
405ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        if (view instanceof TextView) { // divider
406bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            return false;
407bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
408ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        return ((AttendeeItem) view.getTag()).mRemoved;
409bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
410bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
411bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    // TODO put this into a Loader for auto-requeries
412bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    private class PresenceQueryHandler extends AsyncQueryHandler {
413bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        public PresenceQueryHandler(ContentResolver cr) {
414bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            super(cr);
415bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
416bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
417bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        @Override
418bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        protected void onQueryComplete(int queryIndex, Object cookie, Cursor cursor) {
419bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            if (cursor == null || cookie == null) {
420bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                if (DEBUG) {
421bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                    Log.d(TAG, "onQueryComplete: cursor=" + cursor + ", cookie=" + cookie);
422bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                }
423bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                return;
424bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
425bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
426bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            final AttendeeItem item = (AttendeeItem)cookie;
427bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            try {
4288fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                if (item.mUpdateCounts < queryIndex) {
4298fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                    item.mUpdateCounts = queryIndex;
4308fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                    if (cursor.moveToFirst()) {
4318fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        final long contactId = cursor.getLong(EMAIL_PROJECTION_CONTACT_ID_INDEX);
4328fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        final Uri contactUri =
4338fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
4348fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann
4358fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        final String lookupKey =
4368fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                cursor.getString(EMAIL_PROJECTION_CONTACT_LOOKUP_INDEX);
4378fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        item.mContactLookupUri = Contacts.getLookupUri(contactId, lookupKey);
4388fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann
4398fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        final long photoId = cursor.getLong(EMAIL_PROJECTION_PHOTO_ID_INDEX);
4408fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        // If we found a picture, start the async loading
4418fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        if (photoId > 0) {
4428fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                            // Query for this contacts picture
4438fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                            ContactsAsyncHelper.retrieveContactPhotoAsync(
4448fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                    mContext, item, new Runnable() {
4458fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                        @Override
4468fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                        public void run() {
4478fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                            updateAttendeeView(item);
4488fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                        }
4498fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                                    }, contactUri);
4508fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        } else {
4518fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                            // call update view to make sure that the lookup key gets set in
4528fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                            // the QuickContactBadge
4538fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                            updateAttendeeView(item);
4548fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        }
4558fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                    } else {
456ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                        // Contact not found.  For real emails, keep the QuickContactBadge with
457ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                        // its Email address set, so that the user can create a contact by tapping.
4588fa3111ceaab2b26a322caa873f352bb4eb3e783Daniel Lehmann                        item.mContactLookupUri = null;
459ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                        if (!Utils.isValidEmail(item.mAttendee.mEmail)) {
460ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                            item.mAttendee.mEmail = null;
461ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                            updateAttendeeView(item);
462ddbc002f3471e224fc112d406116e396ee1c50aeSara Ting                        }
463bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                    }
464bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                }
465bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            } finally {
466bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa                cursor.close();
467bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            }
468bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
469bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
470bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
471bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public Attendee getItem(int index) {
472bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final View view = getChildAt(index);
473ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        if (view instanceof TextView) { // divider
474bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa            return null;
475bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        }
476ddbf80860566df8425f38a32190e9a64cad4e389Michael Chan        return ((AttendeeItem) view.getTag()).mAttendee;
477bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
478bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa
479bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    @Override
480bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    public void onClick(View view) {
481bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        // Button corresponding to R.id.contact_remove.
482bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        final AttendeeItem item = (AttendeeItem) view.getTag();
483bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        item.mRemoved = !item.mRemoved;
484bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa        updateAttendeeView(item);
485bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa    }
486bdcb9fcc732d52708fafb068f535a2c93ff2356fDaisuke Miyakawa}
487