1/*
2 * Copyright (C) 2007-2008 Esmertec AG.
3 * Copyright (C) 2007-2008 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.im.app;
19
20import com.android.im.R;
21import com.android.im.provider.Imps;
22
23import android.app.ListActivity;
24import android.content.Context;
25import android.content.Intent;
26import android.database.Cursor;
27import android.database.DatabaseUtils;
28import android.net.Uri;
29import android.os.Bundle;
30import android.text.Editable;
31import android.text.TextWatcher;
32import android.util.Log;
33import android.view.View;
34import android.widget.EditText;
35import android.widget.Filter;
36import android.widget.ListView;
37import android.widget.ResourceCursorAdapter;
38
39/**
40 * Activity used to pick a contact.
41 */
42public class ContactsPickerActivity extends ListActivity {
43    public final static String EXTRA_EXCLUDED_CONTACTS = "excludes";
44
45    public final static String EXTRA_RESULT_USERNAME = "result";
46
47    private ContactsAdapter mAdapter;
48    private String mExcludeClause;
49    Uri mData;
50    Filter mFilter;
51
52    private static final void log(String msg) {
53        Log.d(ImApp.LOG_TAG, "<ContactsPickerActivity> " + msg);
54    }
55
56    @Override
57    protected void onCreate(Bundle icicle) {
58        super.onCreate(icicle);
59
60        setContentView(R.layout.contacts_picker_activity);
61        if(!resolveIntent()){
62            if(Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
63                log("no data, finish");
64            }
65            finish();
66            return;
67        }
68
69        EditText filter = (EditText)findViewById(R.id.filter);
70        filter.addTextChangedListener(new TextWatcher() {
71            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
72            }
73
74            public void onTextChanged(CharSequence s, int start, int before, int count) {
75                mFilter.filter(s);
76            }
77
78            public void afterTextChanged(Editable s) {
79            }
80        });
81    }
82
83    private boolean resolveIntent() {
84        Intent i = getIntent();
85        mData = i.getData();
86
87        if(mData == null) {
88            return false;
89        }
90        mExcludeClause = buildExcludeClause(i.getStringArrayExtra(EXTRA_EXCLUDED_CONTACTS));
91        Cursor cursor = managedQuery(mData, ContactView.CONTACT_PROJECTION,
92                mExcludeClause, Imps.Contacts.DEFAULT_SORT_ORDER);
93        if (cursor == null) {
94            return false;
95        }
96
97        mAdapter = new ContactsAdapter(this, cursor);
98        mFilter = mAdapter.getFilter();
99        setListAdapter(mAdapter);
100        return true;
101    }
102
103    @Override
104    protected void onListItemClick(ListView l, View v, int position, long id) {
105        Cursor cursor = (Cursor)mAdapter.getItem(position);
106        Intent data = new Intent();
107        data.putExtra(EXTRA_RESULT_USERNAME,
108                cursor.getString(ContactView.COLUMN_CONTACT_USERNAME));
109        setResult(RESULT_OK, data);
110        finish();
111    }
112
113    private static String buildExcludeClause(String[] excluded) {
114        if (excluded == null || excluded.length == 0) {
115            return null;
116        }
117
118        StringBuilder clause = new StringBuilder();
119        clause.append(Imps.Contacts.USERNAME);
120        clause.append(" NOT IN (");
121        int len = excluded.length;
122        for (int i = 0; i < len - 1; i++) {
123            DatabaseUtils.appendValueToSql(clause, excluded[i]);
124            clause.append(',');
125        }
126        DatabaseUtils.appendValueToSql(clause, excluded[len - 1]);
127        clause.append(')');
128        return clause.toString();
129    }
130
131    Cursor runQuery(CharSequence constraint) {
132        String where;
133        if (constraint == null) {
134            where = mExcludeClause;
135        } else {
136            StringBuilder buf = new StringBuilder();
137            if (mExcludeClause != null) {
138                buf.append(mExcludeClause).append(" AND ");
139            }
140
141            buf.append(Imps.Contacts.NICKNAME);
142            buf.append(" LIKE ");
143            DatabaseUtils.appendValueToSql(buf, "%" + constraint + "%");
144
145            where = buf.toString();
146        }
147        return managedQuery(mData, ContactView.CONTACT_PROJECTION, where,
148                Imps.Contacts.DEFAULT_SORT_ORDER);
149    }
150
151    private class ContactsAdapter extends ResourceCursorAdapter {
152        private String mConstraints;
153
154        public ContactsAdapter(Context context, Cursor c) {
155            super(context, R.layout.contact_view, c);
156        }
157
158        @Override
159        public void bindView(View view, Context context, Cursor cursor) {
160            ContactView v = (ContactView)view;
161            v.setPadding(0, 0, 0, 0);
162            v.bind(cursor, mConstraints, false);
163        }
164
165        @Override
166        public void changeCursor(Cursor cursor) {
167            if(mCursor != null && mCursor != cursor) {
168                mCursor.deactivate();
169            }
170            super.changeCursor(cursor);
171        }
172
173        @Override
174        public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
175            mConstraints = constraint.toString();
176
177            return ContactsPickerActivity.this.runQuery(constraint);
178        }
179    }
180
181}
182