185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey/*
285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * Copyright (C) 2006 The Android Open Source Project
385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey *
485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * Licensed under the Apache License, Version 2.0 (the "License");
585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * you may not use this file except in compliance with the License.
685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * You may obtain a copy of the License at
785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey *
885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey *      http://www.apache.org/licenses/LICENSE-2.0
985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey *
1085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * Unless required by applicable law or agreed to in writing, software
1185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * distributed under the License is distributed on an "AS IS" BASIS,
1285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * See the License for the specific language governing permissions and
1485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * limitations under the License.
1585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey */
1685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
170dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rosepackage com.xtremelabs.robolectric.shadows;
180dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose
190dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose
200dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Roseimport android.content.Context;
2185af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport android.database.ContentObserver;
220dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Roseimport android.database.Cursor;
2385af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport android.database.DataSetObserver;
2485af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport android.os.Handler;
2585af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport android.util.Config;
2685af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport android.util.Log;
275c64020aebafacaa7677f81c044ca22cb1694539Michael Portuesiimport android.view.View;
285c64020aebafacaa7677f81c044ca22cb1694539Michael Portuesiimport android.view.ViewGroup;
290dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Roseimport android.widget.CursorAdapter;
3085af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport android.widget.FilterQueryProvider;
310dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose
320dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Roseimport com.xtremelabs.robolectric.internal.Implementation;
330dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Roseimport com.xtremelabs.robolectric.internal.Implements;
340dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose
3585af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport java.util.ArrayList;
3685af7906879a68c99b1878dac22605fa32454f3fRich Humphreyimport java.util.List;
3729cbbdc99eee133fd8bccb3084fa3881a9ee1233adriancowham
3885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey/**
3985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * Adapter that exposes data from a {@link android.database.Cursor Cursor} to a
4085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * {@link android.widget.ListView ListView} widget. The Cursor must include
4185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey * a column named "_id" or this class will not work.
4285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey */
430dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose@Implements(CursorAdapter.class)
4485af7906879a68c99b1878dac22605fa32454f3fRich Humphreypublic class ShadowCursorAdapter extends ShadowBaseAdapter {
4585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
4685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    private List<View> views = new ArrayList<View>();
4729cbbdc99eee133fd8bccb3084fa3881a9ee1233adriancowham
486d2daa795cd59a43fbebc4e10e0a314a5440bb59Rich Humphrey    @Implementation
4985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public View getView(int position, View convertView, ViewGroup parent) {
5081f3b8bb674e98064e45d7f953cc089daa02b6aeadriancowham    	// if the cursor is null OR there are no views to dispense return null
5181f3b8bb674e98064e45d7f953cc089daa02b6aeadriancowham        if (this.mCursor == null || views.size() == 0 ) {
5285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return null;
5385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
5481f3b8bb674e98064e45d7f953cc089daa02b6aeadriancowham
5585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (convertView != null) {
5685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return convertView;
5785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
5885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
5985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        return views.get(position);
6085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
6185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
6285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
6385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Non-Android API.  Set a list of views to be returned for successive
6485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * calls to getView().
6585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
6685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param views
6785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
6885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public void setViews(List<View> views) {
6985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        this.views = views;
700dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    }
7185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
7285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
7385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
7485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
7585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
7685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected boolean mDataValid;
7785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
7885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
7985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
8085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
8185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected boolean mAutoRequery;
8285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
8385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
8485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
8585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
8685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected Cursor mCursor;
8785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
8885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
8985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
9085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
9185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected Context mContext;
9285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
9385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
9485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
9585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
9685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected int mRowIDColumn;
9785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
9885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
9985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
10085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
10185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected ChangeObserver mChangeObserver;
10285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
10385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
10485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
10585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
10685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected DataSetObserver mDataSetObserver = new MyDataSetObserver();
10785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    /**
10885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * This field should be made private, so it is hidden from the SDK.
10985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * {@hide}
11085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     */
11185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    protected CursorFilter__FromAndroid mCursorFilter;
11285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
11385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This field should be made private, so it is hidden from the SDK.
11485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@hide}
11585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
11685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected FilterQueryProvider mFilterQueryProvider;
11785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
11885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
11985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Constructor. The adapter will call requery() on the cursor whenever
12085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * it changes so that the most recent data is always displayed.
12185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
12285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param c       The cursor from which to get the data.
12385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param context The context
12485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
12585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public void __constructor__(Context context, Cursor c) {
12685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        initialize(context, c, true);
12785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
12885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
12985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
13085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Constructor
13185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
13285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param c           The cursor from which to get the data.
13385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param context     The context
13485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param autoRequery If true the adapter will call requery() on the
13585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *                    cursor whenever it changes so the most recent
13685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *                    data is always displayed.
13785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
13885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public void __constructor__(Context context, Cursor c, boolean autoRequery) {
13985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        initialize(context, c, autoRequery);
14085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
14185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
14285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    // renamed from Android source so as not to conflict with RobolectricWiringTest
14385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    private void initialize(Context context, Cursor c, boolean autoRequery) {
14485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        boolean cursorPresent = c != null;
14585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mAutoRequery = autoRequery;
14685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mCursor = c;
14785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mDataValid = cursorPresent;
14885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mContext = context;
14985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mRowIDColumn = cursorPresent ? c.getColumnIndexOrThrow("_id") : -1;
15085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mChangeObserver = new ChangeObserver();
15185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (cursorPresent) {
15285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            c.registerContentObserver(mChangeObserver);
15385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            c.registerDataSetObserver(mDataSetObserver);
15485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
15585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
15685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
15785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
15885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Returns the cursor.
15985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
16085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @return the cursor.
16185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
1620dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    @Implementation
1630dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    public Cursor getCursor() {
16485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        return mCursor;
1650dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    }
16685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
16785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
16885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see android.widget.ListAdapter#getCount()
16985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
1700dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    @Implementation
1710dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    public int getCount() {
17285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (mDataValid && mCursor != null) {
17385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return mCursor.getCount();
17485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        } else {
17585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return 0;
17685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
1770dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    }
17885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
17985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
18085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see android.widget.ListAdapter#getItem(int)
18185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
1820dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    @Implementation
1830dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    public Object getItem(int position) {
18485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (mDataValid && mCursor != null) {
18585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mCursor.moveToPosition(position);
18685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return mCursor;
18785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        } else {
18885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return null;
18985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
19085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
19185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
19285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
19385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see android.widget.ListAdapter#getItemId(int)
19485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
1950dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    @Implementation
1960dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    public long getItemId(int position) {
19785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (mDataValid && mCursor != null) {
19885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            this.mCursor.getColumnIndexOrThrow("_id");
19985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            if (mCursor.moveToPosition(position)) {
20085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey                return mCursor.getLong(mRowIDColumn);
20185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            } else {
20285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey                return 0;
20385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            }
20485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        } else {
20585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return 0;
20685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
20785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
2080dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose
20985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    @Implementation
21085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public boolean hasStableIds() {
21185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        return true;
2120dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    }
21385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
21485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    /**
21585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @see android.widget.ListAdapter#getView(int, View, ViewGroup)
21685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     */
21785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    @Implementation
21885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    public View getView(int position, View convertView, ViewGroup parent) {
21985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        if (!mDataValid) {
22085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            throw new IllegalStateException("this should only be called when the cursor is valid");
22185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        }
22285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        if (!mCursor.moveToPosition(position)) {
22385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            throw new IllegalStateException("couldn't move cursor to position " + position);
22485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        }
22585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        View v;
22685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        if (convertView == null) {
22785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            v = newView(mContext, mCursor, parent);
22885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        } else {
22985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            v = convertView;
23085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        }
23185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        bindView(v, mContext, mCursor);
23285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        return v;
23385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    }
23485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//
23585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    @Implementation
23685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    public View getDropDownView(int position, View convertView, ViewGroup parent) {
23785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        if (mDataValid) {
23885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            mCursor.moveToPosition(position);
23985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            View v;
24085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            if (convertView == null) {
24185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//                v = newDropDownView(mContext, mCursor, parent);
24285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            } else {
24385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//                v = convertView;
24485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            }
24585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            bindView(v, mContext, mCursor);
24685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            return v;
24785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        } else {
24885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            return null;
24985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        }
25085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    }
25185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
25285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    /**
25385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * Makes a new view to hold the data pointed to by cursor.
25485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param context Interface to application's global information
25585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param cursor The cursor from which to get the data. The cursor is already
25685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * moved to the correct position.
25785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param parent The parent to which the new view is attached to
25885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @return the newly created view.
25985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     */
26085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    public abstract View newView(Context context, Cursor cursor, ViewGroup parent);
26185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
26285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    /**
26385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * Makes a new drop down view to hold the data pointed to by cursor.
26485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param context Interface to application's global information
26585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param cursor The cursor from which to get the data. The cursor is already
26685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * moved to the correct position.
26785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param parent The parent to which the new view is attached to
26885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @return the newly created view.
26985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     */
27085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    @Implementation
27185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) {
27285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        return newView(context, cursor, parent);
27385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    }
27485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
27585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    /**
27685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * Bind an existing view to the data pointed to by cursor
27785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param view Existing view, returned earlier by newView
27885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param context Interface to application's global information
27985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * @param cursor The cursor from which to get the data. The cursor is already
28085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     * moved to the correct position.
28185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//     */
28285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    public abstract void bindView(View view, Context context, Cursor cursor);
28385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
28485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
28585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Change the underlying cursor to a new cursor. If there is an existing cursor it will be
28685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * closed.
28785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
28885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param cursor the new cursor to be used
28985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
2900dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    @Implementation
29185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public void changeCursor(Cursor cursor) {
29285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (cursor == mCursor) {
29385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return;
29485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
29585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (mCursor != null) {
29685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mCursor.unregisterContentObserver(mChangeObserver);
29785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mCursor.unregisterDataSetObserver(mDataSetObserver);
29885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mCursor.close();
29985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
30085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mCursor = cursor;
30185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (cursor != null) {
30285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            cursor.registerContentObserver(mChangeObserver);
30385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            cursor.registerDataSetObserver(mDataSetObserver);
30485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mRowIDColumn = cursor.getColumnIndexOrThrow("_id");
30585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mDataValid = true;
30685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            // notify the observers about the new cursor
30785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            notifyDataSetChanged();
30885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        } else {
30985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mRowIDColumn = -1;
31085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mDataValid = false;
31185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            // notify the observers about the lack of a data set
31285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            notifyDataSetInvalidated();
31385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
31485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
31585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
3160dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    /**
31785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * <p>Converts the cursor into a CharSequence. Subclasses should override this
31885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * method to convert their results. The default implementation returns an
31985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * empty String for null values or the default String representation of
32085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * the value.</p>
32185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
32285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param cursor the cursor to convert to a CharSequence
32385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @return a CharSequence representing the value
3240dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose     */
32585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    @Implementation
32685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public CharSequence convertToString(Cursor cursor) {
32785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        return cursor == null ? "" : cursor.toString();
3280dabe713bf2d78df246d9cff18ed11363491a2acAdam Cohen-Rose    }
32985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
33085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
33185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Runs a query with the specified constraint. This query is requested
33285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * by the filter attached to this adapter.
33385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * <p/>
33485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * The query is provided by a
33585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@link android.widget.FilterQueryProvider}.
33685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * If no provider is specified, the current cursor is not filtered and returned.
33785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * <p/>
33885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * After this method returns the resulting cursor is passed to {@link #changeCursor(Cursor)}
33985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * and the previous cursor is closed.
34085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * <p/>
34185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * This method is always executed on a background thread, not on the
34285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * application's main thread (or UI thread.)
34385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * <p/>
34485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Contract: when constraint is null or empty, the original results,
34585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * prior to any filtering, must be returned.
34685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
34785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param constraint the constraint with which the query must be filtered
34885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @return a Cursor representing the results of the new query
34985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #getFilter()
35085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #getFilterQueryProvider()
35185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #setFilterQueryProvider(android.widget.FilterQueryProvider)
35285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
35385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    @Implementation
35485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
35585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (mFilterQueryProvider != null) {
35685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return mFilterQueryProvider.runQuery(constraint);
35785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
35885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
35985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        return mCursor;
36085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
36185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
36285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    @Implementation
36385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    public Filter getFilter() {
36485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        if (mCursorFilter == null) {
36585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//            mCursorFilter = new CursorFilter__FromAndroid(this);
36685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        }
36785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//        return mCursorFilter;
36885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey//    }
36985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
37085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
37185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Returns the query filter provider used for filtering. When the
37285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * provider is null, no filtering occurs.
37385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
37485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @return the current filter query provider or null if it does not exist
37585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #setFilterQueryProvider(android.widget.FilterQueryProvider)
37685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #runQueryOnBackgroundThread(CharSequence)
37785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
37885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    @Implementation
37985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public FilterQueryProvider getFilterQueryProvider() {
38085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        return mFilterQueryProvider;
38185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
38285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
38385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
38485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Sets the query filter provider used to filter the current Cursor.
38585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * The provider's
38685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * {@link android.widget.FilterQueryProvider#runQuery(CharSequence)}
38785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * method is invoked when filtering is requested by a client of
38885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * this adapter.
38985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
39085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @param filterQueryProvider the filter query provider or null to remove it
39185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #getFilterQueryProvider()
39285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see #runQueryOnBackgroundThread(CharSequence)
39385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
39485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    @Implementation
39585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    public void setFilterQueryProvider(FilterQueryProvider filterQueryProvider) {
39685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        mFilterQueryProvider = filterQueryProvider;
39785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
39885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
39985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    /**
40085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * Called when the {@link ContentObserver} on the cursor receives a change notification.
40185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * The default implementation provides the auto-requery logic, but may be overridden by
40285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * sub classes.
40385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     *
40485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     * @see ContentObserver#onChange(boolean)
40585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey     */
40685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    // renamed from Android source so as not to conflict with RobolectricWiringTest
40785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    protected void onContentChangedInternal() {
40885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        if (mAutoRequery && mCursor != null && !mCursor.isClosed()) {
40985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            if (Config.LOGV) Log.v("Cursor", "Auto requerying " + mCursor + " due to update");
41085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mDataValid = mCursor.requery();
41185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
41285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
41385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
41485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    private class ChangeObserver extends ContentObserver {
41585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        public ChangeObserver() {
41685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            super(new Handler());
41785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
41885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
41985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        @Override
42085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        public boolean deliverSelfNotifications() {
42185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            return true;
42285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
42385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
42485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        @Override
42585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        public void onChange(boolean selfChange) {
42685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            onContentChangedInternal();
42785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
42885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
42985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
43085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    private class MyDataSetObserver extends DataSetObserver {
43185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        @Override
43285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        public void onChanged() {
43385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mDataValid = true;
43485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            notifyDataSetChanged();
43585af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
43685af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
43785af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        @Override
43885af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        public void onInvalidated() {
43985af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            mDataValid = false;
44085af7906879a68c99b1878dac22605fa32454f3fRich Humphrey            notifyDataSetInvalidated();
44185af7906879a68c99b1878dac22605fa32454f3fRich Humphrey        }
44285af7906879a68c99b1878dac22605fa32454f3fRich Humphrey    }
44385af7906879a68c99b1878dac22605fa32454f3fRich Humphrey
44485af7906879a68c99b1878dac22605fa32454f3fRich Humphrey}