1 /*
2  * Copyright (C) 2014 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.Context;
20 import android.graphics.Rect;
21 import android.graphics.drawable.Drawable;
22 import android.text.TextPaint;
23 import android.text.TextUtils;
24 import android.util.AttributeSet;
25 import android.util.TypedValue;
26 import android.view.Gravity;
27 import android.widget.TextView;
28 
29 import com.android.inputmethod.keyboard.Key;
30 import com.android.inputmethod.latin.R;
31 
32 import java.util.HashSet;
33 
34 /**
35  * The pop up key preview view.
36  */
37 public class KeyPreviewView extends TextView {
38     public static final int POSITION_MIDDLE = 0;
39     public static final int POSITION_LEFT = 1;
40     public static final int POSITION_RIGHT = 2;
41 
42     private final Rect mBackgroundPadding = new Rect();
43     private static final HashSet<String> sNoScaleXTextSet = new HashSet<>();
44 
KeyPreviewView(final Context context, final AttributeSet attrs)45     public KeyPreviewView(final Context context, final AttributeSet attrs) {
46         this(context, attrs, 0);
47     }
48 
KeyPreviewView(final Context context, final AttributeSet attrs, final int defStyleAttr)49     public KeyPreviewView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
50         super(context, attrs, defStyleAttr);
51         setGravity(Gravity.CENTER);
52     }
53 
setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet, final KeyDrawParams drawParams)54     public void setPreviewVisual(final Key key, final KeyboardIconsSet iconsSet,
55             final KeyDrawParams drawParams) {
56         // What we show as preview should match what we show on a key top in onDraw().
57         final int iconId = key.getIconId();
58         if (iconId != KeyboardIconsSet.ICON_UNDEFINED) {
59             setCompoundDrawables(null, null, null, key.getPreviewIcon(iconsSet));
60             setText(null);
61             return;
62         }
63 
64         setCompoundDrawables(null, null, null, null);
65         setTextColor(drawParams.mPreviewTextColor);
66         setTextSize(TypedValue.COMPLEX_UNIT_PX, key.selectPreviewTextSize(drawParams));
67         setTypeface(key.selectPreviewTypeface(drawParams));
68         // TODO Should take care of temporaryShiftLabel here.
69         setTextAndScaleX(key.getPreviewLabel());
70     }
71 
setTextAndScaleX(final String text)72     private void setTextAndScaleX(final String text) {
73         setTextScaleX(1.0f);
74         setText(text);
75         if (sNoScaleXTextSet.contains(text)) {
76             return;
77         }
78         // TODO: Override {@link #setBackground(Drawable)} that is supported from API 16 and
79         // calculate maximum text width.
80         final Drawable background = getBackground();
81         if (background == null) {
82             return;
83         }
84         background.getPadding(mBackgroundPadding);
85         final int maxWidth = background.getIntrinsicWidth() - mBackgroundPadding.left
86                 - mBackgroundPadding.right;
87         final float width = getTextWidth(text, getPaint());
88         if (width <= maxWidth) {
89             sNoScaleXTextSet.add(text);
90             return;
91         }
92         setTextScaleX(maxWidth / width);
93     }
94 
clearTextCache()95     public static void clearTextCache() {
96         sNoScaleXTextSet.clear();
97     }
98 
getTextWidth(final String text, final TextPaint paint)99     private static float getTextWidth(final String text, final TextPaint paint) {
100         if (TextUtils.isEmpty(text)) {
101             return 0.0f;
102         }
103         final int len = text.length();
104         final float[] widths = new float[len];
105         final int count = paint.getTextWidths(text, 0, len, widths);
106         float width = 0;
107         for (int i = 0; i < count; i++) {
108             width += widths[i];
109         }
110         return width;
111     }
112 
113     // Background state set
114     private static final int[][][] KEY_PREVIEW_BACKGROUND_STATE_TABLE = {
115         { // POSITION_MIDDLE
116             {},
117             { R.attr.state_has_morekeys }
118         },
119         { // POSITION_LEFT
120             { R.attr.state_left_edge },
121             { R.attr.state_left_edge, R.attr.state_has_morekeys }
122         },
123         { // POSITION_RIGHT
124             { R.attr.state_right_edge },
125             { R.attr.state_right_edge, R.attr.state_has_morekeys }
126         }
127     };
128     private static final int STATE_NORMAL = 0;
129     private static final int STATE_HAS_MOREKEYS = 1;
130 
setPreviewBackground(final boolean hasMoreKeys, final int position)131     public void setPreviewBackground(final boolean hasMoreKeys, final int position) {
132         final Drawable background = getBackground();
133         if (background == null) {
134             return;
135         }
136         final int hasMoreKeysState = hasMoreKeys ? STATE_HAS_MOREKEYS : STATE_NORMAL;
137         background.setState(KEY_PREVIEW_BACKGROUND_STATE_TABLE[position][hasMoreKeysState]);
138     }
139 }
140