19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
171d3165f10b12165f02b7015ac1a817c5f60e6399Neal Nguyenpackage android.util;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
191d3165f10b12165f02b7015ac1a817c5f60e6399Neal Nguyenimport com.android.frameworks.coretests.R;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Color;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that has a known number of selectable rows, and maintains a notion of which
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * row is selected. The rows take up the
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * entire width of the view.  The height of the view is divided evenly among
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the rows.
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
3936a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov * Note: If the height of the view does not divide exactly to the number of rows,
4036a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov *       the last row's height is inflated with the remainder. For example, if the
4136a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov *       view height is 22 and there are two rows, the height of the first row is
4236a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov *       10 and the second 22.
4336a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov *
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Notice what this view does to be a good citizen w.r.t its internal selection:
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1) calls {@link View#requestRectangleOnScreen} each time the selection changes due to
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    internal navigation.
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2) implements {@link View#getFocusedRect} by filling in the rectangle of the currently
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    selected row
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3) overrides {@link View#onFocusChanged} and sets selection appropriately according to
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *    the previously focused rectangle.
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InternalSelectionView extends View {
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mPainter = new Paint();
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mTextPaint = new Paint();
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Rect mTempRect = new Rect();
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumRows = 5;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mSelectedRow = 0;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int mEstimatedPixelHeight = 10;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Integer mDesiredHeight = null;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private String mLabel = null;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InternalSelectionView(Context context, int numRows, String label) {
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumRows = numRows;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLabel = label;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        init();
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InternalSelectionView(Context context, AttributeSet attrs) {
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a =
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                context.obtainStyledAttributes(
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        attrs, R.styleable.SelectableRowView);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumRows = a.getInt(R.styleable.SelectableRowView_numRows, 5);
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        init();
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void init() {
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setFocusable(true);
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTextPaint.setAntiAlias(true);
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTextPaint.setTextSize(10);
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTextPaint.setColor(Color.WHITE);
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNumRows() {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNumRows;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getSelectedRow() {
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSelectedRow;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDesiredHeight(int desiredHeight) {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDesiredHeight = desiredHeight;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String getLabel() {
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mLabel;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMeasuredDimension(
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            measureWidth(widthMeasureSpec),
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            measureHeight(heightMeasureSpec));
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int measureWidth(int measureSpec) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int specMode = MeasureSpec.getMode(measureSpec);
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int specSize = MeasureSpec.getSize(measureSpec);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int desiredWidth = 300 + mPaddingLeft + mPaddingRight;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (specMode == MeasureSpec.EXACTLY) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We were told how big to be
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return specSize;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (specMode == MeasureSpec.AT_MOST) {
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return desiredWidth < specSize ? desiredWidth : specSize;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return desiredWidth;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int measureHeight(int measureSpec) {
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int specMode = MeasureSpec.getMode(measureSpec);
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int specSize = MeasureSpec.getSize(measureSpec);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int desiredHeight = mDesiredHeight != null ?
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDesiredHeight :
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNumRows * mEstimatedPixelHeight + mPaddingTop + mPaddingBottom;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (specMode == MeasureSpec.EXACTLY) {
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We were told how big to be
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return specSize;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (specMode == MeasureSpec.AT_MOST) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return desiredHeight < specSize ? desiredHeight : specSize;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return desiredHeight;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onDraw(Canvas canvas) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rectTop = mPaddingTop;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rectLeft = mPaddingLeft;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rectRight = getWidth() - mPaddingRight;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < mNumRows; i++) {
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPainter.setColor(Color.BLACK);
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPainter.setAlpha(0x20);
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15436a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov            int rowHeight = getRowHeight(i);
15536a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // draw background rect
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTempRect.set(rectLeft, rectTop, rectRight, rectTop + rowHeight);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.drawRect(mTempRect, mPainter);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // draw forground rect
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (i == mSelectedRow && hasFocus()) {
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPainter.setColor(Color.RED);
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPainter.setAlpha(0xF0);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTextPaint.setAlpha(0xFF);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPainter.setColor(Color.BLACK);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPainter.setAlpha(0x40);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTextPaint.setAlpha(0xF0);
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mTempRect.set(rectLeft + 2, rectTop + 2,
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    rectRight - 2, rectTop + rowHeight - 2);
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.drawRect(mTempRect, mPainter);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // draw text to help when visually inspecting
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.drawText(
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Integer.toString(i),
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    rectLeft + 2,
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    rectTop + 2 - (int) mTextPaint.ascent(),
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mTextPaint);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rectTop += rowHeight;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18536a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov    private int getRowHeight(int row) {
18636a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov        final int availableHeight = getHeight() - mPaddingTop - mPaddingBottom;
18736a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov        final int desiredRowHeight = availableHeight / mNumRows;
18836a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov        if (row < mNumRows - 1) {
18936a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov            return desiredRowHeight;
19036a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov        } else {
19136a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov            final int residualHeight = availableHeight % mNumRows;
19236a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov            return desiredRowHeight + residualHeight;
19336a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov        }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void getRectForRow(Rect rect, int row) {
19736a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov        final int rowHeight = getRowHeight(row);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int top = mPaddingTop + row * rowHeight;
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        rect.set(mPaddingLeft,
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                top,
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                getWidth() - mPaddingRight,
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                top + rowHeight);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void ensureRectVisible() {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getRectForRow(mTempRect, mSelectedRow);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        requestRectangleOnScreen(mTempRect);
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21136a561b4ee35911fd6594c1592aab134be22f0f7Svetoslav Ganov    @Override
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch(event.getKeyCode()) {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_UP:
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mSelectedRow > 0) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSelectedRow--;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    invalidate();
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ensureRectVisible();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case KeyEvent.KEYCODE_DPAD_DOWN:
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mSelectedRow < (mNumRows - 1)) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSelectedRow++;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    invalidate();
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ensureRectVisible();
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return true;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void getFocusedRect(Rect r) {
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        getRectForRow(r, mSelectedRow);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onFocusChanged(boolean focused, int direction,
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect previouslyFocusedRect) {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onFocusChanged(focused, direction, previouslyFocusedRect);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (focused) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (direction) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case View.FOCUS_DOWN:
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSelectedRow = 0;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case View.FOCUS_UP:
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mSelectedRow = mNumRows - 1;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case View.FOCUS_LEFT:  // fall through
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case View.FOCUS_RIGHT:
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // set the row that is closest to the rect
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (previouslyFocusedRect != null) {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int y = previouslyFocusedRect.top
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                + (previouslyFocusedRect.height() / 2);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        int yPerRow = getHeight() / mNumRows;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSelectedRow = y / yPerRow;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSelectedRow = 0;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                default:
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // can't gleam any useful information about what internal
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // selection should be...
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invalidate();
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public String toString() {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mLabel != null) {
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mLabel;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return super.toString();
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
282