• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.inputmethod.keyboard;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.util.AttributeSet;
22 import android.view.MotionEvent;
23 import android.view.View;
24 
25 import com.android.inputmethod.latin.Constants;
26 import com.android.inputmethod.latin.R;
27 import com.android.inputmethod.latin.utils.CoordinateUtils;
28 
29 /**
30  * A view that renders a virtual {@link MoreKeysKeyboard}. It handles rendering of keys and
31  * detecting key presses and touch movements.
32  */
33 public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel {
34     private final int[] mCoordinates = CoordinateUtils.newInstance();
35 
36     protected final KeyDetector mKeyDetector;
37     private Controller mController = EMPTY_CONTROLLER;
38     protected KeyboardActionListener mListener;
39     private int mOriginX;
40     private int mOriginY;
41     private Key mCurrentKey;
42 
43     private int mActivePointerId;
44 
MoreKeysKeyboardView(final Context context, final AttributeSet attrs)45     public MoreKeysKeyboardView(final Context context, final AttributeSet attrs) {
46         this(context, attrs, R.attr.moreKeysKeyboardViewStyle);
47     }
48 
MoreKeysKeyboardView(final Context context, final AttributeSet attrs, final int defStyle)49     public MoreKeysKeyboardView(final Context context, final AttributeSet attrs,
50             final int defStyle) {
51         super(context, attrs, defStyle);
52 
53         final Resources res = context.getResources();
54         mKeyDetector = new MoreKeysDetector(
55                 res.getDimension(R.dimen.more_keys_keyboard_slide_allowance));
56     }
57 
58     @Override
onMeasure(final int widthMeasureSpec, final int heightMeasureSpec)59     protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
60         final Keyboard keyboard = getKeyboard();
61         if (keyboard != null) {
62             final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
63             final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
64             setMeasuredDimension(width, height);
65         } else {
66             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
67         }
68     }
69 
70     @Override
setKeyboard(final Keyboard keyboard)71     public void setKeyboard(final Keyboard keyboard) {
72         super.setKeyboard(keyboard);
73         mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
74                 -getPaddingTop() + getVerticalCorrection());
75     }
76 
77     @Override
showMoreKeysPanel(final View parentView, final Controller controller, final int pointX, final int pointY, final KeyboardActionListener listener)78     public void showMoreKeysPanel(final View parentView, final Controller controller,
79             final int pointX, final int pointY, final KeyboardActionListener listener) {
80         mController = controller;
81         mListener = listener;
82         final View container = getContainerView();
83         // The coordinates of panel's left-top corner in parentView's coordinate system.
84         final int x = pointX - getDefaultCoordX() - container.getPaddingLeft();
85         final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom();
86 
87         parentView.getLocationInWindow(mCoordinates);
88         // Ensure the horizontal position of the panel does not extend past the screen edges.
89         final int maxX = parentView.getMeasuredWidth() - container.getMeasuredWidth();
90         final int panelX = Math.max(0, Math.min(maxX, x)) + CoordinateUtils.x(mCoordinates);
91         final int panelY = y + CoordinateUtils.y(mCoordinates);
92         container.setX(panelX);
93         container.setY(panelY);
94 
95         mOriginX = x + container.getPaddingLeft();
96         mOriginY = y + container.getPaddingTop();
97         controller.onShowMoreKeysPanel(this);
98     }
99 
100     /**
101      * Returns the default x coordinate for showing this panel.
102      */
getDefaultCoordX()103     protected int getDefaultCoordX() {
104         return ((MoreKeysKeyboard)getKeyboard()).getDefaultCoordX();
105     }
106 
107     @Override
onDownEvent(final int x, final int y, final int pointerId, final long eventTime)108     public void onDownEvent(final int x, final int y, final int pointerId, final long eventTime) {
109         mActivePointerId = pointerId;
110         onMoveKeyInternal(x, y, pointerId);
111     }
112 
113     @Override
onMoveEvent(int x, int y, final int pointerId, long eventTime)114     public void onMoveEvent(int x, int y, final int pointerId, long eventTime) {
115         if (mActivePointerId != pointerId) {
116             return;
117         }
118         final boolean hasOldKey = (mCurrentKey != null);
119         onMoveKeyInternal(x, y, pointerId);
120         if (hasOldKey && mCurrentKey == null) {
121             // If the pointer has moved too far away from any target then cancel the panel.
122             mController.onCancelMoreKeysPanel(this);
123         }
124     }
125 
126     @Override
onUpEvent(final int x, final int y, final int pointerId, final long eventTime)127     public void onUpEvent(final int x, final int y, final int pointerId, final long eventTime) {
128         if (mCurrentKey != null && mActivePointerId == pointerId) {
129             updateReleaseKeyGraphics(mCurrentKey);
130             onCodeInput(mCurrentKey.getCode(), x, y);
131             mCurrentKey = null;
132         }
133     }
134 
135     /**
136      * Performs the specific action for this panel when the user presses a key on the panel.
137      */
onCodeInput(final int code, final int x, final int y)138     protected void onCodeInput(final int code, final int x, final int y) {
139         if (code == Constants.CODE_OUTPUT_TEXT) {
140             mListener.onTextInput(mCurrentKey.getOutputText());
141         } else if (code != Constants.CODE_UNSPECIFIED) {
142             mListener.onCodeInput(code, x, y);
143         }
144     }
145 
onMoveKeyInternal(int x, int y, int pointerId)146     private void onMoveKeyInternal(int x, int y, int pointerId) {
147         if (mActivePointerId != pointerId) {
148             // Ignore old pointers when newer pointer is active.
149             return;
150         }
151         final Key oldKey = mCurrentKey;
152         final Key newKey = mKeyDetector.detectHitKey(x, y);
153         if (newKey != oldKey) {
154             mCurrentKey = newKey;
155             invalidateKey(mCurrentKey);
156             if (oldKey != null) {
157                 updateReleaseKeyGraphics(oldKey);
158             }
159             if (newKey != null) {
160                 updatePressKeyGraphics(newKey);
161             }
162         }
163     }
164 
updateReleaseKeyGraphics(final Key key)165     private void updateReleaseKeyGraphics(final Key key) {
166         key.onReleased();
167         invalidateKey(key);
168     }
169 
updatePressKeyGraphics(final Key key)170     private void updatePressKeyGraphics(final Key key) {
171         key.onPressed();
172         invalidateKey(key);
173     }
174 
175     @Override
dismissMoreKeysPanel()176     public void dismissMoreKeysPanel() {
177         if (!isShowingInParent()) {
178             return;
179         }
180         mController.onDismissMoreKeysPanel(this);
181     }
182 
183     @Override
translateX(final int x)184     public int translateX(final int x) {
185         return x - mOriginX;
186     }
187 
188     @Override
translateY(final int y)189     public int translateY(final int y) {
190         return y - mOriginY;
191     }
192 
193     @Override
onTouchEvent(final MotionEvent me)194     public boolean onTouchEvent(final MotionEvent me) {
195         final int action = me.getActionMasked();
196         final long eventTime = me.getEventTime();
197         final int index = me.getActionIndex();
198         final int x = (int)me.getX(index);
199         final int y = (int)me.getY(index);
200         final int pointerId = me.getPointerId(index);
201         switch (action) {
202         case MotionEvent.ACTION_DOWN:
203         case MotionEvent.ACTION_POINTER_DOWN:
204             onDownEvent(x, y, pointerId, eventTime);
205             break;
206         case MotionEvent.ACTION_UP:
207         case MotionEvent.ACTION_POINTER_UP:
208             onUpEvent(x, y, pointerId, eventTime);
209             break;
210         case MotionEvent.ACTION_MOVE:
211             onMoveEvent(x, y, pointerId, eventTime);
212             break;
213         }
214         return true;
215     }
216 
217     @Override
getContainerView()218     public View getContainerView() {
219         return (View)getParent();
220     }
221 
222     @Override
isShowingInParent()223     public boolean isShowingInParent() {
224         return (getContainerView().getParent() != null);
225     }
226 }
227