Home | History | Annotate | Download | only in suggestions
      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.latin.suggestions;
     18 
     19 import android.content.Context;
     20 import android.content.res.Resources;
     21 import android.util.AttributeSet;
     22 import android.view.Gravity;
     23 import android.view.MotionEvent;
     24 import android.view.View;
     25 import android.widget.PopupWindow;
     26 
     27 import com.android.inputmethod.keyboard.KeyDetector;
     28 import com.android.inputmethod.keyboard.Keyboard;
     29 import com.android.inputmethod.keyboard.KeyboardActionListener;
     30 import com.android.inputmethod.keyboard.KeyboardView;
     31 import com.android.inputmethod.keyboard.MoreKeysDetector;
     32 import com.android.inputmethod.keyboard.MoreKeysPanel;
     33 import com.android.inputmethod.keyboard.PointerTracker;
     34 import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
     35 import com.android.inputmethod.keyboard.PointerTracker.KeyEventHandler;
     36 import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
     37 import com.android.inputmethod.latin.R;
     38 
     39 /**
     40  * A view that renders a virtual {@link MoreSuggestions}. It handles rendering of keys and detecting
     41  * key presses and touch movements.
     42  */
     43 public final class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
     44     private final int[] mCoordinates = new int[2];
     45 
     46     final KeyDetector mModalPanelKeyDetector;
     47     private final KeyDetector mSlidingPanelKeyDetector;
     48 
     49     private Controller mController;
     50     KeyboardActionListener mListener;
     51     private int mOriginX;
     52     private int mOriginY;
     53 
     54     static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter();
     55 
     56     final KeyboardActionListener mSuggestionsPaneListener =
     57             new KeyboardActionListener.Adapter() {
     58         @Override
     59         public void onPressKey(int primaryCode) {
     60             mListener.onPressKey(primaryCode);
     61         }
     62 
     63         @Override
     64         public void onReleaseKey(int primaryCode, boolean withSliding) {
     65             mListener.onReleaseKey(primaryCode, withSliding);
     66         }
     67 
     68         @Override
     69         public void onCodeInput(int primaryCode, int x, int y) {
     70             final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE;
     71             if (index >= 0 && index < SuggestionStripView.MAX_SUGGESTIONS) {
     72                 mListener.onCustomRequest(index);
     73             }
     74         }
     75 
     76         @Override
     77         public void onCancelInput() {
     78             mListener.onCancelInput();
     79         }
     80     };
     81 
     82     public MoreSuggestionsView(Context context, AttributeSet attrs) {
     83         this(context, attrs, R.attr.moreSuggestionsViewStyle);
     84     }
     85 
     86     public MoreSuggestionsView(Context context, AttributeSet attrs, int defStyle) {
     87         super(context, attrs, defStyle);
     88 
     89         final Resources res = context.getResources();
     90         mModalPanelKeyDetector = new KeyDetector(/* keyHysteresisDistance */ 0);
     91         mSlidingPanelKeyDetector = new MoreKeysDetector(
     92                 res.getDimension(R.dimen.more_suggestions_slide_allowance));
     93         setKeyPreviewPopupEnabled(false, 0);
     94     }
     95 
     96     @Override
     97     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     98         final Keyboard keyboard = getKeyboard();
     99         if (keyboard != null) {
    100             final int width = keyboard.mOccupiedWidth + getPaddingLeft() + getPaddingRight();
    101             final int height = keyboard.mOccupiedHeight + getPaddingTop() + getPaddingBottom();
    102             setMeasuredDimension(width, height);
    103         } else {
    104             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    105         }
    106     }
    107 
    108     public void updateKeyboardGeometry(final int keyHeight) {
    109         mKeyDrawParams.updateParams(keyHeight, mKeyVisualAttributes);
    110     }
    111 
    112     @Override
    113     public void setKeyboard(Keyboard keyboard) {
    114         super.setKeyboard(keyboard);
    115         mModalPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), -getPaddingTop());
    116         mSlidingPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
    117                 -getPaddingTop() + mVerticalCorrection);
    118     }
    119 
    120     @Override
    121     public KeyDetector getKeyDetector() {
    122         return mSlidingPanelKeyDetector;
    123     }
    124 
    125     @Override
    126     public KeyboardActionListener getKeyboardActionListener() {
    127         return mSuggestionsPaneListener;
    128     }
    129 
    130     @Override
    131     public DrawingProxy getDrawingProxy() {
    132         return this;
    133     }
    134 
    135     @Override
    136     public TimerProxy getTimerProxy() {
    137         return EMPTY_TIMER_PROXY;
    138     }
    139 
    140     @Override
    141     public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
    142         // Suggestions pane needs no pop-up key preview displayed, so we pass always false with a
    143         // delay of 0. The delay does not matter actually since the popup is not shown anyway.
    144         super.setKeyPreviewPopupEnabled(false, 0);
    145     }
    146 
    147     @Override
    148     public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
    149             PopupWindow window, KeyboardActionListener listener) {
    150         mController = controller;
    151         mListener = listener;
    152         final View container = (View)getParent();
    153         final MoreSuggestions pane = (MoreSuggestions)getKeyboard();
    154         final int defaultCoordX = pane.mOccupiedWidth / 2;
    155         // The coordinates of panel's left-top corner in parentView's coordinate system.
    156         final int x = pointX - defaultCoordX - container.getPaddingLeft();
    157         final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom();
    158 
    159         window.setContentView(container);
    160         window.setWidth(container.getMeasuredWidth());
    161         window.setHeight(container.getMeasuredHeight());
    162         parentView.getLocationInWindow(mCoordinates);
    163         window.showAtLocation(parentView, Gravity.NO_GRAVITY,
    164                 x + mCoordinates[0], y + mCoordinates[1]);
    165 
    166         mOriginX = x + container.getPaddingLeft();
    167         mOriginY = y + container.getPaddingTop();
    168     }
    169 
    170     private boolean mIsDismissing;
    171 
    172     @Override
    173     public boolean dismissMoreKeysPanel() {
    174         if (mIsDismissing || mController == null) return false;
    175         mIsDismissing = true;
    176         final boolean dismissed = mController.dismissMoreKeysPanel();
    177         mIsDismissing = false;
    178         return dismissed;
    179     }
    180 
    181     @Override
    182     public int translateX(int x) {
    183         return x - mOriginX;
    184     }
    185 
    186     @Override
    187     public int translateY(int y) {
    188         return y - mOriginY;
    189     }
    190 
    191     private final KeyEventHandler mModalPanelKeyEventHandler = new KeyEventHandler() {
    192         @Override
    193         public KeyDetector getKeyDetector() {
    194             return mModalPanelKeyDetector;
    195         }
    196 
    197         @Override
    198         public KeyboardActionListener getKeyboardActionListener() {
    199             return mSuggestionsPaneListener;
    200         }
    201 
    202         @Override
    203         public DrawingProxy getDrawingProxy() {
    204             return MoreSuggestionsView.this;
    205         }
    206 
    207         @Override
    208         public TimerProxy getTimerProxy() {
    209             return EMPTY_TIMER_PROXY;
    210         }
    211     };
    212 
    213     @Override
    214     public boolean onTouchEvent(MotionEvent me) {
    215         final int action = me.getAction();
    216         final long eventTime = me.getEventTime();
    217         final int index = me.getActionIndex();
    218         final int id = me.getPointerId(index);
    219         final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
    220         final int x = (int)me.getX(index);
    221         final int y = (int)me.getY(index);
    222         tracker.processMotionEvent(action, x, y, eventTime, mModalPanelKeyEventHandler);
    223         return true;
    224     }
    225 }
    226