160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov/*
260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov *
460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * you may not use this file except in compliance with the License.
660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * You may obtain a copy of the License at
760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov *
860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov *
1060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
1160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
1260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * See the License for the specific language governing permissions and
1460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * limitations under the License.
1560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov */
1660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovpackage com.android.common.widget;
1760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
1860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovimport android.content.Context;
1960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovimport android.database.Cursor;
2060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovimport android.view.View;
2160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovimport android.view.ViewGroup;
2260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovimport android.widget.BaseAdapter;
2360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
249a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albertimport java.util.ArrayList;
259a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert
2660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov/**
2760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * A general purpose adapter that is composed of multiple cursors. It just
2860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov * appends them in the order they are added.
2960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov */
3060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikovpublic abstract class CompositeCursorAdapter extends BaseAdapter {
3160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
3260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private static final int INITIAL_CAPACITY = 2;
3360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
3460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public static class Partition {
3560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        boolean showIfEmpty;
3660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        boolean hasHeader;
3760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
3860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        Cursor cursor;
3960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int idColumnIndex;
4060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int count;
4160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
4260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        public Partition(boolean showIfEmpty, boolean hasHeader) {
4360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            this.showIfEmpty = showIfEmpty;
4460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            this.hasHeader = hasHeader;
4560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
4660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
4760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        /**
4860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov         * True if the directory should be shown even if no contacts are found.
4960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov         */
5060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        public boolean getShowIfEmpty() {
5160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            return showIfEmpty;
5260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
5360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
5460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        public boolean getHasHeader() {
5560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            return hasHeader;
5660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
5760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
5860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
5960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private final Context mContext;
609a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    private ArrayList<Partition> mPartitions;
6160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private int mCount = 0;
6260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private boolean mCacheValid = true;
6355f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    private boolean mNotificationsEnabled = true;
6455f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    private boolean mNotificationNeeded;
6560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
6660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public CompositeCursorAdapter(Context context) {
6760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        this(context, INITIAL_CAPACITY);
6860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
6960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
7060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public CompositeCursorAdapter(Context context, int initialCapacity) {
7160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mContext = context;
729a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions = new ArrayList<Partition>();
7360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
7460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
7560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Context getContext() {
7660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return mContext;
7760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
7860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
7960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
8060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Registers a partition. The cursor for that partition can be set later.
8160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Partitions should be added in the order they are supposed to appear in the
8260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * list.
8360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
8460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void addPartition(boolean showIfEmpty, boolean hasHeader) {
8560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        addPartition(new Partition(showIfEmpty, hasHeader));
8660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
8760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
8860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void addPartition(Partition partition) {
899a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.add(partition);
909a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        invalidate();
919a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        notifyDataSetChanged();
929a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    }
939a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert
949a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    public void addPartition(int location, Partition partition) {
959a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.add(location, partition);
9660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
9760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        notifyDataSetChanged();
9860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
9960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
10060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void removePartition(int partitionIndex) {
1019a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        Cursor cursor = mPartitions.get(partitionIndex).cursor;
10260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (cursor != null && !cursor.isClosed()) {
10360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            cursor.close();
10460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
1059a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.remove(partitionIndex);
10660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
10760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        notifyDataSetChanged();
10860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
10960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
11060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
11160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Removes cursors for all partitions.
11260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
1139a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    // TODO: Is this really what this is supposed to do? Just remove the cursors? Not close them?
1149a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    // Not remove the partitions themselves? Isn't this leaking?
1159a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert
11660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void clearPartitions() {
1179a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
1189a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            partition.cursor = null;
11960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
12060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
12160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        notifyDataSetChanged();
12260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
12360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
1245cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov    /**
1255cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov     * Closes all cursors and removes all partitions.
1265cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov     */
1275cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov    public void close() {
1289a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
1299a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            Cursor cursor = partition.cursor;
1305cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov            if (cursor != null && !cursor.isClosed()) {
1315cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov                cursor.close();
1325cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov            }
1335cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov        }
1349a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.clear();
1355cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov        invalidate();
1365cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov        notifyDataSetChanged();
1375cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov    }
1385cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov
13960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void setHasHeader(int partitionIndex, boolean flag) {
1409a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.get(partitionIndex).hasHeader = flag;
14160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
14260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
14360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
14460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void setShowIfEmpty(int partitionIndex, boolean flag) {
1459a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.get(partitionIndex).showIfEmpty = flag;
14660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
14760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
14860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
14960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Partition getPartition(int partitionIndex) {
1509a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.get(partitionIndex);
15160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
15260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
15360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected void invalidate() {
15460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mCacheValid = false;
15560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
15660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
15760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getPartitionCount() {
1589a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.size();
15960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
16060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
16160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected void ensureCacheValid() {
16260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (mCacheValid) {
16360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            return;
16460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
16560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
16660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mCount = 0;
1679a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
1689a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            Cursor cursor = partition.cursor;
16960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            int count = cursor != null ? cursor.getCount() : 0;
1709a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            if (partition.hasHeader) {
1719a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (count != 0 || partition.showIfEmpty) {
17260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    count++;
17360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
17460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
1759a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            partition.count = count;
17660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            mCount += count;
17760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
17860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
17960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mCacheValid = true;
18060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
18160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
18260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
18360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true if the specified partition was configured to have a header.
18460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
18560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean hasHeader(int partition) {
1869a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.get(partition).hasHeader;
18760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
18860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
18960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
19060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the total number of list items in all partitions.
19160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
19260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getCount() {
19360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
19460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return mCount;
19560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
19660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
19760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
19860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the cursor for the given partition
19960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
20060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Cursor getCursor(int partition) {
2019a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.get(partition).cursor;
20260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
20360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
20460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
20560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Changes the cursor for an individual partition.
20660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
20760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void changeCursor(int partition, Cursor cursor) {
2089a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        Cursor prevCursor = mPartitions.get(partition).cursor;
20960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (prevCursor != cursor) {
21060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (prevCursor != null && !prevCursor.isClosed()) {
21160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                prevCursor.close();
21260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
2139a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            mPartitions.get(partition).cursor = cursor;
21460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (cursor != null) {
2159a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                mPartitions.get(partition).idColumnIndex = cursor.getColumnIndex("_id");
21660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
21760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            invalidate();
21860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            notifyDataSetChanged();
21960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
22060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
22160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
22260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
22360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true if the specified partition has no cursor or an empty cursor.
22460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
22560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean isPartitionEmpty(int partition) {
2269a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        Cursor cursor = mPartitions.get(partition).cursor;
22760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return cursor == null || cursor.getCount() == 0;
22860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
22960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
23060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
23160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Given a list position, returns the index of the corresponding partition.
23260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
23360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getPartitionForPosition(int position) {
23460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
23560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
2369a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
2379a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartitions.get(i).count;
23860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
23960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return i;
24060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
24160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
24260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
24360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return -1;
24460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
24560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
24660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
24760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Given a list position, return the offset of the corresponding item in its
24860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * partition.  The header, if any, will have offset -1.
24960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
25060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getOffsetInPartition(int position) {
25160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
25260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
2539a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
2549a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + partition.count;
25560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
25660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
2579a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (partition.hasHeader) {
25860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
25960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
26060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return offset;
26160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
26260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
26360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
26460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return -1;
26560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
26660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
26760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
26860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the first list position for the specified partition.
26960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
27060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getPositionForPartition(int partition) {
27160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
27260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int position = 0;
27360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        for (int i = 0; i < partition; i++) {
2749a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            position += mPartitions.get(i).count;
27560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
27660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return position;
27760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
27860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
27960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
28060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getViewTypeCount() {
28160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return getItemViewTypeCount() + 1;
28260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
28360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
28460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
28560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the overall number of item view types across all partitions. An
28660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * implementation of this method needs to ensure that the returned count is
28760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * consistent with the values returned by {@link #getItemViewType(int,int)}.
28860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
28960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getItemViewTypeCount() {
29060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return 1;
29160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
29260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
29360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
29460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the view type for the list item at the specified position in the
29560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * specified partition.
29660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
29760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected int getItemViewType(int partition, int position) {
29860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return 1;
29960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
30060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
30160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
30260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getItemViewType(int position) {
30360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
30460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
3059a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
3069a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start  + mPartitions.get(i).count;
30760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
30860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
3099a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartitions.get(i).hasHeader) {
31053f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                    offset--;
31153f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                }
31253f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                if (offset == -1) {
31360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return IGNORE_ITEM_VIEW_TYPE;
31453f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                } else {
31553f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                    return getItemViewType(i, offset);
31660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
31760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
31860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
31960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
32060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
32160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        throw new ArrayIndexOutOfBoundsException(position);
32260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
32360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
32460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public View getView(int position, View convertView, ViewGroup parent) {
32560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
32660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
3279a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
3289a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartitions.get(i).count;
32960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
33060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
3319a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartitions.get(i).hasHeader) {
33260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
33360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
33460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                View view;
33560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (offset == -1) {
3369a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                    view = getHeaderView(i, mPartitions.get(i).cursor, convertView, parent);
33760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                } else {
3389a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                    if (!mPartitions.get(i).cursor.moveToPosition(offset)) {
33960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                        throw new IllegalStateException("Couldn't move cursor to position "
34060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                                + offset);
34160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    }
3429a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                    view = getView(i, mPartitions.get(i).cursor, offset, convertView, parent);
34360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
34460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (view == null) {
34560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    throw new NullPointerException("View should not be null, partition: " + i
34660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                            + " position: " + offset);
34760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
34860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return view;
34960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
35060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
35160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
35260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
35360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        throw new ArrayIndexOutOfBoundsException(position);
35460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
35560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
35660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
35760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the header view for the specified partition, creating one if needed.
35860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
35960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected View getHeaderView(int partition, Cursor cursor, View convertView,
36060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent) {
36160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        View view = convertView != null
36260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                ? convertView
36360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                : newHeaderView(mContext, partition, cursor, parent);
36460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        bindHeaderView(view, partition, cursor);
36560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return view;
36660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
36760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
36860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
36960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Creates the header view for the specified partition.
37060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
37160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected View newHeaderView(Context context, int partition, Cursor cursor,
37260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent) {
37360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return null;
37460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
37560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
37660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
37760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Binds the header view for the specified partition.
37860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
37960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected void bindHeaderView(View view, int partition, Cursor cursor) {
38060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
38160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
38260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
38360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns an item view for the specified partition, creating one if needed.
38460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
38560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected View getView(int partition, Cursor cursor, int position, View convertView,
38660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent) {
38760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        View view;
38860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (convertView != null) {
38960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            view = convertView;
39060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        } else {
39160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            view = newView(mContext, partition, cursor, position, parent);
39260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
39360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        bindView(view, partition, cursor, position);
39460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return view;
39560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
39660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
39760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
39860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Creates an item view for the specified partition and position. Position
39960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * corresponds directly to the current cursor position.
40060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
40160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected abstract View newView(Context context, int partition, Cursor cursor, int position,
40260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent);
40360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
40460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
40560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Binds an item view for the specified partition and position. Position
40660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * corresponds directly to the current cursor position.
40760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
40860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected abstract void bindView(View v, int partition, Cursor cursor, int position);
40960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
41060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
41160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns a pre-positioned cursor for the specified list position.
41260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
41360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Object getItem(int position) {
41460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
41560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
4169a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition mPartition : mPartitions) {
4179a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartition.count;
41860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
41960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
4209a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartition.hasHeader) {
42160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
42260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
42360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (offset == -1) {
42460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return null;
42560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
4269a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                Cursor cursor = mPartition.cursor;
42760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                cursor.moveToPosition(offset);
42860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return cursor;
42960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
43060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
43160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
43260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
43360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return null;
43460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
43560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
43660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
43760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the item ID for the specified list position.
43860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
43960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public long getItemId(int position) {
44060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
44160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
4429a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition mPartition : mPartitions) {
4439a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartition.count;
44460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
44560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
4469a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartition.hasHeader) {
44760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
44860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
44960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (offset == -1) {
45060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return 0;
45160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
4529a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartition.idColumnIndex == -1) {
45360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return 0;
45460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
45560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
4569a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                Cursor cursor = mPartition.cursor;
45760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(offset)) {
45860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return 0;
45960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
4609a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                return cursor.getLong(mPartition.idColumnIndex);
46160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
46260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
46360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
46460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
46560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return 0;
46660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
46760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
46860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
46960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns false if any partition has a header.
47060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
47160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
47260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean areAllItemsEnabled() {
4739a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition mPartition : mPartitions) {
4749a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            if (mPartition.hasHeader) {
47560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return false;
47660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
47760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
47860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return true;
47960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
48060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
48160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
48260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true for all items except headers.
48360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
48460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
48560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean isEnabled(int position) {
48660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
48760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
4889a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
4899a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartitions.get(i).count;
49060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
49160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
4929a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartitions.get(i).hasHeader && offset == 0) {
49360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return false;
49460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                } else {
49560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return isEnabled(i, offset);
49660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
49760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
49860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
49960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
50060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
50160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return false;
50260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
50360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
50460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
50560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true if the item at the specified offset of the specified
50660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * partition is selectable and clickable.
50760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
50860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected boolean isEnabled(int partition, int position) {
50960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return true;
51060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
51155f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov
51255f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    /**
51355f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov     * Enable or disable data change notifications.  It may be a good idea to
51455f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov     * disable notifications before making changes to several partitions at once.
51555f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov     */
51655f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    public void setNotificationsEnabled(boolean flag) {
5177c76d5f2cd2cc35e7c4f33264d5f281c96351377Gilles Debunne        mNotificationsEnabled = flag;
5187c76d5f2cd2cc35e7c4f33264d5f281c96351377Gilles Debunne        if (flag && mNotificationNeeded) {
51955f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            notifyDataSetChanged();
52055f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        }
52155f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    }
52255f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov
52355f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    @Override
52455f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    public void notifyDataSetChanged() {
52555f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        if (mNotificationsEnabled) {
52655f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            mNotificationNeeded = false;
52755f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            super.notifyDataSetChanged();
52855f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        } else {
52955f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            mNotificationNeeded = true;
53055f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        }
53155f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    }
53260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov}
533