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