• 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.CoordinateUtils;
27 import com.android.inputmethod.latin.R;
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;
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();
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.mCode, 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 boolean dismissMoreKeysPanel() {
177         if (mController == null) return false;
178         return mController.onDismissMoreKeysPanel();
179     }
180 
181     @Override
translateX(final int x)182     public int translateX(final int x) {
183         return x - mOriginX;
184     }
185 
186     @Override
translateY(final int y)187     public int translateY(final int y) {
188         return y - mOriginY;
189     }
190 
191     @Override
onTouchEvent(final MotionEvent me)192     public boolean onTouchEvent(final MotionEvent me) {
193         final int action = me.getActionMasked();
194         final long eventTime = me.getEventTime();
195         final int index = me.getActionIndex();
196         final int x = (int)me.getX(index);
197         final int y = (int)me.getY(index);
198         final int pointerId = me.getPointerId(index);
199         processMotionEvent(action, x, y, pointerId, eventTime);
200         return true;
201     }
202 
processMotionEvent(final int action, final int x, final int y, final int pointerId, final long eventTime)203     public void processMotionEvent(final int action, final int x, final int y,
204             final int pointerId, final long eventTime) {
205         switch (action) {
206         case MotionEvent.ACTION_DOWN:
207         case MotionEvent.ACTION_POINTER_DOWN:
208             onDownEvent(x, y, pointerId, eventTime);
209             break;
210         case MotionEvent.ACTION_UP:
211         case MotionEvent.ACTION_POINTER_UP:
212             onUpEvent(x, y, pointerId, eventTime);
213             break;
214         case MotionEvent.ACTION_MOVE:
215             onMoveEvent(x, y, pointerId, eventTime);
216             break;
217         }
218     }
219 
220     @Override
getContainerView()221     public View getContainerView() {
222         return (View)getParent();
223     }
224 
225     @Override
isShowingInParent()226     public boolean isShowingInParent() {
227         return (getContainerView().getParent() != null);
228     }
229 }
230