Home | History | Annotate | Download | only in contacts
      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