diff options
Diffstat (limited to 'java/src')
9 files changed, 476 insertions, 500 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index b7584d4cd..54c3e7c91 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -28,29 +28,16 @@ import android.graphics.Rect; import android.graphics.Region; import android.graphics.Typeface; import android.graphics.drawable.Drawable; -import android.os.Message; import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; -import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; import com.android.inputmethod.keyboard.internal.KeyDrawParams; -import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; import com.android.inputmethod.keyboard.internal.KeyVisualAttributes; -import com.android.inputmethod.keyboard.internal.PreviewPlacerView; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.CoordinateUtils; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.StaticInnerHandlerWrapper; -import com.android.inputmethod.latin.StringUtils; -import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.ResearchLogger; @@ -60,30 +47,12 @@ import java.util.HashSet; * A view that renders a virtual {@link Keyboard}. * * @attr ref R.styleable#KeyboardView_keyBackground - * @attr ref R.styleable#KeyboardView_moreKeysLayout - * @attr ref R.styleable#KeyboardView_keyPreviewLayout - * @attr ref R.styleable#KeyboardView_keyPreviewOffset - * @attr ref R.styleable#KeyboardView_keyPreviewHeight - * @attr ref R.styleable#KeyboardView_keyPreviewLingerTimeout * @attr ref R.styleable#KeyboardView_keyLabelHorizontalPadding * @attr ref R.styleable#KeyboardView_keyHintLetterPadding * @attr ref R.styleable#KeyboardView_keyPopupHintLetterPadding * @attr ref R.styleable#KeyboardView_keyShiftedLetterHintPadding * @attr ref R.styleable#KeyboardView_keyTextShadowRadius * @attr ref R.styleable#KeyboardView_backgroundDimAlpha - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextSize - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextColor - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextOffset - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewColor - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewHorizontalPadding - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewVerticalPadding - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewRoundRadius - * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextLingerTimeout - * @attr ref R.styleable#KeyboardView_gesturePreviewTrailFadeoutStartDelay - * @attr ref R.styleable#KeyboardView_gesturePreviewTrailFadeoutDuration - * @attr ref R.styleable#KeyboardView_gesturePreviewTrailUpdateInterval - * @attr ref R.styleable#KeyboardView_gesturePreviewTrailColor - * @attr ref R.styleable#KeyboardView_gesturePreviewTrailWidth * @attr ref R.styleable#KeyboardView_verticalCorrection * @attr ref R.styleable#Keyboard_Key_keyTypeface * @attr ref R.styleable#Keyboard_Key_keyLetterSize @@ -103,10 +72,7 @@ import java.util.HashSet; * @attr ref R.styleable#Keyboard_Key_keyShiftedLetterHintActivatedColor * @attr ref R.styleable#Keyboard_Key_keyPreviewTextColor */ -public class KeyboardView extends View implements PointerTracker.DrawingProxy, - MoreKeysPanel.Controller { - private static final String TAG = KeyboardView.class.getSimpleName(); - +public class KeyboardView extends View { // XML attributes protected final KeyVisualAttributes mKeyVisualAttributes; private final int mKeyLabelHorizontalPadding; @@ -115,7 +81,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, private final float mKeyShiftedLetterHintPadding; private final float mKeyTextShadowRadius; protected final float mVerticalCorrection; - protected final int mMoreKeysLayout; protected final Drawable mKeyBackground; protected final Rect mKeyBackgroundPadding = new Rect(); private final int mBackgroundDimAlpha; @@ -135,51 +100,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, private Keyboard mKeyboard; protected final KeyDrawParams mKeyDrawParams = new KeyDrawParams(); - // Preview placer view - private final PreviewPlacerView mPreviewPlacerView; - private final int[] mOriginCoords = CoordinateUtils.newInstance(); - - // More keys panel (used by both more keys keyboard and more suggestions view) - // TODO: Consider extending to support multiple more keys panels - protected MoreKeysPanel mMoreKeysPanel; - - // Key preview - private static final int PREVIEW_ALPHA = 240; - private final int mKeyPreviewLayoutId; - private final int mKeyPreviewOffset; - private final int mKeyPreviewHeight; - private final SparseArray<TextView> mKeyPreviewTexts = CollectionUtils.newSparseArray(); - protected final KeyPreviewDrawParams mKeyPreviewDrawParams = new KeyPreviewDrawParams(); - private boolean mShowKeyPreviewPopup = true; - private int mKeyPreviewLingerTimeout; - - // Gesture floating preview text - // TODO: Make this parameter customizable by user via settings. - private int mGestureFloatingPreviewTextLingerTimeout; - - // Background state set - private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = { - { // STATE_MIDDLE - EMPTY_STATE_SET, - { R.attr.state_has_morekeys } - }, - { // STATE_LEFT - { R.attr.state_left_edge }, - { R.attr.state_left_edge, R.attr.state_has_morekeys } - }, - { // STATE_RIGHT - { R.attr.state_right_edge }, - { R.attr.state_right_edge, R.attr.state_has_morekeys } - } - }; - private static final int STATE_MIDDLE = 0; - private static final int STATE_LEFT = 1; - private static final int STATE_RIGHT = 2; - private static final int STATE_NORMAL = 0; - private static final int STATE_HAS_MOREKEYS = 1; - private static final int[] KEY_PREVIEW_BACKGROUND_DEFAULT_STATE = - KEY_PREVIEW_BACKGROUND_STATE_TABLE[STATE_MIDDLE][STATE_NORMAL]; - // Drawing /** True if the entire keyboard needs to be dimmed. */ private boolean mNeedsToDimEntireKeyboard; @@ -204,55 +124,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, private static final char[] KEY_LABEL_REFERENCE_CHAR = { 'M' }; private static final char[] KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR = { '8' }; - private final DrawingHandler mDrawingHandler = new DrawingHandler(this); - - public static class DrawingHandler extends StaticInnerHandlerWrapper<KeyboardView> { - private static final int MSG_DISMISS_KEY_PREVIEW = 0; - private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; - - public DrawingHandler(final KeyboardView outerInstance) { - super(outerInstance); - } - - @Override - public void handleMessage(final Message msg) { - final KeyboardView keyboardView = getOuterInstance(); - if (keyboardView == null) return; - final PointerTracker tracker = (PointerTracker) msg.obj; - switch (msg.what) { - case MSG_DISMISS_KEY_PREVIEW: - final TextView previewText = keyboardView.mKeyPreviewTexts.get(tracker.mPointerId); - if (previewText != null) { - previewText.setVisibility(INVISIBLE); - } - break; - case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: - keyboardView.mPreviewPlacerView.setGestureFloatingPreviewText(SuggestedWords.EMPTY); - break; - } - } - - public void dismissKeyPreview(final long delay, final PointerTracker tracker) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); - } - - public void cancelDismissKeyPreview(final PointerTracker tracker) { - removeMessages(MSG_DISMISS_KEY_PREVIEW, tracker); - } - - private void cancelAllDismissKeyPreviews() { - removeMessages(MSG_DISMISS_KEY_PREVIEW); - } - - public void dismissGestureFloatingPreviewText(final long delay) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); - } - - public void cancelAllMessages() { - cancelAllDismissKeyPreviews(); - } - } - public KeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } @@ -264,12 +135,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, R.styleable.KeyboardView, defStyle, R.style.KeyboardView); mKeyBackground = keyboardViewAttr.getDrawable(R.styleable.KeyboardView_keyBackground); mKeyBackground.getPadding(mKeyBackgroundPadding); - mKeyPreviewOffset = keyboardViewAttr.getDimensionPixelOffset( - R.styleable.KeyboardView_keyPreviewOffset, 0); - mKeyPreviewHeight = keyboardViewAttr.getDimensionPixelSize( - R.styleable.KeyboardView_keyPreviewHeight, 80); - mKeyPreviewLingerTimeout = keyboardViewAttr.getInt( - R.styleable.KeyboardView_keyPreviewLingerTimeout, 0); mKeyLabelHorizontalPadding = keyboardViewAttr.getDimensionPixelOffset( R.styleable.KeyboardView_keyLabelHorizontalPadding, 0); mKeyHintLetterPadding = keyboardViewAttr.getDimension( @@ -280,19 +145,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, R.styleable.KeyboardView_keyShiftedLetterHintPadding, 0); mKeyTextShadowRadius = keyboardViewAttr.getFloat( R.styleable.KeyboardView_keyTextShadowRadius, 0.0f); - mKeyPreviewLayoutId = keyboardViewAttr.getResourceId( - R.styleable.KeyboardView_keyPreviewLayout, 0); - if (mKeyPreviewLayoutId == 0) { - mShowKeyPreviewPopup = false; - } mVerticalCorrection = keyboardViewAttr.getDimension( R.styleable.KeyboardView_verticalCorrection, 0); - mMoreKeysLayout = keyboardViewAttr.getResourceId( - R.styleable.KeyboardView_moreKeysLayout, 0); mBackgroundDimAlpha = keyboardViewAttr.getInt( R.styleable.KeyboardView_backgroundDimAlpha, 0); - mGestureFloatingPreviewTextLingerTimeout = keyboardViewAttr.getInt( - R.styleable.KeyboardView_gestureFloatingPreviewTextLingerTimeout, 0); keyboardViewAttr.recycle(); final TypedArray keyAttr = context.obtainStyledAttributes(attrs, @@ -300,7 +156,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr); keyAttr.recycle(); - mPreviewPlacerView = new PreviewPlacerView(context, attrs); mPaint.setAntiAlias(true); } @@ -336,33 +191,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, return mKeyboard; } - /** - * Enables or disables the key feedback popup. This is a popup that shows a magnified - * version of the depressed key. By default the preview is enabled. - * @param previewEnabled whether or not to enable the key feedback preview - * @param delay the delay after which the preview is dismissed - * @see #isKeyPreviewPopupEnabled() - */ - public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { - mShowKeyPreviewPopup = previewEnabled; - mKeyPreviewLingerTimeout = delay; - } - - /** - * Returns the enabled state of the key feedback preview - * @return whether or not the key feedback preview is enabled - * @see #setKeyPreviewPopupEnabled(boolean, int) - */ - public boolean isKeyPreviewPopupEnabled() { - return mShowKeyPreviewPopup; - } - - public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail, - final boolean drawsGestureFloatingPreviewText) { - mPreviewPlacerView.setGesturePreviewMode( - drawsGesturePreviewTrail, drawsGestureFloatingPreviewText); - } - @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { if (mKeyboard != null) { @@ -465,6 +293,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, } } + // TODO: Move this code block to MainKeyboardView.onDraw // Overlay a dark rectangle to dim. if (mNeedsToDimEntireKeyboard) { paint.setColor(Color.BLACK); @@ -484,6 +313,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, mInvalidateAllKeys = false; } + // TODO: Move this method to MainKeyboardView. public void dimEntireKeyboard(final boolean dimmed) { final boolean needsRedrawing = mNeedsToDimEntireKeyboard != dimmed; mNeedsToDimEntireKeyboard = dimmed; @@ -801,200 +631,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, return paint; } - public void cancelAllMessages() { - mDrawingHandler.cancelAllMessages(); - } - - private TextView getKeyPreviewText(final int pointerId) { - TextView previewText = mKeyPreviewTexts.get(pointerId); - if (previewText != null) { - return previewText; - } - final Context context = getContext(); - if (mKeyPreviewLayoutId != 0) { - previewText = (TextView)LayoutInflater.from(context).inflate(mKeyPreviewLayoutId, null); - } else { - previewText = new TextView(context); - } - mKeyPreviewTexts.put(pointerId, previewText); - return previewText; - } - - private void dismissAllKeyPreviews() { - final int pointerCount = mKeyPreviewTexts.size(); - for (int id = 0; id < pointerCount; id++) { - final TextView previewText = mKeyPreviewTexts.get(id); - if (previewText != null) { - previewText.setVisibility(INVISIBLE); - } - } - PointerTracker.setReleasedKeyGraphicsToAllKeys(); - } - - @Override - public void dismissKeyPreview(final PointerTracker tracker) { - mDrawingHandler.dismissKeyPreview(mKeyPreviewLingerTimeout, tracker); - } - - private void addKeyPreview(final TextView keyPreview) { - locatePreviewPlacerView(); - mPreviewPlacerView.addView( - keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacerView, 0, 0)); - } - - private void locatePreviewPlacerView() { - if (mPreviewPlacerView.getParent() != null) { - return; - } - final int width = getWidth(); - final int height = getHeight(); - if (width == 0 || height == 0) { - // In transient state. - return; - } - getLocationInWindow(mOriginCoords); - final DisplayMetrics dm = getResources().getDisplayMetrics(); - if (CoordinateUtils.y(mOriginCoords) < dm.heightPixels / 4) { - // In transient state. - return; - } - final View rootView = getRootView(); - if (rootView == null) { - Log.w(TAG, "Cannot find root view"); - return; - } - final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content); - // Note: It'd be very weird if we get null by android.R.id.content. - if (windowContentView == null) { - Log.w(TAG, "Cannot find android.R.id.content view to add PreviewPlacerView"); - } else { - windowContentView.addView(mPreviewPlacerView); - mPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, width, height); - } - } - - @Override - public void showSlidingKeyInputPreview(final PointerTracker tracker) { - locatePreviewPlacerView(); - mPreviewPlacerView.showSlidingKeyInputPreview(tracker); - } - - @Override - public void dismissSlidingKeyInputPreview() { - mPreviewPlacerView.dismissSlidingKeyInputPreview(); - } - - public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) { - locatePreviewPlacerView(); - mPreviewPlacerView.setGestureFloatingPreviewText(suggestedWords); - } - - public void dismissGestureFloatingPreviewText() { - locatePreviewPlacerView(); - mDrawingHandler.dismissGestureFloatingPreviewText(mGestureFloatingPreviewTextLingerTimeout); - } - - @Override - public void showGesturePreviewTrail(final PointerTracker tracker, - final boolean isOldestTracker) { - locatePreviewPlacerView(); - mPreviewPlacerView.invalidatePointer(tracker, isOldestTracker); - } - - @Override - public void showKeyPreview(final PointerTracker tracker) { - final KeyPreviewDrawParams previewParams = mKeyPreviewDrawParams; - if (!mShowKeyPreviewPopup) { - previewParams.mPreviewVisibleOffset = -mKeyboard.mVerticalGap; - return; - } - - final TextView previewText = getKeyPreviewText(tracker.mPointerId); - // If the key preview has no parent view yet, add it to the ViewGroup which can place - // key preview absolutely in SoftInputWindow. - if (previewText.getParent() == null) { - addKeyPreview(previewText); - } - - mDrawingHandler.cancelDismissKeyPreview(tracker); - final Key key = tracker.getKey(); - // If key is invalid or IME is already closed, we must not show key preview. - // Trying to show key preview while root window is closed causes - // WindowManager.BadTokenException. - if (key == null) { - return; - } - - final KeyDrawParams drawParams = mKeyDrawParams; - previewText.setTextColor(drawParams.mPreviewTextColor); - final Drawable background = previewText.getBackground(); - if (background != null) { - background.setState(KEY_PREVIEW_BACKGROUND_DEFAULT_STATE); - background.setAlpha(PREVIEW_ALPHA); - } - final String label = key.isShiftedLetterActivated() ? key.mHintLabel : key.mLabel; - // What we show as preview should match what we show on a key top in onDraw(). - if (label != null) { - // TODO Should take care of temporaryShiftLabel here. - previewText.setCompoundDrawables(null, null, null, null); - if (StringUtils.codePointCount(label) > 1) { - previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, drawParams.mLetterSize); - previewText.setTypeface(Typeface.DEFAULT_BOLD); - } else { - previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, drawParams.mPreviewTextSize); - previewText.setTypeface(key.selectTypeface(drawParams)); - } - previewText.setText(label); - } else { - previewText.setCompoundDrawables(null, null, null, - key.getPreviewIcon(mKeyboard.mIconsSet)); - previewText.setText(null); - } - - previewText.measure( - ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - final int keyDrawWidth = key.getDrawWidth(); - final int previewWidth = previewText.getMeasuredWidth(); - final int previewHeight = mKeyPreviewHeight; - // The width and height of visible part of the key preview background. The content marker - // of the background 9-patch have to cover the visible part of the background. - previewParams.mPreviewVisibleWidth = previewWidth - previewText.getPaddingLeft() - - previewText.getPaddingRight(); - previewParams.mPreviewVisibleHeight = previewHeight - previewText.getPaddingTop() - - previewText.getPaddingBottom(); - // The distance between the top edge of the parent key and the bottom of the visible part - // of the key preview background. - previewParams.mPreviewVisibleOffset = mKeyPreviewOffset - previewText.getPaddingBottom(); - getLocationInWindow(mOriginCoords); - // The key preview is horizontally aligned with the center of the visible part of the - // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and - // the left/right background is used if such background is specified. - final int statePosition; - int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 - + CoordinateUtils.x(mOriginCoords); - if (previewX < 0) { - previewX = 0; - statePosition = STATE_LEFT; - } else if (previewX > getWidth() - previewWidth) { - previewX = getWidth() - previewWidth; - statePosition = STATE_RIGHT; - } else { - statePosition = STATE_MIDDLE; - } - // The key preview is placed vertically above the top edge of the parent key with an - // arbitrary offset. - final int previewY = key.mY - previewHeight + mKeyPreviewOffset - + CoordinateUtils.y(mOriginCoords); - - if (background != null) { - final int hasMoreKeys = (key.mMoreKeys != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL; - background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]); - } - ViewLayoutUtils.placeViewAt( - previewText, previewX, previewY, previewWidth, previewHeight); - previewText.setVisibility(VISIBLE); - } - /** * Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient * because the keyboard renders the keys to an off-screen buffer and an invalidate() only @@ -1014,7 +650,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, * @param key key in the attached {@link Keyboard}. * @see #invalidateAllKeys */ - @Override public void invalidateKey(final Key key) { if (mInvalidateAllKeys) return; if (key == null) return; @@ -1025,53 +660,15 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy, } public void closing() { - dismissAllKeyPreviews(); - cancelAllMessages(); - onCancelMoreKeysPanel(); mInvalidateAllKeys = true; - requestLayout(); - } - - @Override - public void onShowMoreKeysPanel(final MoreKeysPanel panel) { - if (isShowingMoreKeysPanel()) { - onDismissMoreKeysPanel(); - } - mMoreKeysPanel = panel; - mPreviewPlacerView.addView(mMoreKeysPanel.getContainerView()); - } - - public boolean isShowingMoreKeysPanel() { - return (mMoreKeysPanel != null); - } - - @Override - public void onCancelMoreKeysPanel() { - if (isShowingMoreKeysPanel()) { - mMoreKeysPanel.dismissMoreKeysPanel(); - } - } - - @Override - public boolean onDismissMoreKeysPanel() { - if (isShowingMoreKeysPanel()) { - mPreviewPlacerView.removeView(mMoreKeysPanel.getContainerView()); - mMoreKeysPanel = null; - return true; - } - return false; - } - - public void purgeKeyboardAndClosing() { mKeyboard = null; - closing(); + requestLayout(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); closing(); - mPreviewPlacerView.removeAllViews(); freeOffscreenBuffer(); } } diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 625575d53..83b37f1b1 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -32,13 +32,17 @@ import android.os.Message; import android.os.SystemClock; import android.preference.PreferenceManager; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.util.Log; +import android.util.SparseArray; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.inputmethod.InputMethodSubtype; +import android.widget.TextView; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; @@ -46,7 +50,10 @@ import com.android.inputmethod.annotations.ExternallyReferenced; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.KeyDrawParams; +import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; +import com.android.inputmethod.keyboard.internal.PreviewPlacerView; import com.android.inputmethod.keyboard.internal.TouchScreenRegulator; +import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.CoordinateUtils; import com.android.inputmethod.latin.DebugSettings; @@ -57,6 +64,7 @@ import com.android.inputmethod.latin.ResourceUtils; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SubtypeLocale; +import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.research.ResearchLogger; @@ -85,7 +93,13 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_longPressKeyTimeout * @attr ref R.styleable#MainKeyboardView_longPressShiftKeyTimeout * @attr ref R.styleable#MainKeyboardView_ignoreAltCodeKeyTimeout + * @attr ref R.styleable#MainKeyboardView_keyPreviewLayout + * @attr ref R.styleable#MainKeyboardView_keyPreviewOffset + * @attr ref R.styleable#MainKeyboardView_keyPreviewHeight + * @attr ref R.styleable#MainKeyboardView_keyPreviewLingerTimeout + * @attr ref R.styleable#MainKeyboardView_moreKeysKeyboardLayout * @attr ref R.styleable#MainKeyboardView_showMoreKeysKeyboardAtTouchPoint + * @attr ref R.styleable#MainKeyboardView_gestureFloatingPreviewTextLingerTimeout * @attr ref R.styleable#MainKeyboardView_gestureStaticTimeThresholdAfterFastTyping * @attr ref R.styleable#MainKeyboardView_gestureDetectFastMoveSpeedThreshold * @attr ref R.styleable#MainKeyboardView_gestureDynamicThresholdDecayDuration @@ -99,6 +113,7 @@ import java.util.WeakHashMap; * @attr ref R.styleable#MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration */ public final class MainKeyboardView extends KeyboardView implements PointerTracker.KeyEventHandler, + PointerTracker.DrawingProxy, MoreKeysPanel.Controller, TouchScreenRegulator.ProcessMotionEvent { private static final String TAG = MainKeyboardView.class.getSimpleName(); @@ -134,14 +149,36 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack private ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; private int mAltCodeKeyWhileTypingAnimAlpha = Constants.Color.ALPHA_OPAQUE; + // Preview placer view + private final PreviewPlacerView mPreviewPlacerView; + private final int[] mOriginCoords = CoordinateUtils.newInstance(); + + // Key preview + private static final int PREVIEW_ALPHA = 240; + private final int mKeyPreviewLayoutId; + private final int mKeyPreviewOffset; + private final int mKeyPreviewHeight; + private final SparseArray<TextView> mKeyPreviewTexts = CollectionUtils.newSparseArray(); + private final KeyPreviewDrawParams mKeyPreviewDrawParams = new KeyPreviewDrawParams(); + private boolean mShowKeyPreviewPopup = true; + private int mKeyPreviewLingerTimeout; + // More keys keyboard private final WeakHashMap<Key, MoreKeysPanel> mMoreKeysPanelCache = new WeakHashMap<Key, MoreKeysPanel>(); + private final int mMoreKeysLayout; private final boolean mConfigShowMoreKeysKeyboardAtTouchedPoint; + // More keys panel (used by both more keys keyboard and more suggestions view) + // TODO: Consider extending to support multiple more keys panels + private MoreKeysPanel mMoreKeysPanel; + + // Gesture floating preview text + // TODO: Make this parameter customizable by user via settings. + private int mGestureFloatingPreviewTextLingerTimeout; private final TouchScreenRegulator mTouchScreenRegulator; - protected KeyDetector mKeyDetector; + private KeyDetector mKeyDetector; private final boolean mHasDistinctMultitouch; private int mOldPointerCount = 1; private Key mOldKey; @@ -381,6 +418,57 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } } + private final DrawingHandler mDrawingHandler = new DrawingHandler(this); + + public static class DrawingHandler extends StaticInnerHandlerWrapper<MainKeyboardView> { + private static final int MSG_DISMISS_KEY_PREVIEW = 0; + private static final int MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1; + + public DrawingHandler(final MainKeyboardView outerInstance) { + super(outerInstance); + } + + @Override + public void handleMessage(final Message msg) { + final MainKeyboardView mainKeyboardView = getOuterInstance(); + if (mainKeyboardView == null) return; + final PointerTracker tracker = (PointerTracker) msg.obj; + switch (msg.what) { + case MSG_DISMISS_KEY_PREVIEW: + final TextView previewText = mainKeyboardView.mKeyPreviewTexts.get( + tracker.mPointerId); + if (previewText != null) { + previewText.setVisibility(INVISIBLE); + } + break; + case MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT: + mainKeyboardView.mPreviewPlacerView.setGestureFloatingPreviewText( + SuggestedWords.EMPTY); + break; + } + } + + public void dismissKeyPreview(final long delay, final PointerTracker tracker) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); + } + + public void cancelDismissKeyPreview(final PointerTracker tracker) { + removeMessages(MSG_DISMISS_KEY_PREVIEW, tracker); + } + + private void cancelAllDismissKeyPreviews() { + removeMessages(MSG_DISMISS_KEY_PREVIEW); + } + + public void dismissGestureFloatingPreviewText(final long delay) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT), delay); + } + + public void cancelAllMessages() { + cancelAllDismissKeyPreviews(); + } + } + public MainKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.mainKeyboardViewStyle); } @@ -402,38 +490,55 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack res, R.array.phantom_sudden_move_event_device_list)); PointerTracker.init(needsPhantomSuddenMoveEventHack); - final TypedArray a = context.obtainStyledAttributes( + final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); - mAutoCorrectionSpacebarLedEnabled = a.getBoolean( + mAutoCorrectionSpacebarLedEnabled = mainKeyboardViewAttr.getBoolean( R.styleable.MainKeyboardView_autoCorrectionSpacebarLedEnabled, false); - mAutoCorrectionSpacebarLedIcon = a.getDrawable( + mAutoCorrectionSpacebarLedIcon = mainKeyboardViewAttr.getDrawable( R.styleable.MainKeyboardView_autoCorrectionSpacebarLedIcon); - mSpacebarTextRatio = a.getFraction( + mSpacebarTextRatio = mainKeyboardViewAttr.getFraction( R.styleable.MainKeyboardView_spacebarTextRatio, 1, 1, 1.0f); - mSpacebarTextColor = a.getColor(R.styleable.MainKeyboardView_spacebarTextColor, 0); - mSpacebarTextShadowColor = a.getColor( + mSpacebarTextColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_spacebarTextColor, 0); + mSpacebarTextShadowColor = mainKeyboardViewAttr.getColor( R.styleable.MainKeyboardView_spacebarTextShadowColor, 0); - mLanguageOnSpacebarFinalAlpha = a.getInt( + mLanguageOnSpacebarFinalAlpha = mainKeyboardViewAttr.getInt( R.styleable.MainKeyboardView_languageOnSpacebarFinalAlpha, Constants.Color.ALPHA_OPAQUE); - final int languageOnSpacebarFadeoutAnimatorResId = a.getResourceId( + final int languageOnSpacebarFadeoutAnimatorResId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_languageOnSpacebarFadeoutAnimator, 0); - final int altCodeKeyWhileTypingFadeoutAnimatorResId = a.getResourceId( + final int altCodeKeyWhileTypingFadeoutAnimatorResId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeoutAnimator, 0); - final int altCodeKeyWhileTypingFadeinAnimatorResId = a.getResourceId( + final int altCodeKeyWhileTypingFadeinAnimatorResId = mainKeyboardViewAttr.getResourceId( R.styleable.MainKeyboardView_altCodeKeyWhileTypingFadeinAnimator, 0); - final float keyHysteresisDistance = a.getDimension( + final float keyHysteresisDistance = mainKeyboardViewAttr.getDimension( R.styleable.MainKeyboardView_keyHysteresisDistance, 0); - final float keyHysteresisDistanceForSlidingModifier = a.getDimension( + final float keyHysteresisDistanceForSlidingModifier = mainKeyboardViewAttr.getDimension( R.styleable.MainKeyboardView_keyHysteresisDistanceForSlidingModifier, 0); mKeyDetector = new KeyDetector( keyHysteresisDistance, keyHysteresisDistanceForSlidingModifier); - mKeyTimerHandler = new KeyTimerHandler(this, a); - mConfigShowMoreKeysKeyboardAtTouchedPoint = a.getBoolean( + mKeyTimerHandler = new KeyTimerHandler(this, mainKeyboardViewAttr); + mKeyPreviewOffset = mainKeyboardViewAttr.getDimensionPixelOffset( + R.styleable.MainKeyboardView_keyPreviewOffset, 0); + mKeyPreviewHeight = mainKeyboardViewAttr.getDimensionPixelSize( + R.styleable.MainKeyboardView_keyPreviewHeight, 0); + mKeyPreviewLingerTimeout = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_keyPreviewLingerTimeout, 0); + mKeyPreviewLayoutId = mainKeyboardViewAttr.getResourceId( + R.styleable.MainKeyboardView_keyPreviewLayout, 0); + if (mKeyPreviewLayoutId == 0) { + mShowKeyPreviewPopup = false; + } + mMoreKeysLayout = mainKeyboardViewAttr.getResourceId( + R.styleable.MainKeyboardView_moreKeysKeyboardLayout, 0); + mConfigShowMoreKeysKeyboardAtTouchedPoint = mainKeyboardViewAttr.getBoolean( R.styleable.MainKeyboardView_showMoreKeysKeyboardAtTouchedPoint, false); - PointerTracker.setParameters(a); - a.recycle(); + + mGestureFloatingPreviewTextLingerTimeout = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_gestureFloatingPreviewTextLingerTimeout, 0); + PointerTracker.setParameters(mainKeyboardViewAttr); + mainKeyboardViewAttr.recycle(); mLanguageOnSpacebarFadeoutAnimator = loadObjectAnimator( languageOnSpacebarFadeoutAnimatorResId, this); @@ -441,6 +546,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack altCodeKeyWhileTypingFadeoutAnimatorResId, this); mAltCodeKeyWhileTypingFadeinAnimator = loadObjectAnimator( altCodeKeyWhileTypingFadeinAnimatorResId, this); + + mPreviewPlacerView = new PreviewPlacerView(context, attrs); } private ObjectAnimator loadObjectAnimator(final int resId, final Object target) { @@ -538,6 +645,247 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack AccessibleKeyboardViewProxy.getInstance().setKeyboard(); } + /** + * Enables or disables the key feedback popup. This is a popup that shows a magnified + * version of the depressed key. By default the preview is enabled. + * @param previewEnabled whether or not to enable the key feedback preview + * @param delay the delay after which the preview is dismissed + * @see #isKeyPreviewPopupEnabled() + */ + public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { + mShowKeyPreviewPopup = previewEnabled; + mKeyPreviewLingerTimeout = delay; + } + + + private void locatePreviewPlacerView() { + if (mPreviewPlacerView.getParent() != null) { + return; + } + final int width = getWidth(); + final int height = getHeight(); + if (width == 0 || height == 0) { + // In transient state. + return; + } + getLocationInWindow(mOriginCoords); + final DisplayMetrics dm = getResources().getDisplayMetrics(); + if (CoordinateUtils.y(mOriginCoords) < dm.heightPixels / 4) { + // In transient state. + return; + } + final View rootView = getRootView(); + if (rootView == null) { + Log.w(TAG, "Cannot find root view"); + return; + } + final ViewGroup windowContentView = (ViewGroup)rootView.findViewById(android.R.id.content); + // Note: It'd be very weird if we get null by android.R.id.content. + if (windowContentView == null) { + Log.w(TAG, "Cannot find android.R.id.content view to add PreviewPlacerView"); + } else { + windowContentView.addView(mPreviewPlacerView); + mPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, width, height); + } + } + + /** + * Returns the enabled state of the key feedback preview + * @return whether or not the key feedback preview is enabled + * @see #setKeyPreviewPopupEnabled(boolean, int) + */ + public boolean isKeyPreviewPopupEnabled() { + return mShowKeyPreviewPopup; + } + + private void addKeyPreview(final TextView keyPreview) { + locatePreviewPlacerView(); + mPreviewPlacerView.addView( + keyPreview, ViewLayoutUtils.newLayoutParam(mPreviewPlacerView, 0, 0)); + } + + private TextView getKeyPreviewText(final int pointerId) { + TextView previewText = mKeyPreviewTexts.get(pointerId); + if (previewText != null) { + return previewText; + } + final Context context = getContext(); + if (mKeyPreviewLayoutId != 0) { + previewText = (TextView)LayoutInflater.from(context).inflate(mKeyPreviewLayoutId, null); + } else { + previewText = new TextView(context); + } + mKeyPreviewTexts.put(pointerId, previewText); + return previewText; + } + + private void dismissAllKeyPreviews() { + final int pointerCount = mKeyPreviewTexts.size(); + for (int id = 0; id < pointerCount; id++) { + final TextView previewText = mKeyPreviewTexts.get(id); + if (previewText != null) { + previewText.setVisibility(INVISIBLE); + } + } + PointerTracker.setReleasedKeyGraphicsToAllKeys(); + } + + // Background state set + private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = { + { // STATE_MIDDLE + EMPTY_STATE_SET, + { R.attr.state_has_morekeys } + }, + { // STATE_LEFT + { R.attr.state_left_edge }, + { R.attr.state_left_edge, R.attr.state_has_morekeys } + }, + { // STATE_RIGHT + { R.attr.state_right_edge }, + { R.attr.state_right_edge, R.attr.state_has_morekeys } + } + }; + private static final int STATE_MIDDLE = 0; + private static final int STATE_LEFT = 1; + private static final int STATE_RIGHT = 2; + private static final int STATE_NORMAL = 0; + private static final int STATE_HAS_MOREKEYS = 1; + private static final int[] KEY_PREVIEW_BACKGROUND_DEFAULT_STATE = + KEY_PREVIEW_BACKGROUND_STATE_TABLE[STATE_MIDDLE][STATE_NORMAL]; + + @Override + public void showKeyPreview(final PointerTracker tracker) { + final KeyPreviewDrawParams previewParams = mKeyPreviewDrawParams; + final Keyboard keyboard = getKeyboard(); + if (!mShowKeyPreviewPopup) { + previewParams.mPreviewVisibleOffset = -keyboard.mVerticalGap; + return; + } + + final TextView previewText = getKeyPreviewText(tracker.mPointerId); + // If the key preview has no parent view yet, add it to the ViewGroup which can place + // key preview absolutely in SoftInputWindow. + if (previewText.getParent() == null) { + addKeyPreview(previewText); + } + + mDrawingHandler.cancelDismissKeyPreview(tracker); + final Key key = tracker.getKey(); + // If key is invalid or IME is already closed, we must not show key preview. + // Trying to show key preview while root window is closed causes + // WindowManager.BadTokenException. + if (key == null) { + return; + } + + final KeyDrawParams drawParams = mKeyDrawParams; + previewText.setTextColor(drawParams.mPreviewTextColor); + final Drawable background = previewText.getBackground(); + if (background != null) { + background.setState(KEY_PREVIEW_BACKGROUND_DEFAULT_STATE); + background.setAlpha(PREVIEW_ALPHA); + } + final String label = key.isShiftedLetterActivated() ? key.mHintLabel : key.mLabel; + // What we show as preview should match what we show on a key top in onDraw(). + if (label != null) { + // TODO Should take care of temporaryShiftLabel here. + previewText.setCompoundDrawables(null, null, null, null); + if (StringUtils.codePointCount(label) > 1) { + previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, drawParams.mLetterSize); + previewText.setTypeface(Typeface.DEFAULT_BOLD); + } else { + previewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, drawParams.mPreviewTextSize); + previewText.setTypeface(key.selectTypeface(drawParams)); + } + previewText.setText(label); + } else { + previewText.setCompoundDrawables(null, null, null, + key.getPreviewIcon(keyboard.mIconsSet)); + previewText.setText(null); + } + + previewText.measure( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + final int keyDrawWidth = key.getDrawWidth(); + final int previewWidth = previewText.getMeasuredWidth(); + final int previewHeight = mKeyPreviewHeight; + // The width and height of visible part of the key preview background. The content marker + // of the background 9-patch have to cover the visible part of the background. + previewParams.mPreviewVisibleWidth = previewWidth - previewText.getPaddingLeft() + - previewText.getPaddingRight(); + previewParams.mPreviewVisibleHeight = previewHeight - previewText.getPaddingTop() + - previewText.getPaddingBottom(); + // The distance between the top edge of the parent key and the bottom of the visible part + // of the key preview background. + previewParams.mPreviewVisibleOffset = mKeyPreviewOffset - previewText.getPaddingBottom(); + getLocationInWindow(mOriginCoords); + // The key preview is horizontally aligned with the center of the visible part of the + // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and + // the left/right background is used if such background is specified. + final int statePosition; + int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 + + CoordinateUtils.x(mOriginCoords); + if (previewX < 0) { + previewX = 0; + statePosition = STATE_LEFT; + } else if (previewX > getWidth() - previewWidth) { + previewX = getWidth() - previewWidth; + statePosition = STATE_RIGHT; + } else { + statePosition = STATE_MIDDLE; + } + // The key preview is placed vertically above the top edge of the parent key with an + // arbitrary offset. + final int previewY = key.mY - previewHeight + mKeyPreviewOffset + + CoordinateUtils.y(mOriginCoords); + + if (background != null) { + final int hasMoreKeys = (key.mMoreKeys != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL; + background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[statePosition][hasMoreKeys]); + } + ViewLayoutUtils.placeViewAt( + previewText, previewX, previewY, previewWidth, previewHeight); + previewText.setVisibility(VISIBLE); + } + + @Override + public void dismissKeyPreview(final PointerTracker tracker) { + mDrawingHandler.dismissKeyPreview(mKeyPreviewLingerTimeout, tracker); + } + + @Override + public void showSlidingKeyInputPreview(final PointerTracker tracker) { + locatePreviewPlacerView(); + mPreviewPlacerView.showSlidingKeyInputPreview(tracker); + } + + @Override + public void dismissSlidingKeyInputPreview() { + mPreviewPlacerView.dismissSlidingKeyInputPreview(); + } + + public void setGesturePreviewMode(final boolean drawsGesturePreviewTrail, + final boolean drawsGestureFloatingPreviewText) { + mPreviewPlacerView.setGesturePreviewMode( + drawsGesturePreviewTrail, drawsGestureFloatingPreviewText); + } + + public void showGestureFloatingPreviewText(final SuggestedWords suggestedWords) { + locatePreviewPlacerView(); + mPreviewPlacerView.setGestureFloatingPreviewText(suggestedWords); + } + + public void dismissGestureFloatingPreviewText() { + locatePreviewPlacerView(); + mDrawingHandler.dismissGestureFloatingPreviewText(mGestureFloatingPreviewTextLingerTimeout); + } + + public void showGesturePreviewTrail(final PointerTracker tracker, + final boolean isOldestTracker) { + locatePreviewPlacerView(); + mPreviewPlacerView.invalidatePointer(tracker, isOldestTracker); + } + // Note that this method is called from a non-UI thread. public void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) { PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable); @@ -561,6 +909,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + mPreviewPlacerView.removeAllViews(); // Notify the research logger that the keyboard view has been detached. This is needed // to invalidate the reference of {@link MainKeyboardView} to null. if (ProductionFlag.IS_EXPERIMENTAL) { @@ -568,12 +917,6 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } } - @Override - public void cancelAllMessages() { - mKeyTimerHandler.cancelAllMessages(); - super.cancelAllMessages(); - } - private boolean openMoreKeysKeyboardIfRequired(final Key parentKey, final PointerTracker tracker) { // Check if we have a popup layout specified first. @@ -591,8 +934,7 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return onLongPress(parentKey, tracker); } - // This default implementation returns a more keys panel. - protected MoreKeysPanel onCreateMoreKeysPanel(final Key parentKey) { + private MoreKeysPanel onCreateMoreKeysPanel(final Key parentKey) { if (parentKey.mMoreKeys == null) { return null; } @@ -604,7 +946,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final MoreKeysKeyboardView moreKeysKeyboardView = (MoreKeysKeyboardView)container.findViewById(R.id.more_keys_keyboard_view); - final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder(container, parentKey, this) + final Keyboard moreKeysKeyboard = new MoreKeysKeyboard.Builder( + container, parentKey, this, mKeyPreviewDrawParams) .build(); moreKeysKeyboardView.setKeyboard(moreKeysKeyboard); container.measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -613,14 +956,13 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } /** - * Called when a key is long pressed. By default this will open more keys keyboard associated - * with this key. + * Called when a key is long pressed. * @param parentKey the key that was long pressed * @param tracker the pointer tracker which pressed the parent key * @return true if the long press is handled, false otherwise. Subclasses should call the * method on the base class if the subclass doesn't wish to handle the call. */ - protected boolean onLongPress(final Key parentKey, final PointerTracker tracker) { + private boolean onLongPress(final Key parentKey, final PointerTracker tracker) { if (ProductionFlag.IS_EXPERIMENTAL) { ResearchLogger.mainKeyboardView_onLongPress(); } @@ -697,6 +1039,38 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack return PointerTracker.isAnyInSlidingKeyInput(); } + @Override + public void onShowMoreKeysPanel(final MoreKeysPanel panel) { + if (isShowingMoreKeysPanel()) { + onDismissMoreKeysPanel(); + } + mMoreKeysPanel = panel; + mPreviewPlacerView.addView(mMoreKeysPanel.getContainerView()); + } + + public boolean isShowingMoreKeysPanel() { + return (mMoreKeysPanel != null); + } + + @Override + public void onCancelMoreKeysPanel() { + if (isShowingMoreKeysPanel()) { + mMoreKeysPanel.dismissMoreKeysPanel(); + } + PointerTracker.dismissAllMoreKeysPanels(); + } + + @Override + public boolean onDismissMoreKeysPanel() { + dimEntireKeyboard(false /* dimmed */); + if (isShowingMoreKeysPanel()) { + mPreviewPlacerView.removeView(mMoreKeysPanel.getContainerView()); + mMoreKeysPanel = null; + return true; + } + return false; + } + public int getPointerCount() { return mOldPointerCount; } @@ -846,25 +1220,20 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack eventTag + eventTime + "," + id + "," + x + "," + y + "," + size + "," + pressure); } + public void cancelAllMessages() { + mKeyTimerHandler.cancelAllMessages(); + mDrawingHandler.cancelAllMessages(); + } + @Override public void closing() { + dismissAllKeyPreviews(); + cancelAllMessages(); super.closing(); onCancelMoreKeysPanel(); mMoreKeysPanelCache.clear(); } - @Override - public void onCancelMoreKeysPanel() { - super.onCancelMoreKeysPanel(); - PointerTracker.dismissAllMoreKeysPanels(); - } - - @Override - public boolean onDismissMoreKeysPanel() { - dimEntireKeyboard(false /* dimmed */); - return super.onDismissMoreKeysPanel(); - } - /** * Receives hover events from the input framework. * diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java index 3826a39a4..5c15c4aa9 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -21,6 +21,7 @@ import android.graphics.drawable.Drawable; import android.view.View; import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; import com.android.inputmethod.keyboard.internal.KeyboardBuilder; import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.keyboard.internal.KeyboardParams; @@ -262,9 +263,11 @@ public final class MoreKeysKeyboard extends Keyboard { * @param containerView the container of {@link MoreKeysKeyboardView}. * @param parentKey the {@link Key} that invokes more keys keyboard. * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey. + * @param keyPreviewDrawParams the parameter to place key preview. */ public Builder(final View containerView, final Key parentKey, - final KeyboardView parentKeyboardView) { + final MainKeyboardView parentKeyboardView, + final KeyPreviewDrawParams keyPreviewDrawParams) { super(containerView.getContext(), new MoreKeysKeyboardParams()); final Keyboard parentKeyboard = parentKeyboardView.getKeyboard(); load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId); @@ -285,8 +288,8 @@ public final class MoreKeysKeyboard extends Keyboard { // left/right/top paddings. The bottom paddings of both backgrounds don't need to // be considered because the vertical positions of both backgrounds were already // adjusted with their bottom paddings deducted. - width = parentKeyboardView.mKeyPreviewDrawParams.mPreviewVisibleWidth; - height = parentKeyboardView.mKeyPreviewDrawParams.mPreviewVisibleHeight + width = keyPreviewDrawParams.mPreviewVisibleWidth; + height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap; } else { width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth); diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java index 8a5b7dad5..0d42ab2fe 100644 --- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java @@ -53,7 +53,6 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel final Resources res = context.getResources(); mKeyDetector = new MoreKeysDetector( res.getDimension(R.dimen.more_keys_keyboard_slide_allowance)); - setKeyPreviewPopupEnabled(false, 0); } @Override @@ -76,13 +75,6 @@ public class MoreKeysKeyboardView extends KeyboardView implements MoreKeysPanel } @Override - public void setKeyPreviewPopupEnabled(final boolean previewEnabled, final int delay) { - // More keys keyboard needs no pop-up key preview displayed, so we pass always false with a - // delay of 0. The delay does not matter actually since the popup is not shown anyway. - super.setKeyPreviewPopupEnabled(false, 0); - } - - @Override public void showMoreKeysPanel(final View parentView, final Controller controller, final int pointX, final int pointY, final KeyboardActionListener listener) { mController = controller; diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java index aed23a4db..897d856c8 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureFloatingPreviewText.java @@ -34,6 +34,14 @@ import com.android.inputmethod.latin.SuggestedWords; /** * The class for single gesture preview text. The class for multiple gesture preview text will be * derived from it. + * + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextSize + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextColor + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextOffset + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewColor + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewHorizontalPadding + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewVerticalPadding + * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewRoundRadius */ public class GestureFloatingPreviewText extends AbstractDrawingPreview { private static final class GesturePreviewTextParams { @@ -49,21 +57,21 @@ public class GestureFloatingPreviewText extends AbstractDrawingPreview { private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' }; - public GesturePreviewTextParams(final TypedArray keyboardViewAttr) { - mGesturePreviewTextSize = keyboardViewAttr.getDimensionPixelSize( - R.styleable.KeyboardView_gestureFloatingPreviewTextSize, 0); - mGesturePreviewTextColor = keyboardViewAttr.getColor( - R.styleable.KeyboardView_gestureFloatingPreviewTextColor, 0); - mGesturePreviewTextOffset = keyboardViewAttr.getDimensionPixelOffset( - R.styleable.KeyboardView_gestureFloatingPreviewTextOffset, 0); - mGesturePreviewColor = keyboardViewAttr.getColor( - R.styleable.KeyboardView_gestureFloatingPreviewColor, 0); - mGesturePreviewHorizontalPadding = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_gestureFloatingPreviewHorizontalPadding, 0.0f); - mGesturePreviewVerticalPadding = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_gestureFloatingPreviewVerticalPadding, 0.0f); - mGesturePreviewRoundRadius = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_gestureFloatingPreviewRoundRadius, 0.0f); + public GesturePreviewTextParams(final TypedArray mainKeyboardViewAttr) { + mGesturePreviewTextSize = mainKeyboardViewAttr.getDimensionPixelSize( + R.styleable.MainKeyboardView_gestureFloatingPreviewTextSize, 0); + mGesturePreviewTextColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_gestureFloatingPreviewTextColor, 0); + mGesturePreviewTextOffset = mainKeyboardViewAttr.getDimensionPixelOffset( + R.styleable.MainKeyboardView_gestureFloatingPreviewTextOffset, 0); + mGesturePreviewColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_gestureFloatingPreviewColor, 0); + mGesturePreviewHorizontalPadding = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_gestureFloatingPreviewHorizontalPadding, 0.0f); + mGesturePreviewVerticalPadding = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_gestureFloatingPreviewVerticalPadding, 0.0f); + mGesturePreviewRoundRadius = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_gestureFloatingPreviewRoundRadius, 0.0f); final Paint textPaint = new Paint(); textPaint.setAntiAlias(true); diff --git a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java index 9f6945da5..a74c3236b 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GesturePreviewTrail.java @@ -25,6 +25,13 @@ import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.ResizableIntArray; +/* + * @attr ref R.styleable#MainKeyboardView_gesturePreviewTrailFadeoutStartDelay + * @attr ref R.styleable#MainKeyboardView_gesturePreviewTrailFadeoutDuration + * @attr ref R.styleable#MainKeyboardView_gesturePreviewTrailUpdateInterval + * @attr ref R.styleable#MainKeyboardView_gesturePreviewTrailColor + * @attr ref R.styleable#MainKeyboardView_gesturePreviewTrailWidth + */ final class GesturePreviewTrail { private static final int DEFAULT_CAPACITY = GestureStrokeWithPreviewPoints.PREVIEW_CAPACITY; @@ -46,20 +53,20 @@ final class GesturePreviewTrail { public final int mTrailLingerDuration; - public Params(final TypedArray keyboardViewAttr) { - mTrailColor = keyboardViewAttr.getColor( - R.styleable.KeyboardView_gesturePreviewTrailColor, 0); - mTrailStartWidth = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_gesturePreviewTrailStartWidth, 0.0f); - mTrailEndWidth = keyboardViewAttr.getDimension( - R.styleable.KeyboardView_gesturePreviewTrailEndWidth, 0.0f); - mFadeoutStartDelay = keyboardViewAttr.getInt( - R.styleable.KeyboardView_gesturePreviewTrailFadeoutStartDelay, 0); - mFadeoutDuration = keyboardViewAttr.getInt( - R.styleable.KeyboardView_gesturePreviewTrailFadeoutDuration, 0); + public Params(final TypedArray mainKeyboardViewAttr) { + mTrailColor = mainKeyboardViewAttr.getColor( + R.styleable.MainKeyboardView_gesturePreviewTrailColor, 0); + mTrailStartWidth = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_gesturePreviewTrailStartWidth, 0.0f); + mTrailEndWidth = mainKeyboardViewAttr.getDimension( + R.styleable.MainKeyboardView_gesturePreviewTrailEndWidth, 0.0f); + mFadeoutStartDelay = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_gesturePreviewTrailFadeoutStartDelay, 0); + mFadeoutDuration = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_gesturePreviewTrailFadeoutDuration, 0); mTrailLingerDuration = mFadeoutStartDelay + mFadeoutDuration; - mUpdateInterval = keyboardViewAttr.getInt( - R.styleable.KeyboardView_gesturePreviewTrailUpdateInterval, 0); + mUpdateInterval = mainKeyboardViewAttr.getInt( + R.styleable.MainKeyboardView_gesturePreviewTrailUpdateInterval, 0); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java index 7c87467bb..4471cd0fe 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java @@ -100,13 +100,13 @@ public final class PreviewPlacerView extends RelativeLayout { super(context); setWillNotDraw(false); - final TypedArray keyboardViewAttr = context.obtainStyledAttributes( - attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView); + final TypedArray mainKeyboardViewAttr = context.obtainStyledAttributes( + attrs, R.styleable.MainKeyboardView, defStyle, R.style.MainKeyboardView); // TODO: mGestureFloatingPreviewText could be an instance of GestureFloatingPreviewText or // MultiGesturePreviewText, depending on the user's choice in the settings. - mGestureFloatingPreviewText = new GestureFloatingPreviewText(keyboardViewAttr, context); - mGesturePreviewTrailParams = new Params(keyboardViewAttr); - keyboardViewAttr.recycle(); + mGestureFloatingPreviewText = new GestureFloatingPreviewText(mainKeyboardViewAttr, context); + mGesturePreviewTrailParams = new Params(mainKeyboardViewAttr); + mainKeyboardViewAttr.recycle(); mDrawingHandler = new DrawingHandler(this, mGesturePreviewTrailParams); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d9e63da1b..75bf3f29e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1617,7 +1617,7 @@ public final class LatinIME extends InputMethodService implements KeyboardAction private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords, final boolean dismissGestureFloatingPreviewText) { showSuggestionStrip(suggestedWords, null); - final KeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); + final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView(); mainKeyboardView.showGestureFloatingPreviewText(suggestedWords); if (dismissGestureFloatingPreviewText) { mainKeyboardView.dismissGestureFloatingPreviewText(); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 14bb95b3c..5b440c368 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -52,7 +52,7 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.keyboard.KeyboardView; +import com.android.inputmethod.keyboard.MainKeyboardView; import com.android.inputmethod.keyboard.MoreKeysPanel; import com.android.inputmethod.keyboard.ViewLayoutUtils; import com.android.inputmethod.latin.AutoCorrection; @@ -81,7 +81,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick static final boolean DBG = LatinImeLogger.sDBG; private final ViewGroup mSuggestionsStrip; - KeyboardView mKeyboardView; + MainKeyboardView mMainKeyboardView; private final View mMoreSuggestionsContainer; private final MoreSuggestionsView mMoreSuggestionsView; @@ -610,7 +610,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick */ public void setListener(final Listener listener, final View inputView) { mListener = listener; - mKeyboardView = (KeyboardView)inputView.findViewById(R.id.keyboard_view); + mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view); } public void setSuggestions(final SuggestedWords suggestedWords) { @@ -676,13 +676,13 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick new MoreKeysPanel.Controller() { @Override public boolean onDismissMoreKeysPanel() { - mKeyboardView.dimEntireKeyboard(false /* dimmed */); - return mKeyboardView.onDismissMoreKeysPanel(); + mMainKeyboardView.dimEntireKeyboard(false /* dimmed */); + return mMainKeyboardView.onDismissMoreKeysPanel(); } @Override public void onShowMoreKeysPanel(MoreKeysPanel panel) { - mKeyboardView.onShowMoreKeysPanel(panel); + mMainKeyboardView.onShowMoreKeysPanel(panel); } @Override @@ -728,7 +728,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING; mOriginX = mLastX; mOriginY = mLastY; - mKeyboardView.dimEntireKeyboard(true /* dimmed */); + mMainKeyboardView.dimEntireKeyboard(true /* dimmed */); for (int i = 0; i < params.mSuggestionsCountInStrip; i++) { mWords.get(i).setPressed(false); } |