1587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo/* 2587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * Copyright (C) 2011 Google Inc. 3587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * Licensed to The Android Open Source Project. 4587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * 5587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * Licensed under the Apache License, Version 2.0 (the "License"); 6587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * you may not use this file except in compliance with the License. 7587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * You may obtain a copy of the License at 8587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * 9587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * http://www.apache.org/licenses/LICENSE-2.0 10587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * 11587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * Unless required by applicable law or agreed to in writing, software 12587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * distributed under the License is distributed on an "AS IS" BASIS, 13587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * See the License for the specific language governing permissions and 15587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * limitations under the License. 16587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo */ 17587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 18587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 19587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalopackage com.android.mailcommon; 20587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 21587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport android.database.DataSetObserver; 22587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport android.view.View; 23587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport android.view.ViewGroup; 24587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport android.widget.BaseAdapter; 25587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport android.widget.ListAdapter; 26587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport android.widget.SpinnerAdapter; 27587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 28587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport java.util.Arrays; 29587722a561a8ad36a27134379cd1be82c13a13e8Ben Komaloimport java.util.List; 30587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 31587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo/** 32587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * An adapter that combines items from multiple provided adapters into a single list. 33587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * 34587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * @param <T> the class of each constituent adapter 35587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo */ 36587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalopublic class MergedAdapter<T extends MergedAdapter.ListSpinnerAdapter> extends BaseAdapter { 37587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 38587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo private List<T> mAdapters; 39587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo private final DataSetObserver mObserver; 40587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 41587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo /** 42587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * A Mergeable adapter must implement both ListAdapter and SpinnerAdapter to be useful in lists 43587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * and spinners. 44587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo */ 45587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public interface ListSpinnerAdapter extends ListAdapter, SpinnerAdapter { 46587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 47587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 48587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public static class LocalAdapterPosition<T extends ListSpinnerAdapter> { 49587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public final T mAdapter; 50587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public final int mLocalPosition; 51587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 52587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public LocalAdapterPosition(T adapter, int offset) { 53587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo mAdapter = adapter; 54587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo mLocalPosition = offset; 55587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 56587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 57587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 58587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public MergedAdapter() { 59587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo mObserver = new DataSetObserver() { 60587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 61587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public void onChanged() { 62587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo notifyDataSetChanged(); 63587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 64587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo }; 65587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 66587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 67587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public void setAdapters(T... adapters) { 68587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo if (mAdapters != null) { 69587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo for (T adapter : mAdapters) { 70587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo adapter.unregisterDataSetObserver(mObserver); 71587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 72587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 73587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 74587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo mAdapters = Arrays.asList(adapters); 75587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 76587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo for (T adapter : mAdapters) { 77587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo adapter.registerDataSetObserver(mObserver); 78587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 79587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 80587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 81587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public int getSubAdapterCount() { 82587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return mAdapters.size(); 83587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 84587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 85587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public T getSubAdapter(int index) { 86587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return mAdapters.get(index); 87587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 88587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 89587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 90587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public int getCount() { 91587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int count = 0; 92587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo for (T adapter : mAdapters) { 93587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo count += adapter.getCount(); 94587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 95587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return count; 96587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo // TODO: cache counts until next onChanged 97587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 98587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 99587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo /** 100587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * For a given merged position, find the corresponding Adapter and local position within that 101587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * Adapter by iterating through Adapters and summing their counts until the merged position is 102587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * found. 103587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * 104587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * @param position a merged (global) position 105587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo * @return the matching Adapter and local position, or null if not found 106587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo */ 107587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public LocalAdapterPosition<T> getAdapterOffsetForItem(final int position) { 108587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo final int adapterCount = mAdapters.size(); 109587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int i = 0; 110587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int count = 0; 111587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 112587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo while (i < adapterCount) { 113587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo T a = mAdapters.get(i); 114587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int newCount = count + a.getCount(); 115587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo if (position < newCount) { 116587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return new LocalAdapterPosition<T>(a, position - count); 117587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 118587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo count = newCount; 119587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo i++; 120587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 121587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return null; 122587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 123587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 124587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 125587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public Object getItem(int position) { 126587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo LocalAdapterPosition<T> result = getAdapterOffsetForItem(position); 127587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo if (result == null) { 128587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return null; 129587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 130587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return result.mAdapter.getItem(result.mLocalPosition); 131587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 132587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 133587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 134587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public long getItemId(int position) { 135587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return position; 136587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 137587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 138587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 139587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public int getViewTypeCount() { 140587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int count = 0; 141587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo for (T adapter : mAdapters) { 142587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo count += adapter.getViewTypeCount(); 143587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 144587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return count; 145587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 146587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 147587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 148587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public int getItemViewType(int position) { 149587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo LocalAdapterPosition<T> result = getAdapterOffsetForItem(position); 150587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int otherViewTypeCount = 0; 151587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo for (T adapter : mAdapters) { 152587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo if (adapter == result.mAdapter) { 153587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo break; 154587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 155587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo otherViewTypeCount += adapter.getViewTypeCount(); 156587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 157587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo int type = result.mAdapter.getItemViewType(result.mLocalPosition); 158587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo // Headers (negative types) are in a separate global namespace and their values should not 159587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo // be affected by preceding adapter view types. 160587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo if (type >= 0) { 161587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo type += otherViewTypeCount; 162587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 163587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return type; 164587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 165587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 166587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 167587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public View getView(int position, View convertView, ViewGroup parent) { 168587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo LocalAdapterPosition<T> result = getAdapterOffsetForItem(position); 169587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return result.mAdapter.getView(result.mLocalPosition, convertView, parent); 170587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 171587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 172587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 173587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public View getDropDownView(int position, View convertView, ViewGroup parent) { 174587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo LocalAdapterPosition<T> result = getAdapterOffsetForItem(position); 175587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return result.mAdapter.getDropDownView(result.mLocalPosition, convertView, parent); 176587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 177587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 178587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 179587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public boolean areAllItemsEnabled() { 180587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo boolean enabled = true; 181587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo for (T adapter : mAdapters) { 182587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo enabled &= adapter.areAllItemsEnabled(); 183587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 184587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return enabled; 185587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 186587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 187587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo @Override 188587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo public boolean isEnabled(int position) { 189587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo LocalAdapterPosition<T> result = getAdapterOffsetForItem(position); 190587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo return result.mAdapter.isEnabled(result.mLocalPosition); 191587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo } 192587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo 193587722a561a8ad36a27134379cd1be82c13a13e8Ben Komalo}