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