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.loaderapp.fragments;
18 
19 import android.content.Context;
20 import android.net.Uri;
21 import android.os.Parcel;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.BaseAdapter;
26 
27 import java.util.ArrayList;
28 
29 public 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          */
writeToParcel(Parcel p)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          */
readFromParcel(Parcel p)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 
ContactEntryAdapter(Context context, ArrayList<ArrayList<E>> sections, boolean separators)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      */
setSections(ArrayList<ArrayList<E>> sections, boolean separators)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      */
setSections(ArrayList<ArrayList<E>> sections, E entry)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      */
getCount()127     public final int getCount() {
128         return countEntries(mSections, mSeparators);
129     }
130 
131     /**
132      * @see android.widget.ListAdapter#hasSeparators()
133      */
134     @Override
areAllItemsEnabled()135     public final boolean areAllItemsEnabled() {
136         return mSeparators == false;
137     }
138 
139     /**
140      * @see android.widget.ListAdapter#isSeparator(int)
141      */
142     @Override
isEnabled(int position)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      */
getItem(int position)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      */
getEntry(ArrayList<ArrayList<T>> sections, int position, boolean separators)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      */
countEntries(ArrayList<ArrayList<T>> sections, boolean separators)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      */
getItemId(int position)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      */
getView(int position, View convertView, ViewGroup parent)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      */
newView(int position, ViewGroup parent)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      */
bindView(View view, E entry)259     protected abstract void bindView(View view, E entry);
260 }
261