1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.contacts; 18 19 import android.content.Context; 20 import android.net.Uri; 21 import android.os.Parcel; 22 import android.provider.ContactsContract.Contacts; 23 import android.provider.ContactsContract.Data; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 import android.view.ViewGroup; 27 import android.widget.BaseAdapter; 28 29 import java.util.ArrayList; 30 31 public abstract class ContactEntryAdapter<E extends ContactEntryAdapter.Entry> 32 extends BaseAdapter { 33 34 protected ArrayList<ArrayList<E>> mSections; 35 protected LayoutInflater mInflater; 36 protected Context mContext; 37 protected boolean mSeparators; 38 39 /** 40 * Base class for adapter entries. 41 */ 42 public static class Entry { 43 public int type = -1; 44 public String label; 45 public String data; 46 public Uri uri; 47 public long id = 0; 48 public long contactId; 49 public int maxLines = 1; 50 public String mimetype; 51 52 /** 53 * Helper for making subclasses parcelable. 54 */ 55 protected void writeToParcel(Parcel p) { 56 p.writeInt(type); 57 p.writeString(label); 58 p.writeString(data); 59 p.writeParcelable(uri, 0); 60 p.writeLong(id); 61 p.writeInt(maxLines); 62 p.writeString(mimetype); 63 } 64 65 /** 66 * Helper for making subclasses parcelable. 67 */ 68 protected void readFromParcel(Parcel p) { 69 final ClassLoader loader = getClass().getClassLoader(); 70 type = p.readInt(); 71 label = p.readString(); 72 data = p.readString(); 73 uri = p.readParcelable(loader); 74 id = p.readLong(); 75 maxLines = p.readInt(); 76 mimetype = p.readString(); 77 } 78 } 79 80 ContactEntryAdapter(Context context, ArrayList<ArrayList<E>> sections, boolean separators) { 81 mContext = context; 82 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 83 mSections = sections; 84 mSeparators = separators; 85 } 86 87 /** 88 * Resets the section data. 89 * 90 * @param sections the section data 91 */ 92 public final void setSections(ArrayList<ArrayList<E>> sections, boolean separators) { 93 mSections = sections; 94 mSeparators = separators; 95 notifyDataSetChanged(); 96 } 97 98 /** 99 * Resets the section data and returns the position of the given entry. 100 * 101 * @param sections the section data 102 * @param entry the entry to return the position for 103 * @return the position of entry, or -1 if it isn't found 104 */ 105 public final int setSections(ArrayList<ArrayList<E>> sections, E entry) { 106 mSections = sections; 107 notifyDataSetChanged(); 108 109 int numSections = mSections.size(); 110 int position = 0; 111 for (int i = 0; i < numSections; i++) { 112 ArrayList<E> section = mSections.get(i); 113 int sectionSize = section.size(); 114 for (int j = 0; j < sectionSize; j++) { 115 E e = section.get(j); 116 if (e.equals(entry)) { 117 position += j; 118 return position; 119 } 120 } 121 position += sectionSize; 122 } 123 return -1; 124 } 125 126 /** 127 * @see android.widget.ListAdapter#getCount() 128 */ 129 public final int getCount() { 130 return countEntries(mSections, mSeparators); 131 } 132 133 /** 134 * @see android.widget.ListAdapter#hasSeparators() 135 */ 136 @Override 137 public final boolean areAllItemsEnabled() { 138 return mSeparators == false; 139 } 140 141 /** 142 * @see android.widget.ListAdapter#isSeparator(int) 143 */ 144 @Override 145 public final boolean isEnabled(int position) { 146 if (!mSeparators) { 147 return true; 148 } 149 150 int numSections = mSections.size(); 151 for (int i = 0; i < numSections; i++) { 152 ArrayList<E> section = mSections.get(i); 153 int sectionSize = section.size(); 154 if (sectionSize == 1) { 155 // The section only contains a separator and nothing else, skip it 156 continue; 157 } 158 if (position == 0) { 159 // The first item in a section is always the separator 160 return false; 161 } 162 position -= sectionSize; 163 } 164 return true; 165 } 166 167 /** 168 * @see android.widget.ListAdapter#getItem(int) 169 */ 170 public final Object getItem(int position) { 171 return getEntry(mSections, position, mSeparators); 172 } 173 174 /** 175 * Get the entry for the given position. 176 * 177 * @param sections the list of sections 178 * @param position the position for the desired entry 179 * @return the ContactEntry for the given position 180 */ 181 public final static <T extends Entry> T getEntry(ArrayList<ArrayList<T>> sections, 182 int position, boolean separators) { 183 int numSections = sections.size(); 184 for (int i = 0; i < numSections; i++) { 185 ArrayList<T> section = sections.get(i); 186 int sectionSize = section.size(); 187 if (separators && sectionSize == 1) { 188 // The section only contains a separator and nothing else, skip it 189 continue; 190 } 191 if (position < section.size()) { 192 return section.get(position); 193 } 194 position -= section.size(); 195 } 196 return null; 197 } 198 199 /** 200 * Get the count of entries in all sections 201 * 202 * @param sections the list of sections 203 * @return the count of entries in all sections 204 */ 205 public static <T extends Entry> int countEntries(ArrayList<ArrayList<T>> sections, 206 boolean separators) { 207 int count = 0; 208 int numSections = sections.size(); 209 for (int i = 0; i < numSections; i++) { 210 ArrayList<T> section = sections.get(i); 211 int sectionSize = section.size(); 212 if (separators && sectionSize == 1) { 213 // The section only contains a separator and nothing else, skip it 214 continue; 215 } 216 count += sections.get(i).size(); 217 } 218 return count; 219 } 220 221 /** 222 * @see android.widget.ListAdapter#getItemId(int) 223 */ 224 public final long getItemId(int position) { 225 Entry entry = getEntry(mSections, position, mSeparators); 226 if (entry != null) { 227 return entry.id; 228 } else { 229 return -1; 230 } 231 } 232 233 /** 234 * @see android.widget.ListAdapter#getView(int, View, ViewGroup) 235 */ 236 public View getView(int position, View convertView, ViewGroup parent) { 237 View v; 238 if (convertView == null) { 239 v = newView(position, parent); 240 } else { 241 v = convertView; 242 } 243 bindView(v, getEntry(mSections, position, mSeparators)); 244 return v; 245 } 246 247 /** 248 * Create a new view for an entry. 249 * 250 * @parent the parent ViewGroup 251 * @return the newly created view 252 */ 253 protected abstract View newView(int position, ViewGroup parent); 254 255 /** 256 * Binds the data from an entry to a view. 257 * 258 * @param view the view to display the entry in 259 * @param entry the data to bind 260 */ 261 protected abstract void bindView(View view, E entry); 262 } 263