MoreKeysKeyboardView.java revision ac69ab400d1ea4f90b4ca24486d62212decf1069
1ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka/*
2ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project
3ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *
4ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License");
5ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * you may not use this file except in compliance with the License.
6ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * You may obtain a copy of the License at
7ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *
8ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *      http://www.apache.org/licenses/LICENSE-2.0
9ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka *
10ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software
11ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS,
12ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * See the License for the specific language governing permissions and
14ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka * limitations under the License.
15ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka */
16ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
17ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokapackage com.android.inputmethod.keyboard;
18ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
19ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.content.Context;
20ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.content.res.Resources;
21ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.util.AttributeSet;
2235580bad6f3da3b204653825bbb6871563e70728Tom Ouyangimport android.view.MotionEvent;
23ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaokaimport android.view.View;
24ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
25ac78633be28e8990fc3b3a8de192c80966e746e3Tadashi G. Takaokaimport com.android.inputmethod.latin.Constants;
26359c35e0f6e534d096efc1d9f2ff585139e3b3acTadashi G. Takaokaimport com.android.inputmethod.latin.CoordinateUtils;
27e07b51e7c65220ac183546103010dd617d164f60Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
28e07b51e7c65220ac183546103010dd617d164f60Tadashi G. Takaoka
29ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka/**
302affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and
312affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka * detecting key presses and touch movements.
32ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka */
3335580bad6f3da3b204653825bbb6871563e70728Tom Ouyangpublic class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel {
34359c35e0f6e534d096efc1d9f2ff585139e3b3acTadashi G. Takaoka    private final int[] mCoordinates = CoordinateUtils.newInstance();
35ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
3663c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    private final KeyDetector mKeyDetector;
37f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka    private Controller mController;
3835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    protected KeyboardActionListener mListener;
39ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    private int mOriginX;
40ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    private int mOriginY;
4135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private Key mCurrentKey;
4263c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka
4335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private int mActivePointerId;
44ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
45bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public MoreKeysKeyboardView(final Context context, final AttributeSet attrs) {
462affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka        this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
47ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    }
48ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
49bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public MoreKeysKeyboardView(final Context context, final AttributeSet attrs,
50bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka            final int defStyle) {
51ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka        super(context, attrs, defStyle);
52ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
53ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka        final Resources res = context.getResources();
5450e1073e11240fe51b3baf0e2ed80dac0d9f001dTadashi G. Takaoka        mKeyDetector = new MoreKeysDetector(
552affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka                res.getDimension(R.dimen.more_keys_keyboard_slide_allowance));
56240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard        setKeyPreviewPopupEnabled(false, 0);
57ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    }
58ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
59ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    @Override
60bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
6138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        final Keyboard keyboard = getKeyboard();
6238f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        if (keyboard != null) {
638da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
648da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka            final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
6538f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka            setMeasuredDimension(width, height);
6638f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        } else {
6738f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
6838f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka        }
6938f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka    }
7038f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka
7138f55b36c3992a580cf7e20668b1eb72a4eb2431Tadashi G. Takaoka    @Override
72bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public void setKeyboard(final Keyboard keyboard) {
7363c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        super.setKeyboard(keyboard);
7463c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
7563c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka                -getPaddingTop() + mVerticalCorrection);
7663c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    }
7763c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka
7863c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    @Override
79bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) {
802affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka        // More keys keyboard needs no pop-up key preview displayed, so we pass always false with a
81240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard        // delay of 0. The delay does not matter actually since the popup is not shown anyway.
82240297d0ee186b14e795016e9b1bd168c8d8acf8Jean Chalard        super.setKeyPreviewPopupEnabled(false, 0);
83f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka    }
84f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka
85f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka    @Override
86bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public void showMoreKeysPanel(final View parentView, final Controller controller,
87fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang            final int pointX, final int pointY, final KeyboardActionListener listener) {
88f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka        mController = controller;
89f44a01b40852dde2363a061cdc7df2ef4cb59aadTadashi G. Takaoka        mListener = listener;
90fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        final View container = getContainerView();
91bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        // The coordinates of panel's left-top corner in parentView's coordinate system.
9235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int x = pointX - getDefaultCoordX() - container.getPaddingLeft();
937ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka        final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom();
94ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
95bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        parentView.getLocationInWindow(mCoordinates);
96fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        // Ensure the horizontal position of the panel does not extend past the screen edges.
97fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        final int maxX = parentView.getMeasuredWidth() - container.getMeasuredWidth();
98be68b41ccb1a16201c3b91f1576a731f7715aaf6Tom Ouyang        final int panelX = Math.max(0, Math.min(maxX, x)) + CoordinateUtils.x(mCoordinates);
99fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        final int panelY = y + CoordinateUtils.y(mCoordinates);
100fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        container.setX(panelX);
101fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        container.setY(panelY);
102ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka
103bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        mOriginX = x + container.getPaddingLeft();
104bcbaffd9dd950c6b82c682a742c93f9319d908f5Tadashi G. Takaoka        mOriginY = y + container.getPaddingTop();
105fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        controller.onShowMoreKeysPanel(this);
106f3f3189adbce15d609d5e06632f8e0630db890d1Tadashi G. Takaoka    }
107f3f3189adbce15d609d5e06632f8e0630db890d1Tadashi G. Takaoka
10835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    /**
10935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     * Returns the default x coordinate for showing this panel.
11035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     */
11135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    protected int getDefaultCoordX() {
11235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        return ((MoreKeysKeyboard)getKeyboard()).getDefaultCoordX();
11335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
11435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
11535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
11635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void onDownEvent(final int x, final int y, final int pointerId, final long eventTime) {
11735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        mActivePointerId = pointerId;
11835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        onMoveKeyInternal(x, y, pointerId);
11935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
12035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
12135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
12235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void onMoveEvent(int x, int y, final int pointerId, long eventTime) {
123ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        if (mActivePointerId != pointerId) {
124ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang            return;
125ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
126ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        final boolean hasOldKey = (mCurrentKey != null);
12735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        onMoveKeyInternal(x, y, pointerId);
128ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        if (hasOldKey && mCurrentKey == null) {
129ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang            // If the pointer has moved too far away from any target then cancel the panel.
130ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang            mController.onCancelMoreKeysPanel();
131ac69ab400d1ea4f90b4ca24486d62212decf1069Tom Ouyang        }
13235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
13335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
13435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
13535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void onUpEvent(final int x, final int y, final int pointerId, final long eventTime) {
13635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (mCurrentKey != null && mActivePointerId == pointerId) {
13735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            updateReleaseKeyGraphics(mCurrentKey);
13835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onCodeInput(mCurrentKey.mCode, x, y);
13935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mCurrentKey = null;
14035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
14135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
14235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
14335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    /**
14435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     * Performs the specific action for this panel when the user presses a key on the panel.
14535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang     */
14635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    protected void onCodeInput(final int code, final int x, final int y) {
14735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (code == Constants.CODE_OUTPUT_TEXT) {
14835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mListener.onTextInput(mCurrentKey.getOutputText());
14935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        } else if (code != Constants.CODE_UNSPECIFIED) {
15035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mListener.onCodeInput(code, x, y);
15135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
15235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
15335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
15435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private void onMoveKeyInternal(int x, int y, int pointerId) {
15535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (mActivePointerId != pointerId) {
15635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            // Ignore old pointers when newer pointer is active.
15735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            return;
15835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
15935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final Key oldKey = mCurrentKey;
16035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final Key newKey = mKeyDetector.detectHitKey(x, y);
16135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        if (newKey != oldKey) {
16235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            mCurrentKey = newKey;
16335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            invalidateKey(mCurrentKey);
16435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            if (oldKey != null) {
16535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang                updateReleaseKeyGraphics(oldKey);
16635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            }
16735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            if (newKey != null) {
16835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang                updatePressKeyGraphics(newKey);
16935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            }
17035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
17135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
17235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
17335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private void updateReleaseKeyGraphics(final Key key) {
17435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        key.onReleased();
17535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        invalidateKey(key);
17635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
17735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
17835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    private void updatePressKeyGraphics(final Key key) {
17935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        key.onPressed();
18035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        invalidateKey(key);
18135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
18235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
183ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    @Override
1849d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka    public boolean dismissMoreKeysPanel() {
185fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        if (mController == null) return false;
186fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        return mController.onDismissMoreKeysPanel();
1879ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka    }
1889ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka
1899ec80d9d89eb599329c354451acdc482cc3de836Tadashi G. Takaoka    @Override
190bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public int translateX(final int x) {
19163c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        return x - mOriginX;
19263c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    }
19363c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka
19463c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka    @Override
195bc464e2952e102219f0b977fc1e9140ad5bd03e4Tadashi G. Takaoka    public int translateY(final int y) {
19663c233ab9f50d844be6e52e382c6664475606760Tadashi G. Takaoka        return y - mOriginY;
197ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka    }
198fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
199fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    @Override
20035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public boolean onTouchEvent(final MotionEvent me) {
20135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int action = me.getActionMasked();
20235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final long eventTime = me.getEventTime();
20335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int index = me.getActionIndex();
20435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int x = (int)me.getX(index);
20535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int y = (int)me.getY(index);
20635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        final int pointerId = me.getPointerId(index);
20735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        processMotionEvent(action, x, y, pointerId, eventTime);
20835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        return true;
20935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
21035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
21135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    public void processMotionEvent(final int action, final int x, final int y,
21235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            final int pointerId, final long eventTime) {
21335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        switch (action) {
21435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_DOWN:
21535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_POINTER_DOWN:
21635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onDownEvent(x, y, pointerId, eventTime);
21735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            break;
21835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_UP:
21935580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_POINTER_UP:
22035580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onUpEvent(x, y, pointerId, eventTime);
22135580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            break;
22235580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        case MotionEvent.ACTION_MOVE:
22335580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            onMoveEvent(x, y, pointerId, eventTime);
22435580bad6f3da3b204653825bbb6871563e70728Tom Ouyang            break;
22535580bad6f3da3b204653825bbb6871563e70728Tom Ouyang        }
22635580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    }
22735580bad6f3da3b204653825bbb6871563e70728Tom Ouyang
22835580bad6f3da3b204653825bbb6871563e70728Tom Ouyang    @Override
229fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    public View getContainerView() {
230fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        return (View)getParent();
231fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    }
232fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang
233fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    @Override
234fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    public boolean isShowingInParent() {
235fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang        return (getContainerView().getParent() != null);
236fa2d543785c52f639ad3157c57420f58a199c550Tom Ouyang    }
237ff082d081f3ea18ff0b9b22126ee4a86504cf83cTadashi G. Takaoka}
238