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