1/*
2 * Copyright (C) 2013 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.documentsui;
18
19import android.view.View;
20import android.view.ViewGroup;
21import android.widget.AdapterView;
22import android.widget.BaseAdapter;
23import android.widget.ListAdapter;
24
25import com.google.android.collect.Lists;
26
27import java.util.ArrayList;
28
29/**
30 * Adapter that combines multiple adapters as sections, asking each section to
31 * provide a header, and correctly handling item types across child adapters.
32 */
33public class SectionedListAdapter extends BaseAdapter {
34    private ArrayList<SectionAdapter> mSections = Lists.newArrayList();
35
36    public interface SectionAdapter extends ListAdapter {
37        public View getHeaderView(View convertView, ViewGroup parent);
38    }
39
40    public void clearSections() {
41        mSections.clear();
42        notifyDataSetChanged();
43    }
44
45    /**
46     * After mutating sections, you <em>must</em>
47     * {@link AdapterView#setAdapter(android.widget.Adapter)} to correctly
48     * recount view types.
49     */
50    public void addSection(SectionAdapter adapter) {
51        mSections.add(adapter);
52        notifyDataSetChanged();
53    }
54
55    @Override
56    public int getCount() {
57        int count = 0;
58        final int size = mSections.size();
59        for (int i = 0; i < size; i++) {
60            count += mSections.get(i).getCount() + 1;
61        }
62        return count;
63    }
64
65    @Override
66    public Object getItem(int position) {
67        final int size = mSections.size();
68        for (int i = 0; i < size; i++) {
69            final SectionAdapter section = mSections.get(i);
70            final int sectionSize = section.getCount() + 1;
71
72            // Check if position inside this section
73            if (position == 0) {
74                return section;
75            } else if (position < sectionSize) {
76                return section.getItem(position - 1);
77            }
78
79            // Otherwise jump into next section
80            position -= sectionSize;
81        }
82        throw new IllegalStateException("Unknown position " + position);
83    }
84
85    @Override
86    public long getItemId(int position) {
87        return position;
88    }
89
90    @Override
91    public View getView(int position, View convertView, ViewGroup parent) {
92        final int size = mSections.size();
93        for (int i = 0; i < size; i++) {
94            final SectionAdapter section = mSections.get(i);
95            final int sectionSize = section.getCount() + 1;
96
97            // Check if position inside this section
98            if (position == 0) {
99                return section.getHeaderView(convertView, parent);
100            } else if (position < sectionSize) {
101                return section.getView(position - 1, convertView, parent);
102            }
103
104            // Otherwise jump into next section
105            position -= sectionSize;
106        }
107        throw new IllegalStateException("Unknown position " + position);
108    }
109
110    @Override
111    public boolean areAllItemsEnabled() {
112        return false;
113    }
114
115    @Override
116    public boolean isEnabled(int position) {
117        final int size = mSections.size();
118        for (int i = 0; i < size; i++) {
119            final SectionAdapter section = mSections.get(i);
120            final int sectionSize = section.getCount() + 1;
121
122            // Check if position inside this section
123            if (position == 0) {
124                return false;
125            } else if (position < sectionSize) {
126                return section.isEnabled(position - 1);
127            }
128
129            // Otherwise jump into next section
130            position -= sectionSize;
131        }
132        throw new IllegalStateException("Unknown position " + position);
133    }
134
135    @Override
136    public int getItemViewType(int position) {
137        int type = 1;
138        final int size = mSections.size();
139        for (int i = 0; i < size; i++) {
140            final SectionAdapter section = mSections.get(i);
141            final int sectionSize = section.getCount() + 1;
142
143            // Check if position inside this section
144            if (position == 0) {
145                return 0;
146            } else if (position < sectionSize) {
147                return type + section.getItemViewType(position - 1);
148            }
149
150            // Otherwise jump into next section
151            position -= sectionSize;
152            type += section.getViewTypeCount();
153        }
154        throw new IllegalStateException("Unknown position " + position);
155    }
156
157    @Override
158    public int getViewTypeCount() {
159        int count = 1;
160        final int size = mSections.size();
161        for (int i = 0; i < size; i++) {
162            count += mSections.get(i).getViewTypeCount();
163        }
164        return count;
165    }
166}
167