/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.widget.cts;

import org.xmlpull.v1.XmlPullParser;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.test.ActivityInstrumentationTestCase;
import android.test.TouchUtils;
import android.test.UiThreadTest;
import android.test.ViewAsserts;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.GridLayoutAnimationController.AnimationParameters;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.AdapterView.OnItemClickListener;

import com.android.cts.stub.R;

import dalvik.annotation.TestTargets;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.ToBeFixed;

/**
 * Test {@link GridView}.
 */
@TestTargetClass(GridView.class)
public class GridViewTest extends ActivityInstrumentationTestCase<GridViewStubActivity> {
    private GridView mGridView;
    private Activity mActivity;
    private Instrumentation mInstrumentation;

    public GridViewTest() {
        super("com.android.cts.stub", GridViewStubActivity.class);
    }

    private GridView findGridViewById(int id) {
        return (GridView) mActivity.findViewById(id);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        mGridView = null;
        mActivity = getActivity();
        mInstrumentation = getInstrumentation();
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test constructor(s) of {@link GridView}",
            method = "GridView",
            args = {android.content.Context.class}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test constructor(s) of {@link GridView}",
            method = "GridView",
            args = {android.content.Context.class, android.util.AttributeSet.class}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test constructor(s) of {@link GridView}",
            method = "GridView",
            args = {android.content.Context.class, android.util.AttributeSet.class, int.class}
        )
    })
    @ToBeFixed(bug = "1417734", explanation = "GridView#GridView(Context), " +
            "GridView#GridView(Context, AttributeSet) and " +
            "GridView#GridView(Context, AttributeSet, int)" +
            " should check whether the input Context is null")
    public void testConstructor() {
        new GridView(mActivity);

        new GridView(mActivity, null);

        new GridView(mActivity, null, com.android.internal.R.attr.gridViewStyle);

        XmlPullParser parser = mActivity.getResources().getXml(R.layout.gridview_layout);
        AttributeSet attrs = Xml.asAttributeSet(parser);
        new GridView(mActivity, attrs);
        new GridView(mActivity, attrs, 0);

        try {
            new GridView(null);
            fail("should throw NullPointerException.");
        } catch (NullPointerException e) {
        }

        try {
            new GridView(null, null);
            fail("should throw NullPointerException.");
        } catch (NullPointerException e) {
        }

        try {
            new GridView(null, null, 0);
            fail("should throw NullPointerException.");
        } catch (NullPointerException e) {
        }
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "setAdapter",
            args = {android.widget.ListAdapter.class}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "getAdapter",
            args = {}
        )
    })
    public void testAccessAdapter() {
        mGridView = new GridView(mActivity);
        // set Adapter
        ImageAdapter adapter = new ImageAdapter(mActivity);
        mGridView.setAdapter(adapter);
        assertSame(adapter, mGridView.getAdapter());

        mGridView.setAdapter(null);
        assertNull(mGridView.getAdapter());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#setSelection(int)}",
        method = "setSelection",
        args = {int.class}
    )
    public void testSetSelection() {
        mGridView = new GridView(mActivity);
        mGridView.setSelection(0);
        assertEquals(0, mGridView.getSelectedItemPosition());

        mGridView.setSelection(-1);
        assertEquals(-1, mGridView.getSelectedItemPosition());

        mGridView.setSelection(mGridView.getCount());
        assertEquals(mGridView.getCount(), mGridView.getSelectedItemPosition());
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test {@link GridView#onKeyDown(int, KeyEvent)}",
            method = "onKeyDown",
            args = {int.class, android.view.KeyEvent.class}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test {@link GridView#onKeyDown(int, KeyEvent)}",
            method = "onKeyUp",
            args = {int.class, android.view.KeyEvent.class}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test {@link GridView#onKeyDown(int, KeyEvent)}",
            method = "onKeyMultiple",
            args = {int.class, int.class, android.view.KeyEvent.class}
        )
    })
    @ToBeFixed(bug = "", explanation = "Fix click callback tests")
    public void testPressKey() {
        final int NUM_COLUMNS = 3;
        mGridView = findGridViewById(R.id.gridview);

        MockOnItemClickListener listener = new MockOnItemClickListener();
        mGridView.setOnItemClickListener(listener);

        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new ImageAdapter(mActivity));
                mGridView.setNumColumns(NUM_COLUMNS);
                mGridView.invalidate();
                mGridView.requestLayout();
                mGridView.requestFocus();
            }
        });
        mInstrumentation.waitForIdleSync();

        assertEquals(0, mGridView.getSelectedItemPosition());
        KeyEvent event = new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_RIGHT);
        mInstrumentation.sendKeySync(event);
        assertEquals(1, mGridView.getSelectedItemPosition());

        event = new KeyEvent(KeyEvent.ACTION_MULTIPLE, KeyEvent.KEYCODE_DPAD_LEFT);
        mInstrumentation.sendKeySync(event);
        assertEquals(0, mGridView.getSelectedItemPosition());

        assertEquals(0, mGridView.getSelectedItemPosition());
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_RIGHT);
        assertEquals(1, mGridView.getSelectedItemPosition());

        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_LEFT);
        assertEquals(0, mGridView.getSelectedItemPosition());

        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
        assertEquals(NUM_COLUMNS, mGridView.getSelectedItemPosition());

        assertFalse(listener.hasOnItemClickCalled());
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
        assertTrue(listener.hasOnItemClickCalled());

        listener.reset();
        assertFalse(listener.hasOnItemClickCalled());
        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
        assertTrue(listener.hasOnItemClickCalled());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#setGravity(int)}",
        method = "setGravity",
        args = {int.class}
    )
    public void testSetGravity() {
        mGridView = findGridViewById(R.id.gridview);

        View child;
        final int NUM_COLUMNS = 1;
        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new ImageAdapter(mActivity));
                mGridView.setNumColumns(NUM_COLUMNS);
                mGridView.setHorizontalSpacing(0);
                mGridView.setVerticalSpacing(0);
            }
        });
        mInstrumentation.waitForIdleSync();

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setGravity(Gravity.CENTER_HORIZONTAL);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();

        child = mGridView.getChildAt(0); // get the first view.
        ViewAsserts.assertHorizontalCenterAligned(mGridView, child);

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setGravity(Gravity.LEFT);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();

        child = mGridView.getChildAt(0); // get the first view.
        ViewAsserts.assertLeftAligned(mGridView, child, mGridView.getListPaddingLeft());

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setGravity(Gravity.RIGHT);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();

        child = mGridView.getChildAt(0); // get the first view.
        ViewAsserts.assertRightAligned(mGridView, child, mGridView.getListPaddingRight());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#setHorizontalSpacing(int)}",
        method = "setHorizontalSpacing",
        args = {int.class}
    )
    public void testSetHorizontalSpacing() {
        mGridView = findGridViewById(R.id.gridview);
        // Number of columns should be big enough, otherwise the
        // horizontal spacing cannot be correctly verified.
        mGridView.setNumColumns(20);

        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new MockGridViewAdapter(3));
                mGridView.setHorizontalSpacing(0);
            }
        });
        mInstrumentation.waitForIdleSync();

        View child0 = mGridView.getChildAt(0);
        View child1 = mGridView.getChildAt(1);
        assertEquals(0, child1.getLeft() - child0.getRight());

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setHorizontalSpacing(5);
            }
        });
        mInstrumentation.waitForIdleSync();

        child0 = mGridView.getChildAt(0);
        child1 = mGridView.getChildAt(1);
        assertEquals(5, child1.getLeft() - child0.getRight());
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#setVerticalSpacing(int)}",
        method = "setVerticalSpacing",
        args = {int.class}
    )
    public void testSetVerticalSpacing() {
        mGridView = findGridViewById(R.id.gridview);

        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new MockGridViewAdapter(3));
                mGridView.setVerticalSpacing(0);
            }
        });
        mInstrumentation.waitForIdleSync();

        View child0 = mGridView.getChildAt(0);
        View child1 = mGridView.getChildAt(1);
        assertEquals(0, child1.getTop() - child0.getBottom());

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setVerticalSpacing(5);
            }
        });
        mInstrumentation.waitForIdleSync();

        child0 = mGridView.getChildAt(0);
        child1 = mGridView.getChildAt(1);
        assertEquals(5, child1.getTop() - child0.getBottom());
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "setStretchMode",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            method = "getStretchMode",
            args = {}
        )
    })
    public void testAccessStretchMode() {
        mGridView = findGridViewById(R.id.gridview);
        View child;

        final int NUM_COLUMNS = 8;
        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new ImageAdapter(mActivity));
                mGridView.setColumnWidth(10);
                mGridView.setNumColumns(NUM_COLUMNS);
                mGridView.setHorizontalSpacing(0);
                mGridView.setVerticalSpacing(0);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();

        int[][] childRight = new int[3][3];
        int STRETCH_SPACING = 0;
        int STRETCH_COLUMN_WIDTH = 1;
        int STRETCH_SPACING_UNIFORM = 2;
        int INDEX_RIGHTMOST = 0;
        int INDEX_0 = 1;
        int INDEX_1 = 2;

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setColumnWidth(15);
                mGridView.setStretchMode(GridView.STRETCH_SPACING);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(GridView.STRETCH_SPACING, mGridView.getStretchMode());
        child = mGridView.getChildAt(NUM_COLUMNS - 1); // get the rightmost view at the first line.
        childRight[STRETCH_SPACING][INDEX_RIGHTMOST] = child.getRight();

        child = mGridView.getChildAt(0);
        childRight[STRETCH_SPACING][INDEX_0] = child.getRight();

        child = mGridView.getChildAt(1);
        childRight[STRETCH_SPACING][INDEX_1] = child.getRight();

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setColumnWidth(15);
                mGridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(GridView.STRETCH_COLUMN_WIDTH, mGridView.getStretchMode());
        child = mGridView.getChildAt(NUM_COLUMNS - 1); // get the rightmost view at the first line.
        childRight[STRETCH_COLUMN_WIDTH][INDEX_RIGHTMOST] = child.getRight();

        child = mGridView.getChildAt(0);
        childRight[STRETCH_COLUMN_WIDTH][INDEX_0] = child.getRight();

        child = mGridView.getChildAt(1);
        childRight[STRETCH_COLUMN_WIDTH][INDEX_1] = child.getRight();

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setColumnWidth(15);
                mGridView.setStretchMode(GridView.STRETCH_SPACING_UNIFORM);
                mGridView.invalidate();
                mGridView.requestLayout();
            }
        });
        mInstrumentation.waitForIdleSync();
        assertEquals(GridView.STRETCH_SPACING_UNIFORM, mGridView.getStretchMode());
        child = mGridView.getChildAt(NUM_COLUMNS - 1); // get the rightmost view at the first line.
        childRight[STRETCH_SPACING_UNIFORM][INDEX_RIGHTMOST] = child.getRight();

        child = mGridView.getChildAt(0);
        childRight[STRETCH_SPACING_UNIFORM][INDEX_0] = child.getRight();

        child = mGridView.getChildAt(1);
        childRight[STRETCH_SPACING_UNIFORM][INDEX_1] = child.getRight();

        assertTrue(childRight[STRETCH_SPACING][INDEX_RIGHTMOST]
                > childRight[STRETCH_COLUMN_WIDTH][INDEX_RIGHTMOST]);
        assertTrue(childRight[STRETCH_SPACING][INDEX_RIGHTMOST]
                > childRight[STRETCH_SPACING_UNIFORM][INDEX_RIGHTMOST]);
        assertTrue(childRight[STRETCH_SPACING][INDEX_0]
                == childRight[STRETCH_COLUMN_WIDTH][INDEX_0]);
        assertTrue(childRight[STRETCH_SPACING][INDEX_0]
                < childRight[STRETCH_SPACING_UNIFORM][INDEX_0]);
        assertTrue(childRight[STRETCH_SPACING][INDEX_1]
                > childRight[STRETCH_COLUMN_WIDTH][INDEX_1]);
        assertTrue(childRight[STRETCH_SPACING][INDEX_1]
                < childRight[STRETCH_SPACING_UNIFORM][INDEX_1]);
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#setNumColumns(int)}",
        method = "setNumColumns",
        args = {int.class}
    )
    public void testSetNumColumns() {
        mGridView = findGridViewById(R.id.gridview);

        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new MockGridViewAdapter(10));
                mGridView.setHorizontalSpacing(0);
                mGridView.setVerticalSpacing(0);
                mGridView.setNumColumns(10);
            }
        });
        mInstrumentation.waitForIdleSync();

        View child0 = mGridView.getChildAt(0);
        View child9 = mGridView.getChildAt(9);
        assertEquals(child0.getBottom(), child9.getBottom());

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setNumColumns(9);
            }
        });
        mInstrumentation.waitForIdleSync();

        child0 = mGridView.getChildAt(0);
        child9 = mGridView.getChildAt(9);
        assertEquals(child0.getBottom(), child9.getTop());
        assertEquals(child0.getLeft(), child9.getLeft());

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setNumColumns(1);
            }
        });
        mInstrumentation.waitForIdleSync();

        for (int i = 0; i < mGridView.getChildCount(); i++) {
            View child = mGridView.getChildAt(i);
            assertEquals(0, child.getLeft() - mGridView.getListPaddingLeft());
        }
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        method = "attachLayoutAnimationParameters",
        args = {android.view.View.class, android.view.ViewGroup.LayoutParams.class, int.class, 
                int.class}
    )
    public void testAttachLayoutAnimationParameters() {
        MockGridView mockGridView = new MockGridView(mActivity);
        ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(320, 480);
        mockGridView.attachLayoutAnimationParameters(null, p, 1, 2);
        AnimationParameters animationParams = (AnimationParameters) p.layoutAnimationParameters;
        assertEquals(1, animationParams.index);
        assertEquals(2, animationParams.count);
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#layoutChildren()}",
        method = "layoutChildren",
        args = {}
    )
    @ToBeFixed(bug = "1400249", explanation = "It will be tested by functional test.")
    public void testLayoutChildren() {
        MockGridView mockGridView = new MockGridView(mActivity);
        mockGridView.layoutChildren();
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#onFocusChanged(boolean, int, Rect)}",
        method = "onFocusChanged",
        args = {boolean.class, int.class, android.graphics.Rect.class}
    )
    @UiThreadTest
    public void testOnFocusChanged() {
        final MockGridView mockGridView = new MockGridView(mActivity);

        assertFalse(mockGridView.hasCalledOnFocusChanged());
        mockGridView.setAdapter(new MockGridViewAdapter(10));
        mockGridView.setFocusable(true);
        mockGridView.requestFocus();

        assertTrue(mockGridView.hasCalledOnFocusChanged());
        mockGridView.reset();
        assertFalse(mockGridView.hasCalledOnFocusChanged());

        mockGridView.clearFocus();

        assertTrue(mockGridView.hasCalledOnFocusChanged());
    }

    @TestTargetNew(
        level = TestLevel.NOT_NECESSARY,
        notes = "Test {@link GridView#onMeasure(int, int)}",
        method = "onMeasure",
        args = {int.class, int.class}
    )
    public void testOnMeasure() {
        // Do not test it. It's implementation detail.
    }

    @TestTargetNew(
        level = TestLevel.COMPLETE,
        notes = "Test {@link GridView#setColumnWidth(int)}",
        method = "setColumnWidth",
        args = {int.class}
    )
    public void testSetColumnWidth() {
        mGridView = findGridViewById(R.id.gridview);

        // this test case can not be ran in UI thread.
        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setAdapter(new MockGridViewAdapter(10));
                mGridView.setNumColumns(GridView.AUTO_FIT);
                mGridView.setHorizontalSpacing(0);
                mGridView.setVerticalSpacing(0);
                mGridView.setColumnWidth(0);
            }
        });
        mInstrumentation.waitForIdleSync();

        // Verify whether column number equals 2.
        View child0 = mGridView.getChildAt(0);
        View child1 = mGridView.getChildAt(1);
        View child2 = mGridView.getChildAt(2);
        assertEquals(child0.getBottom(), child1.getBottom());
        assertEquals(child0.getLeft(), child2.getLeft());

        mActivity.runOnUiThread(new Runnable() {
            public void run() {
                mGridView.setNumColumns(GridView.AUTO_FIT);
                mGridView.setColumnWidth(Integer.MAX_VALUE);
            }
        });
        mInstrumentation.waitForIdleSync();

        child0 = mGridView.getChildAt(0);
        child1 = mGridView.getChildAt(1);
        assertEquals(child0.getBottom(), child1.getTop());
        assertEquals(child0.getLeft(), child1.getLeft());
    }

    @TestTargets({
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test {@link GridView#computeVerticalScrollExtent()}",
            method = "computeVerticalScrollExtent",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test {@link GridView#computeVerticalScrollExtent()}",
            method = "computeVerticalScrollOffset",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.COMPLETE,
            notes = "Test {@link GridView#computeVerticalScrollExtent()}",
            method = "computeVerticalScrollRange",
            args = {}
        )
    })
    public void testScroll() throws Throwable {
        final MockGridView mockGridView= new MockGridView(mActivity);
        final ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        // this test case can not be ran in UI thread.
        runTestOnUiThread(new Runnable() {
            public void run() {
                mActivity.getWindow().setContentView(mockGridView, params);
                mockGridView.setAdapter(new ImageAdapter(mActivity));
            }
        });
        mInstrumentation.waitForIdleSync();
        TouchUtils.scrollToTop(this, mActivity, mockGridView);

        int oldRange = mockGridView.computeVerticalScrollRange();
        int oldExtent = mockGridView.computeVerticalScrollExtent();
        int oldOffset = mockGridView.computeVerticalScrollOffset();

        TouchUtils.scrollToBottom(this, mActivity, mockGridView);
        assertEquals(oldRange, mockGridView.computeVerticalScrollRange());
        assertEquals(oldExtent, mockGridView.computeVerticalScrollExtent());
        assertTrue(oldOffset < mockGridView.computeVerticalScrollOffset());
    }

    private static class MockGridView extends GridView {
        private boolean mCalledOnMeasure = false;
        private boolean mCalledOnFocusChanged = false;

        public boolean hasCalledOnMeasure() {
            return mCalledOnMeasure;
        }

        public boolean hasCalledOnFocusChanged() {
            return mCalledOnFocusChanged;
        }

        public void reset() {
            mCalledOnMeasure = false;
            mCalledOnFocusChanged = false;
        }

        public MockGridView(Context context) {
            super(context);
        }

        public MockGridView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public MockGridView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }

        @Override
        public void attachLayoutAnimationParameters(View child,
                ViewGroup.LayoutParams params, int index, int count) {
            super.attachLayoutAnimationParameters(child, params, index, count);
        }

        @Override
        protected void layoutChildren() {
            super.layoutChildren();
        }

        @Override
        protected int computeVerticalScrollExtent() {
            return super.computeVerticalScrollExtent();
        }

        @Override
        protected int computeVerticalScrollOffset() {
            return super.computeVerticalScrollOffset();
        }

        @Override
        protected int computeVerticalScrollRange() {
            return super.computeVerticalScrollRange();
        }

        @Override
        protected void onFocusChanged(boolean gainFocus, int direction,
                Rect previouslyFocusedRect) {
            mCalledOnFocusChanged = true;
            super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            mCalledOnMeasure = true;
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    class MockOnItemClickListener implements OnItemClickListener {
        private boolean mOnItemClickCalled = false;

        public boolean hasOnItemClickCalled() {
            return mOnItemClickCalled;
        }

        public void reset() {
            mOnItemClickCalled = false;
        }

        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            mOnItemClickCalled = true;
        }
    }

    private class MockGridViewAdapter implements ListAdapter, Filterable {
        private final int mCount;

        MockGridViewAdapter(int count) {
            mCount = count;
        }

        MockGridViewAdapter() {
            this(1);
        }

        public boolean areAllItemsEnabled() {
            return true;
        }

        public boolean isEnabled(int position) {
            return true;
        }

        public void registerDataSetObserver(DataSetObserver observer) {
        }

        public void unregisterDataSetObserver(DataSetObserver observer) {
        }

        public int getCount() {
            return mCount;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public boolean hasStableIds() {
            return false;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            if ((convertView != null) && (convertView instanceof ImageView)) {
                ((ImageView) convertView).setImageResource(R.drawable.size_48x48);
                return convertView;
            }

            ImageView newView = new ImageView(mActivity);
            AbsListView.LayoutParams params = new AbsListView.LayoutParams(
                                                  AbsListView.LayoutParams.WRAP_CONTENT,
                                                  AbsListView.LayoutParams.WRAP_CONTENT);
            newView.setLayoutParams(params);
            newView.setImageResource(R.drawable.size_48x48);
            return newView;
        }

        public int getItemViewType(int position) {
            return 0;
        }

        public int getViewTypeCount() {
            return 1;
        }

        public boolean isEmpty() {
            return false;
        }

        public Filter getFilter() {
            return new FilterTest();
        }
    }

    private static class FilterTest extends Filter {
        @Override
        protected Filter.FilterResults performFiltering(CharSequence constraint) {
            return null;
        }

        @Override
        protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
        }
    }

    public class ImageAdapter implements ListAdapter {
        public ImageAdapter(Context c) {
            mContext = c;
        }

        public int getCount() {
            return mThumbIds.length;
        }

        public Object getItem(int position) {
            return position;
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView imageView;
            if (convertView == null) {
                imageView = new ImageView(mContext);
                int layoutSize = (int)(50 * mContext.getResources().getDisplayMetrics().density);
                imageView.setLayoutParams(new GridView.LayoutParams(layoutSize, layoutSize));
                imageView.setAdjustViewBounds(false);
                imageView.setScaleType(ImageView.ScaleType.CENTER);
                imageView.setPadding(0, 0, 0, 0);
            } else {
                imageView = (ImageView) convertView;
            }

            imageView.setImageResource(mThumbIds[position]);

            return imageView;
        }

        private Context mContext;

        private Integer[] mThumbIds = {
                R.drawable.failed, R.drawable.pass,
                R.drawable.animated, R.drawable.black,
                R.drawable.blue, R.drawable.red,
                R.drawable.animated, R.drawable.black,
                R.drawable.blue, R.drawable.failed,
                R.drawable.pass, R.drawable.red,
        };

        private final DataSetObservable mDataSetObservable = new DataSetObservable();

        public boolean hasStableIds() {
            return false;
        }

        public void registerDataSetObserver(DataSetObserver observer) {
            mDataSetObservable.registerObserver(observer);
        }

        public void unregisterDataSetObserver(DataSetObserver observer) {
            mDataSetObservable.unregisterObserver(observer);
        }

        public void notifyDataSetChanged() {
            mDataSetObservable.notifyChanged();
        }

        public void notifyDataSetInvalidated() {
            mDataSetObservable.notifyInvalidated();
        }

        public boolean areAllItemsEnabled() {
            return true;
        }

        public boolean isEnabled(int position) {
            return true;
        }

        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return getView(position, convertView, parent);
        }

        public int getItemViewType(int position) {
            return 0;
        }

        public int getViewTypeCount() {
            return 1;
        }

        public boolean isEmpty() {
            return getCount() == 0;
        }
    }
}
