Home | History | Annotate | Download | only in latin
      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;
     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 
     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 class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel {
     44     private final int[] mCoordinates = new int[2];
     45 
     46     private final KeyDetector mModalPanelKeyDetector;
     47     private final KeyDetector mSlidingPanelKeyDetector;
     48 
     49     private Controller mController;
     50     private KeyboardActionListener mListener;
     51     private int mOriginX;
     52     private int mOriginY;
     53 
     54     private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter();
     55 
     56     private final KeyboardActionListener mSuggestionsPaneListener =
     57             new KeyboardActionListener.Adapter() {
     58         @Override
     59         public void onPress(int primaryCode, boolean withSliding) {
     60             mListener.onPress(primaryCode, withSliding);
     61         }
     62 
     63         @Override
     64         public void onRelease(int primaryCode, boolean withSliding) {
     65             mListener.onRelease(primaryCode, withSliding);
     66         }
     67 
     68         @Override
     69         public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
     70             final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE;
     71             if (index >= 0 && index < SuggestionsView.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     @Override
    109     public void setKeyboard(Keyboard keyboard) {
    110         super.setKeyboard(keyboard);
    111         mModalPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), -getPaddingTop());
    112         mSlidingPanelKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
    113                 -getPaddingTop() + mVerticalCorrection);
    114     }
    115 
    116     @Override
    117     public KeyDetector getKeyDetector() {
    118         return mSlidingPanelKeyDetector;
    119     }
    120 
    121     @Override
    122     public KeyboardActionListener getKeyboardActionListener() {
    123         return mSuggestionsPaneListener;
    124     }
    125 
    126     @Override
    127     public DrawingProxy getDrawingProxy() {
    128         return  this;
    129     }
    130 
    131     @Override
    132     public TimerProxy getTimerProxy() {
    133         return EMPTY_TIMER_PROXY;
    134     }
    135 
    136     @Override
    137     public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
    138         // Suggestions pane needs no pop-up key preview displayed, so we pass always false with a
    139         // delay of 0. The delay does not matter actually since the popup is not shown anyway.
    140         super.setKeyPreviewPopupEnabled(false, 0);
    141     }
    142 
    143     @Override
    144     public void setShifted(boolean shifted) {
    145         // Nothing to do with.
    146     }
    147 
    148     @Override
    149     public void showMoreKeysPanel(View parentView, Controller controller, int pointX, int pointY,
    150             PopupWindow window, KeyboardActionListener listener) {
    151         mController = controller;
    152         mListener = listener;
    153         final View container = (View)getParent();
    154         final MoreSuggestions pane = (MoreSuggestions)getKeyboard();
    155 
    156         parentView.getLocationInWindow(mCoordinates);
    157         final int paneLeft = pointX - (pane.mOccupiedWidth / 2) + parentView.getPaddingLeft();
    158         final int x = wrapUp(Math.max(0, Math.min(paneLeft,
    159                 parentView.getWidth() - pane.mOccupiedWidth))
    160                 - container.getPaddingLeft() + mCoordinates[0],
    161                 container.getMeasuredWidth(), 0, parentView.getWidth());
    162         final int y = pointY
    163                 - (container.getMeasuredHeight() - container.getPaddingBottom())
    164                 + parentView.getPaddingTop() + mCoordinates[1];
    165 
    166         window.setContentView(container);
    167         window.setWidth(container.getMeasuredWidth());
    168         window.setHeight(container.getMeasuredHeight());
    169         window.showAtLocation(parentView, Gravity.NO_GRAVITY, x, y);
    170 
    171         mOriginX = x + container.getPaddingLeft() - mCoordinates[0];
    172         mOriginY = y + container.getPaddingTop() - mCoordinates[1];
    173     }
    174 
    175     private static int wrapUp(int x, int width, int left, int right) {
    176         if (x < left)
    177             return left;
    178         if (x + width > right)
    179             return right - width;
    180         return x;
    181     }
    182 
    183     @Override
    184     public boolean dismissMoreKeysPanel() {
    185         if (mController == null) return false;
    186         return mController.dismissMoreKeysPanel();
    187     }
    188 
    189     @Override
    190     public int translateX(int x) {
    191         return x - mOriginX;
    192     }
    193 
    194     @Override
    195     public int translateY(int y) {
    196         return y - mOriginY;
    197     }
    198 
    199     private final KeyEventHandler mModalPanelKeyEventHandler = new KeyEventHandler() {
    200         @Override
    201         public KeyDetector getKeyDetector() {
    202             return mModalPanelKeyDetector;
    203         }
    204 
    205         @Override
    206         public KeyboardActionListener getKeyboardActionListener() {
    207             return mSuggestionsPaneListener;
    208         }
    209 
    210         @Override
    211         public DrawingProxy getDrawingProxy() {
    212             return MoreSuggestionsView.this;
    213         }
    214 
    215         @Override
    216         public TimerProxy getTimerProxy() {
    217             return EMPTY_TIMER_PROXY;
    218         }
    219     };
    220 
    221     @Override
    222     public boolean onTouchEvent(MotionEvent me) {
    223         final int action = me.getAction();
    224         final long eventTime = me.getEventTime();
    225         final int index = me.getActionIndex();
    226         final int id = me.getPointerId(index);
    227         final PointerTracker tracker = PointerTracker.getPointerTracker(id, this);
    228         final int x = (int)me.getX(index);
    229         final int y = (int)me.getY(index);
    230         tracker.processMotionEvent(action, x, y, eventTime, mModalPanelKeyEventHandler);
    231         return true;
    232     }
    233 }
    234