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        }
57e93a23581cbb9da2282b5897ffc167f86836afaeNancy Chen
58e93a23581cbb9da2282b5897ffc167f86836afaeNancy Chen        public boolean isEmpty() {
59e93a23581cbb9da2282b5897ffc167f86836afaeNancy Chen            return count == 0;
60e93a23581cbb9da2282b5897ffc167f86836afaeNancy Chen        }
6160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
6260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
6360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private final Context mContext;
649a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    private ArrayList<Partition> mPartitions;
6560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private int mCount = 0;
6660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    private boolean mCacheValid = true;
6755f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    private boolean mNotificationsEnabled = true;
6855f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    private boolean mNotificationNeeded;
6960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
7060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public CompositeCursorAdapter(Context context) {
7160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        this(context, INITIAL_CAPACITY);
7260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
7360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
7460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public CompositeCursorAdapter(Context context, int initialCapacity) {
7560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mContext = context;
769a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions = new ArrayList<Partition>();
7760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
7860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
7960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Context getContext() {
8060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return mContext;
8160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
8260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
8360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
8460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Registers a partition. The cursor for that partition can be set later.
8560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Partitions should be added in the order they are supposed to appear in the
8660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * list.
8760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
8860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void addPartition(boolean showIfEmpty, boolean hasHeader) {
8960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        addPartition(new Partition(showIfEmpty, hasHeader));
9060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
9160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
9260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void addPartition(Partition partition) {
939a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.add(partition);
949a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        invalidate();
959a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        notifyDataSetChanged();
969a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    }
979a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert
989a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    public void addPartition(int location, Partition partition) {
999a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.add(location, partition);
10060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
10160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        notifyDataSetChanged();
10260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
10360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
10460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void removePartition(int partitionIndex) {
1059a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        Cursor cursor = mPartitions.get(partitionIndex).cursor;
10660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (cursor != null && !cursor.isClosed()) {
10760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            cursor.close();
10860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
1099a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.remove(partitionIndex);
11060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
11160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        notifyDataSetChanged();
11260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
11360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
11460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
11560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Removes cursors for all partitions.
11660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
117e93a23581cbb9da2282b5897ffc167f86836afaeNancy Chen    // TODO: Is this really what this is supposed to do? Just remove the cursors? Not close them?
1189a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert    // Not remove the partitions themselves? Isn't this leaking?
1199a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert
12060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void clearPartitions() {
1219a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
1229a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            partition.cursor = null;
12360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
12460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
12560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        notifyDataSetChanged();
12660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
12760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
1285cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov    /**
1295cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov     * Closes all cursors and removes all partitions.
1305cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov     */
1315cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov    public void close() {
1329a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
1339a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            Cursor cursor = partition.cursor;
1345cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov            if (cursor != null && !cursor.isClosed()) {
1355cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov                cursor.close();
1365cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov            }
1375cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov        }
1389a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.clear();
1395cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov        invalidate();
1405cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov        notifyDataSetChanged();
1415cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov    }
1425cc774535d73c09b6788b63ecc728e60da09cfa9Dmitri Plotnikov
14360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void setHasHeader(int partitionIndex, boolean flag) {
1449a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.get(partitionIndex).hasHeader = flag;
14560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
14660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
14760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
14860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void setShowIfEmpty(int partitionIndex, boolean flag) {
1499a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        mPartitions.get(partitionIndex).showIfEmpty = flag;
15060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        invalidate();
15160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
15260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
15360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Partition getPartition(int partitionIndex) {
1549a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.get(partitionIndex);
15560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
15660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
15760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected void invalidate() {
15860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mCacheValid = false;
15960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
16060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
16160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getPartitionCount() {
1629a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.size();
16360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
16460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
16560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected void ensureCacheValid() {
16660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (mCacheValid) {
16760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            return;
16860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
16960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
17060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mCount = 0;
1719a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
1729a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            Cursor cursor = partition.cursor;
1737158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner            int count;
1747158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner            if (cursor == null || cursor.isClosed()) {
1757158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner                count = 0;
1767158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner            } else {
1777158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner                count = cursor.getCount();
1787158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner            }
1799a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            if (partition.hasHeader) {
1809a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (count != 0 || partition.showIfEmpty) {
18160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    count++;
18260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
18360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
1849a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            partition.count = count;
18560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            mCount += count;
18660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
18760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
18860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        mCacheValid = true;
18960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
19060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
19160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
19260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true if the specified partition was configured to have a header.
19360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
19460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean hasHeader(int partition) {
1959a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.get(partition).hasHeader;
19660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
19760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
19860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
19960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the total number of list items in all partitions.
20060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
20160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getCount() {
20260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
20360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return mCount;
20460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
20560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
20660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
20760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the cursor for the given partition
20860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
20960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Cursor getCursor(int partition) {
2109a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        return mPartitions.get(partition).cursor;
21160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
21260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
21360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
21460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Changes the cursor for an individual partition.
21560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
21660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public void changeCursor(int partition, Cursor cursor) {
2179a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        Cursor prevCursor = mPartitions.get(partition).cursor;
21860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (prevCursor != cursor) {
21960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (prevCursor != null && !prevCursor.isClosed()) {
22060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                prevCursor.close();
22160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
2229a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            mPartitions.get(partition).cursor = cursor;
22329134bfe1712e58c31c68789247495e2efcc7fdbWalter Jang            if (cursor != null && !cursor.isClosed()) {
2249a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                mPartitions.get(partition).idColumnIndex = cursor.getColumnIndex("_id");
22560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
22660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            invalidate();
22760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            notifyDataSetChanged();
22860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
22960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
23060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
23160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
23260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true if the specified partition has no cursor or an empty cursor.
23360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
23460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean isPartitionEmpty(int partition) {
2359a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        Cursor cursor = mPartitions.get(partition).cursor;
23662e75fbd7d174d511e35a19a882a249490daa2cdJay Shrauner        return cursor == null || cursor.isClosed() || cursor.getCount() == 0;
23760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
23860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
23960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
24060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Given a list position, returns the index of the corresponding partition.
24160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
24260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getPartitionForPosition(int position) {
24360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
24460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
2459a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
2469a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartitions.get(i).count;
24760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
24860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return i;
24960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
25060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
25160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
25260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return -1;
25360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
25460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
25560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
25660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Given a list position, return the offset of the corresponding item in its
25760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * partition.  The header, if any, will have offset -1.
25860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
25960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getOffsetInPartition(int position) {
26060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
26160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
2629a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition partition : mPartitions) {
2639a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + partition.count;
26460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
26560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
2669a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (partition.hasHeader) {
26760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
26860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
26960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return offset;
27060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
27160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
27260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
27360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return -1;
27460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
27560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
27660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
27760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the first list position for the specified partition.
27860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
27960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getPositionForPartition(int partition) {
28060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
28160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int position = 0;
28260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        for (int i = 0; i < partition; i++) {
2839a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            position += mPartitions.get(i).count;
28460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
28560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return position;
28660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
28760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
28860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
28960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getViewTypeCount() {
29060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return getItemViewTypeCount() + 1;
29160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
29260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
29360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
29460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the overall number of item view types across all partitions. An
29560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * implementation of this method needs to ensure that the returned count is
29660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * consistent with the values returned by {@link #getItemViewType(int,int)}.
29760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
29860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getItemViewTypeCount() {
29960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return 1;
30060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
30160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
30260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
30360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the view type for the list item at the specified position in the
30460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * specified partition.
30560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
30660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected int getItemViewType(int partition, int position) {
30760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return 1;
30860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
30960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
31060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
31160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public int getItemViewType(int position) {
31260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
31360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
3149a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
3159a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start  + mPartitions.get(i).count;
31660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
31760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
3189a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartitions.get(i).hasHeader) {
31953f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                    offset--;
32053f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                }
32153f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                if (offset == -1) {
32260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return IGNORE_ITEM_VIEW_TYPE;
32353f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                } else {
32453f35c7c31f31db40b106cc0f7a51f5daf40a7fdYorke Lee                    return getItemViewType(i, offset);
32560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
32660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
32760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
32860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
32960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
33060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        throw new ArrayIndexOutOfBoundsException(position);
33160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
33260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
33360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public View getView(int position, View convertView, ViewGroup parent) {
33460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
33560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
3369a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
3379a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartitions.get(i).count;
33860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
33960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
3409a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartitions.get(i).hasHeader) {
34160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
34260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
34360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                View view;
34460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (offset == -1) {
3459a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                    view = getHeaderView(i, mPartitions.get(i).cursor, convertView, parent);
34660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                } else {
3479a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                    if (!mPartitions.get(i).cursor.moveToPosition(offset)) {
34860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                        throw new IllegalStateException("Couldn't move cursor to position "
34960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                                + offset);
35060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    }
3519a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                    view = getView(i, mPartitions.get(i).cursor, offset, convertView, parent);
35260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
35360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (view == null) {
35460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    throw new NullPointerException("View should not be null, partition: " + i
35560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                            + " position: " + offset);
35660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
35760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return view;
35860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
35960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
36060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
36160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
36260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        throw new ArrayIndexOutOfBoundsException(position);
36360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
36460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
36560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
36660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the header view for the specified partition, creating one if needed.
36760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
36860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected View getHeaderView(int partition, Cursor cursor, View convertView,
36960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent) {
37060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        View view = convertView != null
37160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                ? convertView
37260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                : newHeaderView(mContext, partition, cursor, parent);
37360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        bindHeaderView(view, partition, cursor);
37460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return view;
37560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
37660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
37760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
37860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Creates the header view for the specified partition.
37960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
38060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected View newHeaderView(Context context, int partition, Cursor cursor,
38160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent) {
38260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return null;
38360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
38460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
38560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
38660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Binds the header view for the specified partition.
38760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
38860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected void bindHeaderView(View view, int partition, Cursor cursor) {
38960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
39060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
39160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
39260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns an item view for the specified partition, creating one if needed.
39360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
39460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected View getView(int partition, Cursor cursor, int position, View convertView,
39560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent) {
39660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        View view;
39760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        if (convertView != null) {
39860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            view = convertView;
39960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        } else {
40060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            view = newView(mContext, partition, cursor, position, parent);
40160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
40260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        bindView(view, partition, cursor, position);
40360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return view;
40460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
40560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
40660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
40760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Creates an item view for the specified partition and position. Position
40860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * corresponds directly to the current cursor position.
40960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
41060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected abstract View newView(Context context, int partition, Cursor cursor, int position,
41160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            ViewGroup parent);
41260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
41360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
41460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Binds an item view for the specified partition and position. Position
41560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * corresponds directly to the current cursor position.
41660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
41760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected abstract void bindView(View v, int partition, Cursor cursor, int position);
41860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
41960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
42060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns a pre-positioned cursor for the specified list position.
42160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
42260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public Object getItem(int position) {
42360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
42460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
4259a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition mPartition : mPartitions) {
4269a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartition.count;
42760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
42860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
4299a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartition.hasHeader) {
43060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
43160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
43260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (offset == -1) {
43360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return null;
43460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
4359a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                Cursor cursor = mPartition.cursor;
4367158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner                if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(offset)) {
4377158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner                    return null;
4387158b6705d330ac1e61d5aa51c51b54507c4ab88Jay Shrauner                }
43960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return cursor;
44060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
44160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
44260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
44360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
44460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return null;
44560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
44660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
44760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
44860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns the item ID for the specified list position.
44960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
45060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public long getItemId(int position) {
45160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
45260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
4539a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition mPartition : mPartitions) {
4549a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartition.count;
45560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
45660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
4579a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartition.hasHeader) {
45860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    offset--;
45960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
46060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (offset == -1) {
46160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return 0;
46260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
4639a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartition.idColumnIndex == -1) {
46460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return 0;
46560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
46660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
4679a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                Cursor cursor = mPartition.cursor;
46860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(offset)) {
46960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return 0;
47060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
4719a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                return cursor.getLong(mPartition.idColumnIndex);
47260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
47360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
47460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
47560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
47660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return 0;
47760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
47860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
47960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
48060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns false if any partition has a header.
48160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
48260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
48360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean areAllItemsEnabled() {
4849a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (Partition mPartition : mPartitions) {
4859a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            if (mPartition.hasHeader) {
48660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                return false;
48760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
48860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
48960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return true;
49060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
49160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
49260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
49360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true for all items except headers.
49460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
49560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    @Override
49660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    public boolean isEnabled(int position) {
49760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        ensureCacheValid();
49860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        int start = 0;
4999a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert        for (int i = 0, n = mPartitions.size(); i < n; i++) {
5009a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert            int end = start + mPartitions.get(i).count;
50160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            if (position >= start && position < end) {
50260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                int offset = position - start;
5039a4f02a8eaf7eb3991900231dbea250e4fb34553Alon Albert                if (mPartitions.get(i).hasHeader && offset == 0) {
50460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return false;
50560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                } else {
50660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                    return isEnabled(i, offset);
50760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov                }
50860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            }
50960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov            start = end;
51060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        }
51160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
51260ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return false;
51360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
51460ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov
51560ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    /**
51660ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * Returns true if the item at the specified offset of the specified
51760ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     * partition is selectable and clickable.
51860ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov     */
51960ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    protected boolean isEnabled(int partition, int position) {
52060ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov        return true;
52160ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov    }
52255f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov
52355f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    /**
52455f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov     * Enable or disable data change notifications.  It may be a good idea to
52555f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov     * disable notifications before making changes to several partitions at once.
52655f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov     */
52755f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    public void setNotificationsEnabled(boolean flag) {
5287c76d5f2cd2cc35e7c4f33264d5f281c96351377Gilles Debunne        mNotificationsEnabled = flag;
5297c76d5f2cd2cc35e7c4f33264d5f281c96351377Gilles Debunne        if (flag && mNotificationNeeded) {
53055f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            notifyDataSetChanged();
53155f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        }
53255f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    }
53355f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov
53455f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    @Override
53555f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    public void notifyDataSetChanged() {
53655f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        if (mNotificationsEnabled) {
53755f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            mNotificationNeeded = false;
53855f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            super.notifyDataSetChanged();
53955f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        } else {
54055f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov            mNotificationNeeded = true;
54155f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov        }
54255f04311fb40ccadb224f1a4dc1b8ff473dfdf03Dmitri Plotnikov    }
54360ae52719e0567fa5b1860df19807716951eca50Dmitri Plotnikov}
544