blob: 777660b7126e4750c3776b5716eb42a1fd1c31b7 [file] [log] [blame]
Alexandre Lisiona8b78722013-12-13 10:18:33 -05001/*
Alexandre Lisionc1024c02014-01-06 11:12:53 -05002 * Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
Alexandre Lisiona8b78722013-12-13 10:18:33 -05003 *
4 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * Additional permission under GNU GPL version 3 section 7:
21 *
22 * If you modify this program, or any covered work, by linking or
23 * combining it with the OpenSSL project's OpenSSL library (or a
24 * modified version of that library), containing parts covered by the
25 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
26 * grants you additional permission to convey the resulting work.
27 * Corresponding Source for a non-source form of such a combination
28 * shall include the source code for the parts of OpenSSL used as well
29 * as that of the covered work.
30 */
31
Alexandre Lision064e1e02013-10-01 16:18:42 -040032package org.sflphone.adapters;
alisiond295ec22013-05-17 10:12:13 -040033
Alexandre Lisione1c96db2013-10-04 14:34:21 -040034import java.lang.ref.WeakReference;
alisiond295ec22013-05-17 10:12:13 -040035import java.util.ArrayList;
36import java.util.concurrent.ExecutorService;
37import java.util.concurrent.Executors;
38
Alexandre Lisione1c96db2013-10-04 14:34:21 -040039import org.sflphone.R;
40import org.sflphone.fragments.ContactListFragment;
Alexandre Lision064e1e02013-10-01 16:18:42 -040041import org.sflphone.model.CallContact;
Alexandre Lision691a1d62013-11-12 10:06:27 -050042import org.sflphone.views.stickylistheaders.StickyListHeadersAdapter;
Alexandre Lision064e1e02013-10-01 16:18:42 -040043
alisiond295ec22013-05-17 10:12:13 -040044import android.content.Context;
alisiond295ec22013-05-17 10:12:13 -040045import android.view.LayoutInflater;
46import android.view.View;
Alexandre Lisione1c96db2013-10-04 14:34:21 -040047import android.view.View.OnClickListener;
alisiond295ec22013-05-17 10:12:13 -040048import android.view.ViewGroup;
49import android.widget.BaseAdapter;
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -040050import android.widget.ImageButton;
alisiond295ec22013-05-17 10:12:13 -040051import android.widget.ImageView;
alisionf7053602013-07-09 10:25:20 -040052import android.widget.SectionIndexer;
alisiond295ec22013-05-17 10:12:13 -040053import android.widget.TextView;
Alexandre Lisionc59685a2013-10-04 16:36:36 -040054import android.widget.Toast;
alisiond295ec22013-05-17 10:12:13 -040055
Alexandre Lision691a1d62013-11-12 10:06:27 -050056public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAdapter, SectionIndexer {
alisiond295ec22013-05-17 10:12:13 -040057
58 private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
alisiond295ec22013-05-17 10:12:13 -040059 Context mContext;
60
Alexandre Lision691a1d62013-11-12 10:06:27 -050061 private ArrayList<CallContact> mContacts;
62 private int[] mSectionIndices;
63 private Character[] mSectionLetters;
Alexandre Lisione1c96db2013-10-04 14:34:21 -040064 WeakReference<ContactListFragment> parent;
Alexandre Lision691a1d62013-11-12 10:06:27 -050065 private LayoutInflater mInflater;
alisionf7053602013-07-09 10:25:20 -040066
Alexandre Lisione1c96db2013-10-04 14:34:21 -040067 // private static final String TAG = ContactsAdapter.class.getSimpleName();
alisiond295ec22013-05-17 10:12:13 -040068
Alexandre Lisione1c96db2013-10-04 14:34:21 -040069 public ContactsAdapter(ContactListFragment contactListFragment) {
alisiond295ec22013-05-17 10:12:13 -040070 super();
Alexandre Lisione1c96db2013-10-04 14:34:21 -040071 mContext = contactListFragment.getActivity();
Alexandre Lision691a1d62013-11-12 10:06:27 -050072 mInflater = LayoutInflater.from(mContext);
Alexandre Lisione1c96db2013-10-04 14:34:21 -040073 parent = new WeakReference<ContactListFragment>(contactListFragment);
Alexandre Lision691a1d62013-11-12 10:06:27 -050074 mContacts = new ArrayList<CallContact>();
75 mSectionIndices = getSectionIndices();
76 mSectionLetters = getSectionLetters();
alisiond295ec22013-05-17 10:12:13 -040077 }
78
Alexandre Lision691a1d62013-11-12 10:06:27 -050079 public static final int TYPE_HEADER = 0;
80 public static final int TYPE_CONTACT = 1;
81
82 private int[] getSectionIndices() {
83 ArrayList<Integer> sectionIndices = new ArrayList<Integer>();
84 if (mContacts.isEmpty())
85 return new int[0];
86 char lastFirstChar = mContacts.get(0).getmDisplayName().charAt(0);
87 sectionIndices.add(0);
88 for (int i = 1; i < mContacts.size(); i++) {
89 if (mContacts.get(i).getmDisplayName().charAt(0) != lastFirstChar) {
90 lastFirstChar = mContacts.get(i).getmDisplayName().charAt(0);
91 sectionIndices.add(i);
92 }
93 }
94 int[] sections = new int[sectionIndices.size()];
95 for (int i = 0; i < sectionIndices.size(); i++) {
96 sections[i] = sectionIndices.get(i);
97 }
98 return sections;
99 }
100
101 private Character[] getSectionLetters() {
102 Character[] letters = new Character[mSectionIndices.length];
103 for (int i = 0; i < mSectionIndices.length; i++) {
104 letters[i] = mContacts.get(mSectionIndices[i]).getmDisplayName().charAt(0);
105 }
106 return letters;
107 }
alisionf7053602013-07-09 10:25:20 -0400108
109 @Override
Alexandre Lision691a1d62013-11-12 10:06:27 -0500110 public View getView(int position, View convertView, ViewGroup root) {
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400111 ContactView entryView;
Alexandre Lision691a1d62013-11-12 10:06:27 -0500112
alisionf7053602013-07-09 10:25:20 -0400113 if (convertView == null) {
Alexandre Lision691a1d62013-11-12 10:06:27 -0500114 convertView = mInflater.inflate(R.layout.item_contact, null);
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400115
116 entryView = new ContactView();
117 entryView.quick_starred = (ImageButton) convertView.findViewById(R.id.quick_starred);
118 entryView.quick_edit = (ImageButton) convertView.findViewById(R.id.quick_edit);
119 entryView.quick_discard = (ImageButton) convertView.findViewById(R.id.quick_discard);
120 entryView.quick_call = (ImageButton) convertView.findViewById(R.id.quick_call);
121 entryView.quick_msg = (ImageButton) convertView.findViewById(R.id.quick_message);
122 entryView.photo = (ImageView) convertView.findViewById(R.id.photo);
123 entryView.display_name = (TextView) convertView.findViewById(R.id.display_name);
124 convertView.setTag(entryView);
125 } else {
126 entryView = (ContactView) convertView.getTag();
alisionf7053602013-07-09 10:25:20 -0400127 }
128
Alexandre Lision691a1d62013-11-12 10:06:27 -0500129 final CallContact item = mContacts.get(position);
alisionf7053602013-07-09 10:25:20 -0400130
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400131 entryView.display_name.setText(item.getmDisplayName());
alisionf7053602013-07-09 10:25:20 -0400132
Alexandre Lision691a1d62013-11-12 10:06:27 -0500133 if (item.hasPhoto()) {
Alexandre Lision35c3cbb2013-11-04 17:11:54 -0500134 entryView.photo.setImageBitmap(item.getPhoto());
135 } else {
136 infos_fetcher.execute(new ContactPictureTask(mContext, entryView.photo, item));
137 }
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400138
139 entryView.quick_call.setOnClickListener(new OnClickListener() {
Alexandre Lisione1c96db2013-10-04 14:34:21 -0400140
141 @Override
142 public void onClick(View v) {
143 parent.get().mCallbacks.onCallContact(item);
144
145 }
146 });
Alexandre Lision691a1d62013-11-12 10:06:27 -0500147
Alexandre Lisione168d4a2013-10-24 12:32:59 -0400148 entryView.quick_msg.setOnClickListener(new OnClickListener() {
149
150 @Override
151 public void onClick(View v) {
152 parent.get().mCallbacks.onTextContact(item);
153 }
154 });
Alexandre Lision691a1d62013-11-12 10:06:27 -0500155
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400156 entryView.quick_starred.setOnClickListener(new OnClickListener() {
Alexandre Lisionc59685a2013-10-04 16:36:36 -0400157
158 @Override
159 public void onClick(View v) {
160 Toast.makeText(mContext, "Coming soon", Toast.LENGTH_SHORT).show();
161 }
162 });
Alexandre Lision691a1d62013-11-12 10:06:27 -0500163
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400164 entryView.quick_edit.setOnClickListener(new OnClickListener() {
Alexandre Lisionc59685a2013-10-04 16:36:36 -0400165
166 @Override
167 public void onClick(View v) {
168 parent.get().mCallbacks.onEditContact(item);
169
170 }
171 });
Alexandre Lision691a1d62013-11-12 10:06:27 -0500172
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400173 entryView.quick_discard.setOnClickListener(new OnClickListener() {
Alexandre Lisionc59685a2013-10-04 16:36:36 -0400174
175 @Override
176 public void onClick(View v) {
177 Toast.makeText(mContext, "Coming soon", Toast.LENGTH_SHORT).show();
178
179 }
180 });
Alexandre Lision691a1d62013-11-12 10:06:27 -0500181
Alexandre Lisione168d4a2013-10-24 12:32:59 -0400182 entryView.quick_edit.setClickable(false);
183 entryView.quick_discard.setClickable(false);
184 entryView.quick_starred.setClickable(false);
Alexandre Lisione1c96db2013-10-04 14:34:21 -0400185
alisionf7053602013-07-09 10:25:20 -0400186 return convertView;
alisiond295ec22013-05-17 10:12:13 -0400187 }
Alexandre Lision691a1d62013-11-12 10:06:27 -0500188
Alexandre Lisiond5dbcdf2013-10-07 14:13:09 -0400189 /*********************
190 * ViewHolder Pattern
191 *********************/
192 public class ContactView {
193 ImageButton quick_starred, quick_edit, quick_discard, quick_call, quick_msg;
194 ImageView photo;
195 TextView display_name;
196 }
alisiond295ec22013-05-17 10:12:13 -0400197
198 @Override
199 public int getCount() {
Alexandre Lision691a1d62013-11-12 10:06:27 -0500200 return mContacts.size();
alisionf7053602013-07-09 10:25:20 -0400201 }
202
203 @Override
204 public int getViewTypeCount() {
205 return 2;
206 }
207
alisionf7053602013-07-09 10:25:20 -0400208 @Override
209 public long getItemId(int position) {
210 return 0;
211 }
212
Alexandre Lision691a1d62013-11-12 10:06:27 -0500213 @Override
214 public View getHeaderView(int position, View convertView, ViewGroup parent) {
215 HeaderViewHolder holder;
216
217 if (convertView == null) {
218 holder = new HeaderViewHolder();
219 convertView = mInflater.inflate(R.layout.header, parent, false);
220 holder.text = (TextView) convertView.findViewById(R.id.header_letter);
221 convertView.setTag(holder);
222 } else {
223 holder = (HeaderViewHolder) convertView.getTag();
224 }
225
226 // set header text as first char in name
227 char headerChar = mContacts.get(position).getmDisplayName().subSequence(0, 1).charAt(0);
228
229 holder.text.setText("" + headerChar);
230
231 return convertView;
232
alisionf7053602013-07-09 10:25:20 -0400233 }
234
Alexandre Lision691a1d62013-11-12 10:06:27 -0500235 class HeaderViewHolder {
236 TextView text;
alisionf7053602013-07-09 10:25:20 -0400237 }
238
Alexandre Lision691a1d62013-11-12 10:06:27 -0500239 @Override
240 public long getHeaderId(int position) {
241 // return the first character of the name as ID because this is what
242 // headers are based upon
243 return mContacts.get(position).getmDisplayName().subSequence(0, 1).charAt(0);
alisionf7053602013-07-09 10:25:20 -0400244 }
245
alisionf7053602013-07-09 10:25:20 -0400246 @Override
247 public int getPositionForSection(int section) {
Alexandre Lision691a1d62013-11-12 10:06:27 -0500248 if (section >= mSectionIndices.length) {
249 section = mSectionIndices.length - 1;
250 } else if (section < 0) {
251 section = 0;
252 }
253 return mSectionIndices[section];
alisionf7053602013-07-09 10:25:20 -0400254 }
255
256 @Override
257 public int getSectionForPosition(int position) {
Alexandre Lision691a1d62013-11-12 10:06:27 -0500258 for (int i = 0; i < mSectionIndices.length; i++) {
259 if (position < mSectionIndices[i]) {
260 return i - 1;
261 }
262 }
263 return mSectionIndices.length - 1;
alisionf7053602013-07-09 10:25:20 -0400264 }
265
266 @Override
267 public Object[] getSections() {
Alexandre Lision691a1d62013-11-12 10:06:27 -0500268 return mSectionLetters;
alisiond295ec22013-05-17 10:12:13 -0400269 }
270
271 @Override
Alexandre Lision691a1d62013-11-12 10:06:27 -0500272 public CallContact getItem(int position) {
273 return mContacts.get(position);
alisiond295ec22013-05-17 10:12:13 -0400274 }
Alexandre Lisione1c96db2013-10-04 14:34:21 -0400275
Alexandre Lision691a1d62013-11-12 10:06:27 -0500276 public void clear() {
277 mContacts = new ArrayList<CallContact>();
278 mSectionIndices = new int[0];
279 mSectionLetters = new Character[0];
280 notifyDataSetChanged();
281 }
alisiond295ec22013-05-17 10:12:13 -0400282
Alexandre Lision691a1d62013-11-12 10:06:27 -0500283 public void restore() {
284 mContacts = new ArrayList<CallContact>();
285 mSectionIndices = getSectionIndices();
286 mSectionLetters = getSectionLetters();
287 notifyDataSetChanged();
288 }
alisiond295ec22013-05-17 10:12:13 -0400289
Alexandre Lision691a1d62013-11-12 10:06:27 -0500290 public void addAll(ArrayList<CallContact> tmp) {
291 mContacts.addAll(tmp);
292 mSectionIndices = getSectionIndices();
293 mSectionLetters = getSectionLetters();
294 notifyDataSetChanged();
alisiond295ec22013-05-17 10:12:13 -0400295 }
296
297}