1 /* 2 * Copyright (C) 2012 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.internal; 18 19 import android.content.res.TypedArray; 20 import android.graphics.Canvas; 21 import android.graphics.Paint; 22 import android.graphics.Paint.Align; 23 import android.graphics.Rect; 24 import android.graphics.RectF; 25 import android.text.TextUtils; 26 27 import com.android.inputmethod.keyboard.PointerTracker; 28 import com.android.inputmethod.latin.R; 29 import com.android.inputmethod.latin.SuggestedWords; 30 import com.android.inputmethod.latin.utils.CoordinateUtils; 31 32 /** 33 * The class for single gesture preview text. The class for multiple gesture preview text will be 34 * derived from it. 35 * 36 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextSize 37 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextColor 38 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewTextOffset 39 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewColor 40 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewHorizontalPadding 41 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewVerticalPadding 42 * @attr ref R.styleable#KeyboardView_gestureFloatingPreviewRoundRadius 43 */ 44 public class GestureFloatingTextDrawingPreview extends AbstractDrawingPreview { 45 protected static final class GesturePreviewTextParams { 46 public final int mGesturePreviewTextOffset; 47 public final int mGesturePreviewTextHeight; 48 public final float mGesturePreviewHorizontalPadding; 49 public final float mGesturePreviewVerticalPadding; 50 public final float mGesturePreviewRoundRadius; 51 public final int mDisplayWidth; 52 53 private final int mGesturePreviewTextSize; 54 private final int mGesturePreviewTextColor; 55 private final int mGesturePreviewColor; 56 private final Paint mPaint = new Paint(); 57 58 private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' }; 59 60 public GesturePreviewTextParams(final TypedArray mainKeyboardViewAttr) { 61 mGesturePreviewTextSize = mainKeyboardViewAttr.getDimensionPixelSize( 62 R.styleable.MainKeyboardView_gestureFloatingPreviewTextSize, 0); 63 mGesturePreviewTextColor = mainKeyboardViewAttr.getColor( 64 R.styleable.MainKeyboardView_gestureFloatingPreviewTextColor, 0); 65 mGesturePreviewTextOffset = mainKeyboardViewAttr.getDimensionPixelOffset( 66 R.styleable.MainKeyboardView_gestureFloatingPreviewTextOffset, 0); 67 mGesturePreviewColor = mainKeyboardViewAttr.getColor( 68 R.styleable.MainKeyboardView_gestureFloatingPreviewColor, 0); 69 mGesturePreviewHorizontalPadding = mainKeyboardViewAttr.getDimension( 70 R.styleable.MainKeyboardView_gestureFloatingPreviewHorizontalPadding, 0.0f); 71 mGesturePreviewVerticalPadding = mainKeyboardViewAttr.getDimension( 72 R.styleable.MainKeyboardView_gestureFloatingPreviewVerticalPadding, 0.0f); 73 mGesturePreviewRoundRadius = mainKeyboardViewAttr.getDimension( 74 R.styleable.MainKeyboardView_gestureFloatingPreviewRoundRadius, 0.0f); 75 mDisplayWidth = mainKeyboardViewAttr.getResources().getDisplayMetrics().widthPixels; 76 77 final Paint textPaint = getTextPaint(); 78 final Rect textRect = new Rect(); 79 textPaint.getTextBounds(TEXT_HEIGHT_REFERENCE_CHAR, 0, 1, textRect); 80 mGesturePreviewTextHeight = textRect.height(); 81 } 82 83 public Paint getTextPaint() { 84 mPaint.setAntiAlias(true); 85 mPaint.setTextAlign(Align.CENTER); 86 mPaint.setTextSize(mGesturePreviewTextSize); 87 mPaint.setColor(mGesturePreviewTextColor); 88 return mPaint; 89 } 90 91 public Paint getBackgroundPaint() { 92 mPaint.setColor(mGesturePreviewColor); 93 return mPaint; 94 } 95 } 96 97 private final GesturePreviewTextParams mParams; 98 private final RectF mGesturePreviewRectangle = new RectF(); 99 private int mPreviewTextX; 100 private int mPreviewTextY; 101 private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; 102 private final int[] mLastPointerCoords = CoordinateUtils.newInstance(); 103 104 public GestureFloatingTextDrawingPreview(final TypedArray mainKeyboardViewAttr) { 105 mParams = new GesturePreviewTextParams(mainKeyboardViewAttr); 106 } 107 108 @Override 109 public void onDeallocateMemory() { 110 // Nothing to do here. 111 } 112 113 public void setSuggetedWords(final SuggestedWords suggestedWords) { 114 if (!isPreviewEnabled()) { 115 return; 116 } 117 mSuggestedWords = suggestedWords; 118 updatePreviewPosition(); 119 } 120 121 @Override 122 public void setPreviewPosition(final PointerTracker tracker) { 123 if (!isPreviewEnabled()) { 124 return; 125 } 126 tracker.getLastCoordinates(mLastPointerCoords); 127 updatePreviewPosition(); 128 } 129 130 /** 131 * Draws gesture preview text 132 * @param canvas The canvas where preview text is drawn. 133 */ 134 @Override 135 public void drawPreview(final Canvas canvas) { 136 if (!isPreviewEnabled() || mSuggestedWords.isEmpty() 137 || TextUtils.isEmpty(mSuggestedWords.getWord(0))) { 138 return; 139 } 140 final float round = mParams.mGesturePreviewRoundRadius; 141 canvas.drawRoundRect( 142 mGesturePreviewRectangle, round, round, mParams.getBackgroundPaint()); 143 final String text = mSuggestedWords.getWord(0); 144 canvas.drawText(text, mPreviewTextX, mPreviewTextY, mParams.getTextPaint()); 145 } 146 147 /** 148 * Updates gesture preview text position based on mLastPointerCoords. 149 */ 150 protected void updatePreviewPosition() { 151 if (mSuggestedWords.isEmpty() || TextUtils.isEmpty(mSuggestedWords.getWord(0))) { 152 invalidateDrawingView(); 153 return; 154 } 155 final String text = mSuggestedWords.getWord(0); 156 157 final RectF rectangle = mGesturePreviewRectangle; 158 159 final int textHeight = mParams.mGesturePreviewTextHeight; 160 final float textWidth = mParams.getTextPaint().measureText(text); 161 final float hPad = mParams.mGesturePreviewHorizontalPadding; 162 final float vPad = mParams.mGesturePreviewVerticalPadding; 163 final float rectWidth = textWidth + hPad * 2.0f; 164 final float rectHeight = textHeight + vPad * 2.0f; 165 166 final float rectX = Math.min( 167 Math.max(CoordinateUtils.x(mLastPointerCoords) - rectWidth / 2.0f, 0.0f), 168 mParams.mDisplayWidth - rectWidth); 169 final float rectY = CoordinateUtils.y(mLastPointerCoords) 170 - mParams.mGesturePreviewTextOffset - rectHeight; 171 rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight); 172 173 mPreviewTextX = (int)(rectX + hPad + textWidth / 2.0f); 174 mPreviewTextY = (int)(rectY + vPad) + textHeight; 175 // TODO: Should narrow the invalidate region. 176 invalidateDrawingView(); 177 } 178 } 179