1 /*
2  * Copyright (C) 2012 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 package com.android.dreams.phototable;
17 
18 import android.content.Context;
19 import android.content.SharedPreferences;
20 import android.database.DataSetObserver;
21 import android.util.Log;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.ListAdapter;
26 import android.widget.TextView;
27 
28 import java.util.Arrays;
29 import java.util.List;
30 
31 /**
32  * Settings panel for photo flipping dream.
33  */
34 public class SectionedAlbumDataAdapter extends DataSetObserver implements ListAdapter {
35     private static final String TAG = "SectionedAlbumDataAdapter";
36     private static final boolean DEBUG = false;
37 
38     private final LayoutInflater mInflater;
39     private final int mLayout;
40     private final AlbumDataAdapter mAlbumData;
41     private int[] sections;
42 
SectionedAlbumDataAdapter(Context context, SharedPreferences settings, int headerLayout, int itemLayout, List<PhotoSource.AlbumData> objects)43     public SectionedAlbumDataAdapter(Context context, SharedPreferences settings,
44             int headerLayout, int itemLayout, List<PhotoSource.AlbumData> objects) {
45         mLayout = headerLayout;
46         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
47         mAlbumData = new AlbumDataAdapter(context, settings, itemLayout, objects);
48         mAlbumData.sort(new AlbumDataAdapter.AccountComparator());
49         onChanged();
50         mAlbumData.registerDataSetObserver(this);
51     }
52 
areAllSelected()53     boolean areAllSelected() {
54         return mAlbumData != null && mAlbumData.areAllSelected();
55     }
56 
selectAll(boolean select)57     void selectAll(boolean select) {
58         if (mAlbumData != null) {
59             mAlbumData.selectAll(select);
60         }
61     }
62 
63     // DataSetObserver
64 
65     @Override
onChanged()66     public void onChanged() {
67         if (DEBUG) Log.i(TAG, "onChanged");
68         int numSections = 0;
69         String previous = "";
70         if (DEBUG) Log.i(TAG, "numAlbums = " + mAlbumData.getCount());
71         for (int i = 0; i < mAlbumData.getCount(); i++) {
72             PhotoSource.AlbumData item = mAlbumData.getItem(i);
73             if (previous.isEmpty() || !previous.equals(item.account)) {
74                 if (DEBUG) Log.i(TAG, "previous = " + previous +", title = " + item.account);
75                 previous = item.account;
76                 numSections++;
77             }
78         }
79 
80         if (DEBUG) Log.i(TAG, "numSections = " + numSections);
81         sections = new int[numSections];
82         numSections = 0;
83         previous = "";
84 
85         for (int i = 0; i < mAlbumData.getCount(); i++) {
86             PhotoSource.AlbumData item = mAlbumData.getItem(i);
87             if (previous.isEmpty() || !previous.equals(item.account)) {
88                 previous = item.account;
89                 sections[numSections] = i;
90                 numSections++;
91             }
92         }
93 
94         for (int i = 0; i < sections.length; i++) {
95             sections[i] += i;
96             if (DEBUG) Log.i(TAG, i + ": " + sections[i]);
97         }
98     }
99 
100     @Override
onInvalidated()101     public void onInvalidated() {
102         onChanged();
103     }
104 
105     // ListAdapter
106 
107     @Override
areAllItemsEnabled()108     public boolean areAllItemsEnabled() {
109         return mAlbumData.areAllItemsEnabled();
110     }
111 
112     @Override
isEnabled(int position)113     public boolean isEnabled(int position) {
114         if (isHeader(position)) {
115             return false;
116         } else {
117             return mAlbumData.isEnabled(internalPosition(position));
118         }
119     }
120 
121     // Adapter
122 
123     @Override
getCount()124     public int getCount() {
125         return mAlbumData.getCount() + sections.length;
126     }
127 
128     @Override
getItem(int position)129     public Object getItem(int position) {
130         if (isHeader(position)) {
131             return mAlbumData.getItem(internalPosition(position+1)).account;
132         } else {
133             return mAlbumData.getItem(internalPosition(position));
134         }
135     }
136 
137     @Override
getItemId(int position)138     public long getItemId(int position) {
139         return position;
140     }
141 
142     @Override
getItemViewType(int position)143     public int getItemViewType(int position) {
144         if (isHeader(position)) {
145             return mAlbumData.getViewTypeCount();
146         } else {
147             return mAlbumData.getItemViewType(internalPosition(position));
148         }
149     }
150 
151     @Override
getViewTypeCount()152     public int getViewTypeCount() {
153         return mAlbumData.getViewTypeCount() + 1;
154     }
155 
156     @Override
hasStableIds()157     public boolean hasStableIds() {
158         return mAlbumData.hasStableIds();
159     }
160 
161     @Override
isEmpty()162     public boolean isEmpty() {
163         return mAlbumData.isEmpty();
164     }
165 
166     @Override
registerDataSetObserver(DataSetObserver observer)167     public void registerDataSetObserver(DataSetObserver observer) {
168         mAlbumData.registerDataSetObserver(observer);
169     }
170 
171     @Override
unregisterDataSetObserver(DataSetObserver observer)172     public void unregisterDataSetObserver(DataSetObserver observer) {
173         mAlbumData.unregisterDataSetObserver(observer);
174     }
175 
176     @Override
getView(int position, View convertView, ViewGroup parent)177     public View getView (int position, View convertView, ViewGroup parent) {
178         if (isHeader(position)) {
179             if (DEBUG) Log.i(TAG, "header at " + position);
180             View item = convertView;
181             if (item == null) {
182                 item = mInflater.inflate(mLayout, parent, false);
183             }
184             View vTextView = item.findViewById(R.id.title);
185             if (vTextView != null && vTextView instanceof TextView) {
186                 TextView textView = (TextView) vTextView;
187                 textView.setText((String) getItem(position));
188             }
189             return item;
190         } else {
191             if (DEBUG) Log.i(TAG, "non-header at " + position +
192                              " fetching " + internalPosition(position));
193             View item = mAlbumData.getView(internalPosition(position), convertView, parent);
194             return item;
195         }
196     }
197 
198     // internal
199 
isHeader(int position)200     private boolean isHeader(int position) {
201         return (Arrays.binarySearch(sections, position) >= 0);
202     }
203 
internalPosition(int position)204     private int internalPosition(int position) {
205         int offset = Arrays.binarySearch(sections, position);
206         if (offset < 0) {
207             offset = -(offset + 1);
208         }
209         return position - offset;
210     }
211 }
212