10b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su/*
20b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * Copyright (C) 2008 The Android Open Source Project
30b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su *
40b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * Licensed under the Apache License, Version 2.0 (the "License");
50b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * you may not use this file except in compliance with the License.
60b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * You may obtain a copy of the License at
70b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su *
80b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su *      http://www.apache.org/licenses/LICENSE-2.0
90b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su *
100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * Unless required by applicable law or agreed to in writing, software
110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * distributed under the License is distributed on an "AS IS" BASIS,
120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * See the License for the specific language governing permissions and
140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * limitations under the License.
150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su */
160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Supackage android.text.method.cts;
180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1968897e40ea2b6cd1203aea4c65a804217dde8515Brett Chabotimport dalvik.annotation.KnownFailure;
200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.os.SystemClock;
220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.test.ActivityInstrumentationTestCase2;
230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.text.Layout;
240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.text.Spannable;
250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.text.SpannableString;
260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.text.method.MovementMethod;
270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.text.method.ScrollingMovementMethod;
280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.view.KeyEvent;
290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.view.MotionEvent;
300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.view.View;
310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.view.ViewConfiguration;
320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.view.ViewGroup;
330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.view.ViewGroup.LayoutParams;
340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.widget.TextView;
350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Suimport android.widget.TextView.BufferType;
36f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsuimport android.widget.cts.WidgetTestUtils;
370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su/**
390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * Test {@link ScrollingMovementMethod}. The class is an implementation of interface
400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * {@link MovementMethod}. The typical usage of {@link MovementMethod} is tested in
410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * {@link android.widget.cts.TextViewTest} and this test case is only focused on the
420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * implementation of the methods.
430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su *
440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su * @see android.widget.cts.TextViewTest
450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su */
460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Supublic class ScrollingMovementMethodTest extends ActivityInstrumentationTestCase2<StubActivity> {
470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private static final int LITTLE_SPACE = 20;
480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private static final String THREE_LINES_TEXT = "first line\nsecond line\nlast line";
500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private TextView mTextView;
520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private Spannable mSpannable;
540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private int mScaledTouchSlop;
560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public ScrollingMovementMethodTest() {
580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        super("com.android.cts.stub", StubActivity.class);
590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    @Override
620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    protected void setUp() throws Exception {
630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        super.setUp();
640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        mTextView = new TextView(getActivity());
650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        mTextView.setText(THREE_LINES_TEXT, BufferType.EDITABLE);
660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        mSpannable = (Spannable) mTextView.getText();
670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        mScaledTouchSlop = ViewConfiguration.get(getActivity()).getScaledTouchSlop();
680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testConstructor() {
710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        new ScrollingMovementMethod();
720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testGetInstance() {
750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        MovementMethod method0 = ScrollingMovementMethod.getInstance();
760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(method0 instanceof ScrollingMovementMethod);
770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        MovementMethod method1 = ScrollingMovementMethod.getInstance();
790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertSame(method0, method1);
800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnTouchEventHorizontalMotion() throws Throwable {
830b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
850b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
860b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
870b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final ScrollingMovementMethod method = new ScrollingMovementMethod();
920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
930b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
940b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setText("hello world", BufferType.SPANNABLE);
950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setSingleLine();
960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mSpannable = (Spannable) mTextView.getText();
97f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
99f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
1000b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
1020b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
1030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1040b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        float rightMost = mTextView.getLayout().getLineRight(0) - mTextView.getWidth()
1050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                + mTextView.getTotalPaddingLeft() + mTextView.getTotalPaddingRight();
1060b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int leftMost = mTextView.getScrollX();
1070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final long now = SystemClock.uptimeMillis();
1090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
1100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // press
1120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
1140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final int tinyDist = -(mScaledTouchSlop - 1);
1180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int previousScrollX = mTextView.getScrollX();
1190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
1200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move for short distance
1220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, tinyDist, 0, 0));
1240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(previousScrollX, mTextView.getScrollX());
1270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
1290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // release
1310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, tinyDist, 0, 0));
1330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
1370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // press
1390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
1410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final int distFar = -mScaledTouchSlop;
1450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
1460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
1470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move for enough distance
1490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, distFar, 0, 0));
1510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() > previousScrollX);
1540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() < rightMost);
1550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
1570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final int distTooFar = (int) (-rightMost * 10);
1580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
1590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move for long distance
1610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, distTooFar, 0, 0));
1630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() > previousScrollX);
16662c3e10261c06ab08dcf442421cfb37b5cef76bbNorio Nasu        assertEquals(rightMost, mTextView.getScrollX(), 1.0f);
1670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
1690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
1700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move back
1720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, 0, 0, 0));
1740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() < previousScrollX);
1770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(leftMost, mTextView.getScrollX());
1780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
1800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
1810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // release
1820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable,
1830b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, 0, 0, 0));
1840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
1850b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
1860b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
1870b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
1880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnTouchEventVerticalMotion() throws Throwable {
1890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
1900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
1910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
1920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
1930b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
1940b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
1950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
1960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
1970b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final ScrollingMovementMethod method = new ScrollingMovementMethod();
1980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
1990b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2000b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setLines(1);
2010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
2020cbe49a83ac10de466b8efa8d8775d8686353186Romain Guy                        new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
2030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2040b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
2050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
2060b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        float bottom = mTextView.getLayout().getHeight() - mTextView.getHeight()
2080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                + mTextView.getTotalPaddingTop() + mTextView.getTotalPaddingBottom();
2090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int top = mTextView.getScrollY();
2100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final long now = SystemClock.uptimeMillis();
2120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
2130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // press
2150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_DOWN, 0, 0, 0));
2170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final int tinyDist = -(mScaledTouchSlop - 1);
2210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int previousScrollY = mTextView.getScrollY();
2220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
2230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move for short distance
2250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_MOVE, 0, tinyDist, 0));
2270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(previousScrollY, mTextView.getScrollY());
2300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
2320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // release
2340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_UP, 0, tinyDist, 0));
2360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
2400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // press
2420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_DOWN, 0, 0, 0));
2440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final int distFar = -mScaledTouchSlop;
2480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollY = mTextView.getScrollY();
2490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
2500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move for enough distance
2520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_MOVE, 0, distFar, 0));
2540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollY() > previousScrollY);
2570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() < bottom);
2580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollY = mTextView.getScrollY();
2600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final int distTooFar = (int) (-bottom * 10);
2610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
2620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move for long distance
2640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_MOVE, 0, distTooFar, 0));
2660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollY() > previousScrollY);
2690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(bottom, mTextView.getScrollY(), 0f);
2700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollY = mTextView.getScrollY();
2720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
2730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // move back
2750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_MOVE, 0, 0, 0));
2770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollY() < previousScrollY);
2800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(top, mTextView.getScrollX());
2810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
2830b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
2840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                // release
2850b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.onTouchEvent(mTextView, mSpannable, MotionEvent.obtain(now, now,
2860b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.ACTION_UP, 0, 0, 0));
2870b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
2880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
2890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
2900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
2910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnTouchEventExceptional() throws Throwable {
2920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
2930b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
2940b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
2950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
2960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
2970b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
2980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
2990b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
3000b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
3010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
302f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
3030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
304f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
3050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
3060b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
3070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
3080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
3100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
3110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable, null);
3130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3147a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                long now = SystemClock.uptimeMillis();
3180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(mTextView, null,
3200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
3210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3227a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(null, mSpannable,
3270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
3280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3297a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable,
3330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
3340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(null, mSpannable,
3360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, - 10000, 0, 0));
3370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3387a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(mTextView, null,
3430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, - 10000, 0, 0));
3440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3457a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(null, mSpannable,
3500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, - 10000, 0, 0));
3510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3527a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
3560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    new ScrollingMovementMethod().onTouchEvent(mTextView, null,
3570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            MotionEvent.obtain(now, now, MotionEvent.ACTION_UP, - 10000, 0, 0));
3580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
3597a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
3600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
3610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
3620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
3630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
3640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testCanSelectArbitrarily() {
3660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(new ScrollingMovementMethod().canSelectArbitrarily());
3670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
3680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnKeyDownVerticalMovement() throws Throwable {
3700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
3710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
3720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
3730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
3740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
3750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
3760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
3770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
3780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
3790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
3800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView);
3810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
3820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
3830b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
3840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3850b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
3860b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
3870b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
3880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
3890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_DOWN,
3900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
3910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
3920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
3930b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(1);
3940b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
3950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
3960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
3970b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_UP,
3980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                        new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
3990b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4000b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
4020b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
4030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4040b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnKeyDownHorizontalMovement() throws Throwable {
4050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
4060b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
4070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
4080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
4090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
4100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
4110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
4120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
4130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
4140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
4150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setText("short");
4160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setSingleLine();
417f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
4180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
419f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
4200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
4230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
4250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int previousScrollX = mTextView.getScrollX();
4260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
4270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
4286cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                method.onKeyDown(mTextView, (Spannable) mTextView.getText(),
4296cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                        KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
4306cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                                KeyEvent.KEYCODE_DPAD_RIGHT));
4310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() > previousScrollX);
4340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
4360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
4370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
4386cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                method.onKeyDown(mTextView, (Spannable) mTextView.getText(),
4396cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                        KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
4406cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                                KeyEvent.KEYCODE_DPAD_LEFT));
4410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() < previousScrollX);
4440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
4460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
4470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
4480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
4496cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                assertFalse(method.onKeyDown(mTextView, mSpannable, 0,
4506cc97966e394e443fb65910766d8b3bd30ea2257Brian Muramatsu                        new KeyEvent(KeyEvent.ACTION_DOWN, 0)));
4510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(previousScrollX, mTextView.getScrollX());
4540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
4550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
4560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnKeyDownExceptions() throws Throwable {
4580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
4590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
4600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
4610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
4620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
4630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
4640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
4650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
4660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
4670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
4680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView);
4690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
4720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
4740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
4750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
4760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
4770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.onKeyDown(null, mSpannable, KeyEvent.KEYCODE_DPAD_RIGHT,
4780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
4790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
4807a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
4810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
4820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4830b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
4840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.onKeyDown(mTextView, null, KeyEvent.KEYCODE_DPAD_RIGHT,
4850b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                            new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP));
4860b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
4877a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
4880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
4890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
4910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.onKeyDown(mTextView, mSpannable, KeyEvent.KEYCODE_DPAD_RIGHT, null);
4920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
4937a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
4940b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
4950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
4960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
4970b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
4980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
4990b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testVerticalMovement() throws Throwable {
5000b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
5010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
5020b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
5030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
5040b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
5050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
5060b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
5070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
5080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
5090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
5100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setLines(1);
5120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
5130cbe49a83ac10de466b8efa8d8775d8686353186Romain Guy                        new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
5140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
5160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
5170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
5190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.down(mTextView, mSpannable);
5210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
5230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(1);
5240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
5260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.down(mTextView, mSpannable);
5280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
5300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(2);
5310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
5330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.down(mTextView, mSpannable);
5350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
5370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(2);
5380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
5400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.up(mTextView, mSpannable);
5420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
5440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(1);
5450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
5470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.up(mTextView, mSpannable);
5490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
5510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
5520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
5540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.up(mTextView, mSpannable);
5560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
5580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
5590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
5610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
5620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
5630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.up(null, mSpannable);
5640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
5657a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
5660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
5670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
5690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.up(mTextView, null);
5700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
5717a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
5720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
5730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
5750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.down(null, mSpannable);
5760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
5777a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
5780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
5790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
5810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.down(mTextView, null);
5820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
5837a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
5840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
5850b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
5860b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
5870b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
5880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testMovementWithNullLayout() {
5900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNull(mTextView.getLayout());
5910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
5920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            new MyScrollingMovementMethod().down(mTextView, mSpannable);
5930b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
5947a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
5950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
5960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
5970b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
5980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            new MyScrollingMovementMethod().up(mTextView, mSpannable);
5990b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
6007a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
6010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
6020b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
6040b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            new MyScrollingMovementMethod().left(mTextView, mSpannable);
6050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
6067a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
6070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
6080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
6100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            new MyScrollingMovementMethod().right(mTextView, mSpannable);
6110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
6127a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
6130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
6140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        long now = SystemClock.uptimeMillis();
6160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
6170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
6180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            new ScrollingMovementMethod().onKeyDown(mTextView, mSpannable,
6190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    KeyEvent.KEYCODE_DPAD_RIGHT, event);
6200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
6217a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
6220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
6230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable,
6250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 0, 0, 0));
6260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
6270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            new ScrollingMovementMethod().onTouchEvent(mTextView, mSpannable,
6280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    MotionEvent.obtain(now, now, MotionEvent.ACTION_MOVE, - 10000, 0, 0));
6290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
6307a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
6310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
6320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
6330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testInitialize() {
6350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        new ScrollingMovementMethod().initialize(null, null);
6360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
6370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnTrackballEvent() {
6390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        long now = SystemClock.uptimeMillis();
6400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        MotionEvent event = MotionEvent.obtain(now, now, 0, 2, -2, 0);
6410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        MyScrollingMovementMethod mockMethod = new MyScrollingMovementMethod();
6420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(mockMethod.onTrackballEvent(mTextView, mSpannable, event));
6440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(mockMethod.onTrackballEvent(null, mSpannable, event));
6450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(mockMethod.onTrackballEvent(mTextView, mSpannable, null));
6460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(mockMethod.onTrackballEvent(mTextView, null, event));
6470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
6480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnKeyUp() {
6500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        ScrollingMovementMethod method = new ScrollingMovementMethod();
6510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        SpannableString spannable = new SpannableString("Test Content");
6520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0);
6530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        TextView view = new TextView(getActivity());
6540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, event));
6560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(method.onKeyUp(null, null, 0, null));
6570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(method.onKeyUp(null, spannable, KeyEvent.KEYCODE_0, event));
6580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(method.onKeyUp(view, null, KeyEvent.KEYCODE_0, event));
6590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(method.onKeyUp(view, spannable, 0, event));
6600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(method.onKeyUp(view, spannable, KeyEvent.KEYCODE_0, null));
6610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
6620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testOnTakeFocus() throws Throwable {
6640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
6650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
6660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
6670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
6680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
6690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
6700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
6710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
6720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final ScrollingMovementMethod method = new ScrollingMovementMethod();
6730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        // wait until the text view gets layout
6740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNull(mTextView.getLayout());
6750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        try {
6760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            method.onTakeFocus(mTextView, mSpannable, View.FOCUS_BACKWARD);
6770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        } catch (NullPointerException e) {
6787a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach            // NPE is acceptable
6790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
6800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
6820b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
683f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                int height = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
6840b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
6850cbe49a83ac10de466b8efa8d8775d8686353186Romain Guy                        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
686f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                                height));
6870b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
6880b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
6890b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        Layout layout = mTextView.getLayout();
6900b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(layout);
6910b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
6920b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int previousScrollY = mTextView.getScrollY();
6930b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
6940b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
6950b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                method.onTakeFocus(mTextView, mSpannable, View.FOCUS_BACKWARD);
6960b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
6970b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
6980b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollY() >= previousScrollY);
6990b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(2);
7000b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7010b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollY = mTextView.getScrollY();
7020b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
7030b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7040b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                method.onTakeFocus(mTextView, mSpannable, View.FOCUS_FORWARD);
7050b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7060b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
7070b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollY() <= previousScrollY);
7080b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertVisibleLineInTextView(0);
7090b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7100b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
7110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
7130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.onTakeFocus(null, mSpannable, View.FOCUS_FORWARD);
7140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
7157a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
7160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
7170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                try {
7190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                    method.onTakeFocus(mTextView, null, View.FOCUS_FORWARD);
7200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                } catch (NullPointerException e) {
7217a06798806a656c5fbffd496a3606ecb1658b86fPhil Dubach                    // NPE is acceptable
7220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                }
7230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
7250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
7260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    public void testHorizontalMovement() throws Throwable {
7280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        /*
7290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * All these assertions depends on whether the TextView has a layout.The text view will not
7300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * get layout in setContent method but in otherhandler's function. Assertion which is
7310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * following the setContent will not get the expecting result. It have to wait all the
7320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * handlers' operations on the UiTread to finish. So all these cases are divided into
7330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * several steps,setting the content at first, waiting the layout, and checking the
7340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         * assertion at last.
7350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su         */
7360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
7370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(new Runnable() {
7380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setText("short");
7400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mTextView.setSingleLine();
741f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                int width = WidgetTestUtils.convertDipToPixels(getActivity(), LITTLE_SPACE);
7420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                getActivity().setContentView(mTextView,
743f176eafe119e8065c29f6eb99d62d01274581174Brian Muramatsu                        new ViewGroup.LayoutParams(width, ViewGroup.LayoutParams.WRAP_CONTENT));
7440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        });
7460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertNotNull(mTextView.getLayout());
7470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int previousScrollX = mTextView.getScrollX();
7490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
7500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.right(mTextView, mSpannable);
7530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
7550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() > previousScrollX);
7560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
7580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
7590b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7600b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.right(mTextView, mSpannable);
7610b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7620b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
7630b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(previousScrollX, mTextView.getScrollX());
7640b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7650b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
7660b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(getActionResult(new ActionRunnerWithResult() {
7670b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7680b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.left(mTextView, mSpannable);
7690b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7700b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
7710b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(mTextView.getScrollX() < previousScrollX);
7720b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7730b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        previousScrollX = mTextView.getScrollX();
7740b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertFalse(getActionResult(new ActionRunnerWithResult() {
7750b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            public void run() {
7760b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su                mResult = method.left(mTextView, mSpannable);
7770b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            }
7780b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }));
7790b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertEquals(previousScrollX, mTextView.getScrollX());
7800b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
7810b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
7828ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach    public void testOnKeyOther() throws Throwable {
7838ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        runActionOnUiThread(new Runnable() {
7848ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach            public void run() {
7858ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                getActivity().setContentView(mTextView);
7868ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach            }
7878ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        });
7888ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        assertNotNull(mTextView.getLayout());
7898ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach
7908ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        assertVisibleLineInTextView(0);
7918ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        final MyScrollingMovementMethod method = new MyScrollingMovementMethod();
7928ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        runActionOnUiThread(new Runnable() {
7938ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach            public void run() {
7948ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                method.onKeyOther(mTextView, null,
7958ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                        new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE,
7968ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                                KeyEvent.KEYCODE_DPAD_DOWN, 2));
7978ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach            }
7988ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        });
7998ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        assertVisibleLineInTextView(1);
8008ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach
8018ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        runActionOnUiThread(new Runnable() {
8028ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach            public void run() {
8038ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                method.onKeyOther(mTextView, null,
8048ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                        new KeyEvent(0, 0, KeyEvent.ACTION_MULTIPLE,
8058ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach                                KeyEvent.KEYCODE_DPAD_UP, 2));
8068ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach            }
8078ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        });
8088ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach        assertVisibleLineInTextView(0);
8098ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach    }
8108ce9f296cac94572c4cf16b5693a54c41258018fPhil Dubach
8110b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private void assertVisibleLineInTextView(int line) {
8120b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        Layout layout = mTextView.getLayout();
8130b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int scrollY = mTextView.getScrollY();
8140b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        int padding = mTextView.getTotalPaddingTop() + mTextView.getTotalPaddingBottom();
8150b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(layout.getLineForVertical(scrollY) <= line);
8160b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        assertTrue(layout.getLineForVertical(scrollY + mTextView.getHeight() - padding) >= line);
8170b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
8180b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8190b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private boolean getActionResult(ActionRunnerWithResult actionRunner) throws Throwable {
8200b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runActionOnUiThread(actionRunner);
8210b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        return actionRunner.getResult();
8220b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
8230b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8240b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private void runActionOnUiThread(Runnable actionRunner) throws Throwable {
8250b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        runTestOnUiThread(actionRunner);
8260b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        getInstrumentation().waitForIdleSync();
8270b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
8280b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8290b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private static abstract class ActionRunnerWithResult implements Runnable {
8300b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        protected boolean mResult = false;
8310b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8320b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        public boolean getResult() {
8330b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            return mResult;
8340b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
8350b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
8360b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8370b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    private static class MyScrollingMovementMethod extends ScrollingMovementMethod {
8380b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        @Override
8390b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        protected boolean down(TextView widget, Spannable buffer) {
8400b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            return super.down(widget, buffer);
8410b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
8420b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8430b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        @Override
8440b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        protected boolean left(TextView widget, Spannable buffer) {
8450b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            return super.left(widget, buffer);
8460b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
8470b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8480b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        @Override
8490b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        protected boolean right(TextView widget, Spannable buffer) {
8500b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            return super.right(widget, buffer);
8510b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
8520b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su
8530b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        @Override
8540b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        protected boolean up(TextView widget, Spannable buffer) {
8550b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su            return super.up(widget, buffer);
8560b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su        }
8570b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su    }
8580b9320a68db44c2ca8a11a221c2c22bbc116e2d5Scott Su}
859