Merge remote-tracking branch 'goog/master' into merge
commit
abcbe57252
|
@ -32,14 +32,14 @@
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/candidate_strip_height"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/keyboard_suggest_strip_holo"
|
android:background="@drawable/keyboard_suggest_strip_holo"
|
||||||
android:paddingRight="@dimen/candidate_strip_padding"
|
android:paddingRight="@dimen/candidate_strip_padding"
|
||||||
android:paddingLeft="@dimen/candidate_strip_padding"
|
android:paddingLeft="@dimen/candidate_strip_padding"
|
||||||
>
|
>
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:fadingEdge="horizontal"
|
android:fadingEdge="horizontal"
|
||||||
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
|
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
|
||||||
android:scrollbars="none"
|
android:scrollbars="none"
|
||||||
|
@ -47,7 +47,8 @@
|
||||||
<com.android.inputmethod.latin.CandidateView
|
<com.android.inputmethod.latin.CandidateView
|
||||||
android:id="@+id/candidates"
|
android:id="@+id/candidates"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="@dimen/candidate_strip_height"
|
||||||
|
android:gravity="center_vertical" />
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
>
|
>
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/candidate_strip_height"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/keyboard_suggest_strip"
|
android:background="@drawable/keyboard_suggest_strip"
|
||||||
android:fadingEdge="horizontal"
|
android:fadingEdge="horizontal"
|
||||||
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
|
android:fadingEdgeLength="@dimen/candidate_strip_fading_edge_length"
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
<com.android.inputmethod.latin.CandidateView
|
<com.android.inputmethod.latin.CandidateView
|
||||||
android:id="@+id/candidates"
|
android:id="@+id/candidates"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="@dimen/candidate_strip_height"
|
||||||
|
android:gravity="center_vertical" />
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||||
<string name="alternates_for_a">1,à,â,æ,á,ä,ã,å,ā,ª</string>
|
<string name="alternates_for_a">à,â,1,æ,á,ä,ã,å,ā,ª</string>
|
||||||
<string name="alternates_for_e">3,é,è,ê,ë,ę,ė,ē</string>
|
<string name="alternates_for_e">é,è,ê,ë,3,ę,ė,ē</string>
|
||||||
<string name="alternates_for_i">8,î,ï,ì,í,į,ī</string>
|
<string name="alternates_for_i">î,8,ï,ì,í,į,ī</string>
|
||||||
<string name="alternates_for_o">9,ô,œ,ö,ò,ó,õ,ø,ō,º</string>
|
<string name="alternates_for_o">ô,œ,9,ö,ò,ó,õ,ø,ō,º</string>
|
||||||
<string name="alternates_for_u">7,û,ù,ü,ú,ū</string>
|
<string name="alternates_for_u">ù,û,7,ü,ú,ū</string>
|
||||||
<string name="alternates_for_c">ç,ć,č</string>
|
<string name="alternates_for_c">ç,ć,č</string>
|
||||||
<string name="alternates_for_y">6,ÿ</string>
|
<string name="alternates_for_y">6,ÿ</string>
|
||||||
<string name="alternates_for_q"></string>
|
<string name="alternates_for_q"></string>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2011, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<!-- Screen metrics for logging. 0 = "mdpi", 1 = "hdpi", 2 = "xlarge" -->
|
||||||
|
<integer name="log_screen_metrics">1</integer>
|
||||||
|
</resources>
|
|
@ -43,4 +43,6 @@
|
||||||
<string name="config_default_keyboard_theme_id" translatable="false">5</string>
|
<string name="config_default_keyboard_theme_id" translatable="false">5</string>
|
||||||
<string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
|
<string name="config_text_size_of_language_on_spacebar" translatable="false">medium</string>
|
||||||
<integer name="config_max_popup_keyboard_column">5</integer>
|
<integer name="config_max_popup_keyboard_column">5</integer>
|
||||||
|
<!-- Screen metrics for logging. 0 = "mdpi", 1 = "hdpi", 2 = "xlarge" -->
|
||||||
|
<integer name="log_screen_metrics">2</integer>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
|
<!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
|
||||||
<string name="config_default_keyboard_theme_id" translatable="false">4</string>
|
<string name="config_default_keyboard_theme_id" translatable="false">4</string>
|
||||||
<string name="config_text_size_of_language_on_spacebar" translatable="false">small</string>
|
<string name="config_text_size_of_language_on_spacebar" translatable="false">small</string>
|
||||||
<integer name="config_max_popup_keyboard_column">10</integer>
|
<integer name="config_max_popup_keyboard_column">5</integer>
|
||||||
<!-- Whether or not auto-correction should be enabled by default -->
|
<!-- Whether or not auto-correction should be enabled by default -->
|
||||||
<bool name="enable_autocorrect">true</bool>
|
<bool name="enable_autocorrect">true</bool>
|
||||||
<string-array name="auto_correction_threshold_values" translatable="false">
|
<string-array name="auto_correction_threshold_values" translatable="false">
|
||||||
|
@ -76,4 +76,6 @@
|
||||||
will be subject to auto-correction. -->
|
will be subject to auto-correction. -->
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<!-- Screen metrics for logging. 0 = "mdpi", 1 = "hdpi", 2 = "xlarge" -->
|
||||||
|
<integer name="log_screen_metrics">0</integer>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -16,36 +16,35 @@
|
||||||
|
|
||||||
package com.android.inputmethod.keyboard;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class KeyDetector {
|
public class KeyDetector {
|
||||||
public static final int NOT_A_KEY = -1;
|
private static final String TAG = KeyDetector.class.getSimpleName();
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
public static final int NOT_A_CODE = -1;
|
public static final int NOT_A_CODE = -1;
|
||||||
|
public static final int NOT_A_KEY = -1;
|
||||||
|
|
||||||
protected Keyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
|
private int mCorrectionX;
|
||||||
|
private int mCorrectionY;
|
||||||
|
private boolean mProximityCorrectOn;
|
||||||
|
private int mProximityThresholdSquare;
|
||||||
|
|
||||||
private Key[] mKeys;
|
// working area
|
||||||
|
private static final int MAX_NEARBY_KEYS = 12;
|
||||||
|
private final int[] mDistances = new int[MAX_NEARBY_KEYS];
|
||||||
|
private final int[] mIndices = new int[MAX_NEARBY_KEYS];
|
||||||
|
|
||||||
protected int mCorrectionX;
|
public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
|
||||||
|
|
||||||
protected int mCorrectionY;
|
|
||||||
|
|
||||||
protected boolean mProximityCorrectOn;
|
|
||||||
|
|
||||||
protected int mProximityThresholdSquare;
|
|
||||||
|
|
||||||
public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
|
|
||||||
if (keyboard == null)
|
if (keyboard == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
mCorrectionX = (int)correctionX;
|
mCorrectionX = (int)correctionX;
|
||||||
mCorrectionY = (int)correctionY;
|
mCorrectionY = (int)correctionY;
|
||||||
mKeyboard = keyboard;
|
mKeyboard = keyboard;
|
||||||
List<Key> keys = mKeyboard.getKeys();
|
|
||||||
Key[] array = keys.toArray(new Key[keys.size()]);
|
|
||||||
mKeys = array;
|
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getTouchX(int x) {
|
protected int getTouchX(int x) {
|
||||||
|
@ -56,11 +55,11 @@ public abstract class KeyDetector {
|
||||||
return y + mCorrectionY;
|
return y + mCorrectionY;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Key[] getKeys() {
|
protected List<Key> getKeys() {
|
||||||
if (mKeys == null)
|
if (mKeyboard == null)
|
||||||
throw new IllegalStateException("keyboard isn't set");
|
throw new IllegalStateException("keyboard isn't set");
|
||||||
// mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null
|
// mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null
|
||||||
return mKeys;
|
return mKeyboard.getKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProximityCorrectionEnabled(boolean enabled) {
|
public void setProximityCorrectionEnabled(boolean enabled) {
|
||||||
|
@ -75,6 +74,17 @@ public abstract class KeyDetector {
|
||||||
mProximityThresholdSquare = threshold * threshold;
|
mProximityThresholdSquare = threshold * threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes maximum size of the array that can contain all nearby key indices returned by
|
||||||
|
* {@link #getKeyIndexAndNearbyCodes}.
|
||||||
|
*
|
||||||
|
* @return Returns maximum size of the array that can contain all nearby key indices returned
|
||||||
|
* by {@link #getKeyIndexAndNearbyCodes}.
|
||||||
|
*/
|
||||||
|
protected int getMaxNearbyKeys() {
|
||||||
|
return MAX_NEARBY_KEYS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes}
|
* Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes}
|
||||||
* method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}.
|
* method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}.
|
||||||
|
@ -89,14 +99,60 @@ public abstract class KeyDetector {
|
||||||
return codes;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeNearbyKeys() {
|
||||||
|
Arrays.fill(mDistances, Integer.MAX_VALUE);
|
||||||
|
Arrays.fill(mIndices, NOT_A_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes maximum size of the array that can contain all nearby key indices returned by
|
* Insert the key into nearby keys buffer and sort nearby keys by ascending order of distance.
|
||||||
* {@link #getKeyIndexAndNearbyCodes}.
|
|
||||||
*
|
*
|
||||||
* @return Returns maximum size of the array that can contain all nearby key indices returned
|
* @param keyIndex index of the key.
|
||||||
* by {@link #getKeyIndexAndNearbyCodes}.
|
* @param distance distance between the key's edge and user touched point.
|
||||||
|
* @return order of the key in the nearby buffer, 0 if it is the nearest key.
|
||||||
*/
|
*/
|
||||||
abstract protected int getMaxNearbyKeys();
|
private int sortNearbyKeys(int keyIndex, int distance) {
|
||||||
|
final int[] distances = mDistances;
|
||||||
|
final int[] indices = mIndices;
|
||||||
|
for (int insertPos = 0; insertPos < distances.length; insertPos++) {
|
||||||
|
if (distance < distances[insertPos]) {
|
||||||
|
final int nextPos = insertPos + 1;
|
||||||
|
if (nextPos < distances.length) {
|
||||||
|
System.arraycopy(distances, insertPos, distances, nextPos,
|
||||||
|
distances.length - nextPos);
|
||||||
|
System.arraycopy(indices, insertPos, indices, nextPos,
|
||||||
|
indices.length - nextPos);
|
||||||
|
}
|
||||||
|
distances[insertPos] = distance;
|
||||||
|
indices[insertPos] = keyIndex;
|
||||||
|
return insertPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return distances.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getNearbyKeyCodes(final int[] allCodes) {
|
||||||
|
final List<Key> keys = getKeys();
|
||||||
|
final int[] indices = mIndices;
|
||||||
|
|
||||||
|
// allCodes[0] should always have the key code even if it is a non-letter key.
|
||||||
|
if (indices[0] == NOT_A_KEY) {
|
||||||
|
allCodes[0] = NOT_A_CODE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numCodes = 0;
|
||||||
|
for (int j = 0; j < indices.length && numCodes < allCodes.length; j++) {
|
||||||
|
final int index = indices[j];
|
||||||
|
if (index == NOT_A_KEY)
|
||||||
|
break;
|
||||||
|
final int code = keys.get(index).mCode;
|
||||||
|
// filter out a non-letter key from nearby keys
|
||||||
|
if (code < Keyboard.CODE_SPACE)
|
||||||
|
continue;
|
||||||
|
allCodes[numCodes++] = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds all possible nearby key indices around a touch event point and returns the nearest key
|
* Finds all possible nearby key indices around a touch event point and returns the nearest key
|
||||||
|
@ -109,32 +165,34 @@ public abstract class KeyDetector {
|
||||||
* @param allCodes All nearby key code except functional key are returned in this array
|
* @param allCodes All nearby key code except functional key are returned in this array
|
||||||
* @return The nearest key index
|
* @return The nearest key index
|
||||||
*/
|
*/
|
||||||
abstract public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes);
|
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
|
||||||
|
final List<Key> keys = getKeys();
|
||||||
|
final int touchX = getTouchX(x);
|
||||||
|
final int touchY = getTouchY(y);
|
||||||
|
|
||||||
/**
|
initializeNearbyKeys();
|
||||||
* Compute the most common key width in order to use it as proximity key detection threshold.
|
int primaryIndex = NOT_A_KEY;
|
||||||
*
|
for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
|
||||||
* @param keyboard The keyboard to compute the most common key width
|
final Key key = keys.get(index);
|
||||||
* @return The most common key width in the keyboard
|
final boolean isInside = key.isInside(touchX, touchY);
|
||||||
*/
|
final int distance = key.squaredDistanceToEdge(touchX, touchY);
|
||||||
public static int getMostCommonKeyWidth(final Keyboard keyboard) {
|
if (isInside || (mProximityCorrectOn && distance < mProximityThresholdSquare)) {
|
||||||
if (keyboard == null) return 0;
|
final int insertedPosition = sortNearbyKeys(index, distance);
|
||||||
final List<Key> keys = keyboard.getKeys();
|
if (insertedPosition == 0 && isInside)
|
||||||
if (keys == null || keys.size() == 0) return 0;
|
primaryIndex = index;
|
||||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
|
||||||
int maxCount = 0;
|
|
||||||
int mostCommonWidth = 0;
|
|
||||||
for (final Key key : keys) {
|
|
||||||
final Integer width = key.mWidth + key.mGap;
|
|
||||||
Integer count = histogram.get(width);
|
|
||||||
if (count == null)
|
|
||||||
count = 0;
|
|
||||||
histogram.put(width, ++count);
|
|
||||||
if (count > maxCount) {
|
|
||||||
maxCount = count;
|
|
||||||
mostCommonWidth = width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mostCommonWidth;
|
|
||||||
|
if (allCodes != null && allCodes.length > 0) {
|
||||||
|
getNearbyKeyCodes(allCodes);
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "x=" + x + " y=" + y
|
||||||
|
+ " primary="
|
||||||
|
+ (primaryIndex == NOT_A_KEY ? "none" : keys.get(primaryIndex).mCode)
|
||||||
|
+ " codes=" + Arrays.toString(allCodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return primaryIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,8 @@ public class Keyboard {
|
||||||
/** Height of keyboard */
|
/** Height of keyboard */
|
||||||
private int mKeyboardHeight;
|
private int mKeyboardHeight;
|
||||||
|
|
||||||
|
private int mMostCommonKeyWidth = 0;
|
||||||
|
|
||||||
public final KeyboardId mId;
|
public final KeyboardId mId;
|
||||||
|
|
||||||
// Variables for pre-computing nearest keys.
|
// Variables for pre-computing nearest keys.
|
||||||
|
@ -405,6 +407,41 @@ public class Keyboard {
|
||||||
return EMPTY_INT_ARRAY;
|
return EMPTY_INT_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the most common key width in order to use it as proximity key detection threshold.
|
||||||
|
*
|
||||||
|
* @return The most common key width in the keyboard
|
||||||
|
*/
|
||||||
|
public int getMostCommonKeyWidth() {
|
||||||
|
if (mMostCommonKeyWidth == 0) {
|
||||||
|
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||||
|
int maxCount = 0;
|
||||||
|
int mostCommonWidth = 0;
|
||||||
|
for (final Key key : mKeys) {
|
||||||
|
final Integer width = key.mWidth + key.mGap;
|
||||||
|
Integer count = histogram.get(width);
|
||||||
|
if (count == null)
|
||||||
|
count = 0;
|
||||||
|
histogram.put(width, ++count);
|
||||||
|
if (count > maxCount) {
|
||||||
|
maxCount = count;
|
||||||
|
mostCommonWidth = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mMostCommonKeyWidth = mostCommonWidth;
|
||||||
|
}
|
||||||
|
return mMostCommonKeyWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if spacebar needs showing preview even when "popup on keypress" is off.
|
||||||
|
* @param keyIndex index of the pressing key
|
||||||
|
* @return true if spacebar needs showing preview
|
||||||
|
*/
|
||||||
|
public boolean needSpacebarPreview(int keyIndex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void loadKeyboard(Context context, int xmlLayoutResId) {
|
private void loadKeyboard(Context context, int xmlLayoutResId) {
|
||||||
try {
|
try {
|
||||||
KeyboardParser parser = new KeyboardParser(this, context.getResources());
|
KeyboardParser parser = new KeyboardParser(this, context.getResources());
|
||||||
|
|
|
@ -18,7 +18,6 @@ package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.LatinImeLogger;
|
import com.android.inputmethod.latin.LatinImeLogger;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
@ -47,6 +46,7 @@ import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.PopupWindow;
|
import android.widget.PopupWindow;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -105,7 +105,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
|
|
||||||
// Main keyboard
|
// Main keyboard
|
||||||
private Keyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
private Key[] mKeys;
|
|
||||||
|
|
||||||
// Key preview popup
|
// Key preview popup
|
||||||
private boolean mInForeground;
|
private boolean mInForeground;
|
||||||
|
@ -146,7 +145,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
// Accessibility
|
// Accessibility
|
||||||
private boolean mIsAccessibilityEnabled;
|
private boolean mIsAccessibilityEnabled;
|
||||||
|
|
||||||
protected KeyDetector mKeyDetector = new ProximityKeyDetector();
|
protected KeyDetector mKeyDetector = new KeyDetector();
|
||||||
|
|
||||||
// Swipe gesture detector
|
// Swipe gesture detector
|
||||||
private GestureDetector mGestureDetector;
|
private GestureDetector mGestureDetector;
|
||||||
|
@ -224,7 +223,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
|
|
||||||
public void popupPreview(long delay, int keyIndex, PointerTracker tracker) {
|
public void popupPreview(long delay, int keyIndex, PointerTracker tracker) {
|
||||||
removeMessages(MSG_POPUP_PREVIEW);
|
removeMessages(MSG_POPUP_PREVIEW);
|
||||||
if (mPreviewText.getVisibility() == VISIBLE) {
|
if (mPreviewText.getVisibility() == VISIBLE || delay == 0) {
|
||||||
// Show right away, if it's already visible and finger is moving around
|
// Show right away, if it's already visible and finger is moving around
|
||||||
showKey(keyIndex, tracker);
|
showKey(keyIndex, tracker);
|
||||||
} else {
|
} else {
|
||||||
|
@ -492,15 +491,15 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
mKeyboard = keyboard;
|
mKeyboard = keyboard;
|
||||||
LatinImeLogger.onSetKeyboard(keyboard);
|
LatinImeLogger.onSetKeyboard(keyboard);
|
||||||
mKeys = mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
|
mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
|
||||||
-getPaddingTop() + mVerticalCorrection);
|
-getPaddingTop() + mVerticalCorrection);
|
||||||
for (PointerTracker tracker : mPointerTrackers) {
|
for (PointerTracker tracker : mPointerTrackers) {
|
||||||
tracker.setKeyboard(keyboard, mKeys, mKeyHysteresisDistance);
|
tracker.setKeyboard(keyboard, mKeyHysteresisDistance);
|
||||||
}
|
}
|
||||||
requestLayout();
|
requestLayout();
|
||||||
mKeyboardChanged = true;
|
mKeyboardChanged = true;
|
||||||
invalidateAllKeys();
|
invalidateAllKeys();
|
||||||
mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(keyboard));
|
mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
|
||||||
mMiniKeyboardCache.clear();
|
mMiniKeyboardCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,44 +636,75 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
}
|
}
|
||||||
final Canvas canvas = mCanvas;
|
final Canvas canvas = mCanvas;
|
||||||
canvas.clipRect(mDirtyRect, Op.REPLACE);
|
canvas.clipRect(mDirtyRect, Op.REPLACE);
|
||||||
|
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
if (mKeyboard == null) return;
|
if (mKeyboard == null) return;
|
||||||
|
|
||||||
|
if (mInvalidatedKey != null && mInvalidatedKeyRect.contains(mDirtyRect)) {
|
||||||
|
// Draw a single key.
|
||||||
|
onBufferDrawKey(canvas, mInvalidatedKey);
|
||||||
|
} else {
|
||||||
|
// Draw all keys.
|
||||||
|
for (final Key key : mKeyboard.getKeys()) {
|
||||||
|
onBufferDrawKey(canvas, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move this function to ProximityInfo for getting rid of
|
||||||
|
// public declarations for
|
||||||
|
// GRID_WIDTH and GRID_HEIGHT
|
||||||
|
if (DEBUG_KEYBOARD_GRID) {
|
||||||
|
Paint p = new Paint();
|
||||||
|
p.setStyle(Paint.Style.STROKE);
|
||||||
|
p.setStrokeWidth(1.0f);
|
||||||
|
p.setColor(0x800000c0);
|
||||||
|
int cw = (mKeyboard.getMinWidth() + mKeyboard.GRID_WIDTH - 1)
|
||||||
|
/ mKeyboard.GRID_WIDTH;
|
||||||
|
int ch = (mKeyboard.getHeight() + mKeyboard.GRID_HEIGHT - 1)
|
||||||
|
/ mKeyboard.GRID_HEIGHT;
|
||||||
|
for (int i = 0; i <= mKeyboard.GRID_WIDTH; i++)
|
||||||
|
canvas.drawLine(i * cw, 0, i * cw, ch * mKeyboard.GRID_HEIGHT, p);
|
||||||
|
for (int i = 0; i <= mKeyboard.GRID_HEIGHT; i++)
|
||||||
|
canvas.drawLine(0, i * ch, cw * mKeyboard.GRID_WIDTH, i * ch, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overlay a dark rectangle to dim the keyboard
|
||||||
|
if (mMiniKeyboardView != null) {
|
||||||
|
mPaint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
|
||||||
|
canvas.drawRect(0, 0, width, height, mPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
mInvalidatedKey = null;
|
||||||
|
mDrawPending = false;
|
||||||
|
mDirtyRect.setEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onBufferDrawKey(final Canvas canvas, final Key key) {
|
||||||
final Paint paint = mPaint;
|
final Paint paint = mPaint;
|
||||||
final Drawable keyBackground = mKeyBackground;
|
final Drawable keyBackground = mKeyBackground;
|
||||||
final Rect padding = mPadding;
|
final Rect padding = mPadding;
|
||||||
final int kbdPaddingLeft = getPaddingLeft();
|
final int kbdPaddingLeft = getPaddingLeft();
|
||||||
final int kbdPaddingTop = getPaddingTop();
|
final int kbdPaddingTop = getPaddingTop();
|
||||||
final Key[] keys = mKeys;
|
|
||||||
final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase();
|
|
||||||
final boolean drawSingleKey = (mInvalidatedKey != null
|
|
||||||
&& mInvalidatedKeyRect.contains(mDirtyRect));
|
|
||||||
|
|
||||||
canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
|
|
||||||
final int keyCount = keys.length;
|
|
||||||
for (int i = 0; i < keyCount; i++) {
|
|
||||||
final Key key = keys[i];
|
|
||||||
if (drawSingleKey && key != mInvalidatedKey) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int[] drawableState = key.getCurrentDrawableState();
|
|
||||||
keyBackground.setState(drawableState);
|
|
||||||
|
|
||||||
// Switch the character to uppercase if shift is pressed
|
|
||||||
String label = key.mLabel == null? null : adjustCase(key.mLabel).toString();
|
|
||||||
|
|
||||||
final int keyDrawX = key.mX + key.mVisualInsetsLeft;
|
final int keyDrawX = key.mX + key.mVisualInsetsLeft;
|
||||||
final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
|
final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
|
||||||
|
final int rowHeight = padding.top + key.mHeight;
|
||||||
|
final boolean isManualTemporaryUpperCase = mKeyboard.isManualTemporaryUpperCase();
|
||||||
|
|
||||||
|
canvas.translate(keyDrawX + kbdPaddingLeft, key.mY + kbdPaddingTop);
|
||||||
|
|
||||||
|
// Draw key background.
|
||||||
|
final int[] drawableState = key.getCurrentDrawableState();
|
||||||
|
keyBackground.setState(drawableState);
|
||||||
final Rect bounds = keyBackground.getBounds();
|
final Rect bounds = keyBackground.getBounds();
|
||||||
if (keyDrawWidth != bounds.right || key.mHeight != bounds.bottom) {
|
if (keyDrawWidth != bounds.right || key.mHeight != bounds.bottom) {
|
||||||
keyBackground.setBounds(0, 0, keyDrawWidth, key.mHeight);
|
keyBackground.setBounds(0, 0, keyDrawWidth, key.mHeight);
|
||||||
}
|
}
|
||||||
canvas.translate(keyDrawX + kbdPaddingLeft, key.mY + kbdPaddingTop);
|
|
||||||
keyBackground.draw(canvas);
|
keyBackground.draw(canvas);
|
||||||
|
|
||||||
final int rowHeight = padding.top + key.mHeight;
|
// Draw key label.
|
||||||
// Draw key label
|
if (key.mLabel != null) {
|
||||||
if (label != null) {
|
// Switch the character to uppercase if shift is pressed
|
||||||
|
final String label = key.mLabel == null ? null : adjustCase(key.mLabel).toString();
|
||||||
// For characters, use large font. For labels like "Done", use small font.
|
// For characters, use large font. For labels like "Done", use small font.
|
||||||
final int labelSize = getLabelSizeAndSetPaint(label, key.mLabelOption, paint);
|
final int labelSize = getLabelSizeAndSetPaint(label, key.mLabelOption, paint);
|
||||||
final int labelCharHeight = getLabelCharHeight(labelSize, paint);
|
final int labelCharHeight = getLabelCharHeight(labelSize, paint);
|
||||||
|
@ -682,15 +712,13 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
// Vertical label text alignment.
|
// Vertical label text alignment.
|
||||||
final float baseline;
|
final float baseline;
|
||||||
if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_BOTTOM) != 0) {
|
if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_BOTTOM) != 0) {
|
||||||
baseline = key.mHeight -
|
baseline = key.mHeight - labelCharHeight * KEY_LABEL_VERTICAL_PADDING_FACTOR;
|
||||||
+ labelCharHeight * KEY_LABEL_VERTICAL_PADDING_FACTOR;
|
|
||||||
if (DEBUG_SHOW_ALIGN)
|
if (DEBUG_SHOW_ALIGN)
|
||||||
drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000,
|
drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000,
|
||||||
new Paint());
|
new Paint());
|
||||||
} else { // Align center
|
} else { // Align center
|
||||||
final float centerY = (key.mHeight + padding.top - padding.bottom) / 2;
|
final float centerY = (key.mHeight + padding.top - padding.bottom) / 2;
|
||||||
baseline = centerY
|
baseline = centerY + labelCharHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER;
|
||||||
+ labelCharHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR_CENTER;
|
|
||||||
if (DEBUG_SHOW_ALIGN)
|
if (DEBUG_SHOW_ALIGN)
|
||||||
drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000,
|
drawHorizontalLine(canvas, (int)baseline, keyDrawWidth, 0xc0008000,
|
||||||
new Paint());
|
new Paint());
|
||||||
|
@ -731,14 +759,14 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
// Turn off drop shadow
|
// Turn off drop shadow
|
||||||
paint.setShadowLayer(0, 0, 0, 0);
|
paint.setShadowLayer(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
// Draw key icon
|
|
||||||
|
// Draw key icon.
|
||||||
final Drawable icon = key.getIcon();
|
final Drawable icon = key.getIcon();
|
||||||
if (key.mLabel == null && icon != null) {
|
if (key.mLabel == null && icon != null) {
|
||||||
final int drawableWidth = icon.getIntrinsicWidth();
|
final int drawableWidth = icon.getIntrinsicWidth();
|
||||||
final int drawableHeight = icon.getIntrinsicHeight();
|
final int drawableHeight = icon.getIntrinsicHeight();
|
||||||
final int drawableX;
|
final int drawableX;
|
||||||
final int drawableY = (
|
final int drawableY = (key.mHeight + padding.top - padding.bottom - drawableHeight) / 2;
|
||||||
key.mHeight + padding.top - padding.bottom - drawableHeight) / 2;
|
|
||||||
if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) {
|
if ((key.mLabelOption & KEY_LABEL_OPTION_ALIGN_LEFT) != 0) {
|
||||||
drawableX = padding.left + mKeyLabelHorizontalPadding;
|
drawableX = padding.left + mKeyLabelHorizontalPadding;
|
||||||
if (DEBUG_SHOW_ALIGN)
|
if (DEBUG_SHOW_ALIGN)
|
||||||
|
@ -760,6 +788,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
|
drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
|
||||||
0x80c00000, new Paint());
|
0x80c00000, new Paint());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw hint icon.
|
||||||
if (key.mHintIcon != null) {
|
if (key.mHintIcon != null) {
|
||||||
final int drawableWidth = keyDrawWidth;
|
final int drawableWidth = keyDrawWidth;
|
||||||
final int drawableHeight = key.mHeight;
|
final int drawableHeight = key.mHeight;
|
||||||
|
@ -773,35 +803,10 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
|
drawRectangle(canvas, drawableX, drawableY, drawableWidth, drawableHeight,
|
||||||
0x80c0c000, new Paint());
|
0x80c0c000, new Paint());
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.translate(-keyDrawX - kbdPaddingLeft, -key.mY - kbdPaddingTop);
|
canvas.translate(-keyDrawX - kbdPaddingLeft, -key.mY - kbdPaddingTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move this function to ProximityInfo for getting rid of public declarations for
|
|
||||||
// GRID_WIDTH and GRID_HEIGHT
|
|
||||||
if (DEBUG_KEYBOARD_GRID) {
|
|
||||||
Paint p = new Paint();
|
|
||||||
p.setStyle(Paint.Style.STROKE);
|
|
||||||
p.setStrokeWidth(1.0f);
|
|
||||||
p.setColor(0x800000c0);
|
|
||||||
int cw = (mKeyboard.getMinWidth() + mKeyboard.GRID_WIDTH - 1) / mKeyboard.GRID_WIDTH;
|
|
||||||
int ch = (mKeyboard.getHeight() + mKeyboard.GRID_HEIGHT - 1) / mKeyboard.GRID_HEIGHT;
|
|
||||||
for (int i = 0; i <= mKeyboard.GRID_WIDTH; i++)
|
|
||||||
canvas.drawLine(i * cw, 0, i * cw, ch * mKeyboard.GRID_HEIGHT, p);
|
|
||||||
for (int i = 0; i <= mKeyboard.GRID_HEIGHT; i++)
|
|
||||||
canvas.drawLine(0, i * ch, cw * mKeyboard.GRID_WIDTH, i * ch, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlay a dark rectangle to dim the keyboard
|
|
||||||
if (mMiniKeyboardView != null) {
|
|
||||||
paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24);
|
|
||||||
canvas.drawRect(0, 0, width, height, paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
mInvalidatedKey = null;
|
|
||||||
mDrawPending = false;
|
|
||||||
mDirtyRect.setEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLabelSizeAndSetPaint(CharSequence label, int keyLabelOption, Paint paint) {
|
public int getLabelSizeAndSetPaint(CharSequence label, int keyLabelOption, Paint paint) {
|
||||||
// For characters, use large font. For labels like "Done", use small font.
|
// For characters, use large font. For labels like "Done", use small font.
|
||||||
final int labelSize;
|
final int labelSize;
|
||||||
|
@ -883,15 +888,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
public void showPreview(int keyIndex, PointerTracker tracker) {
|
public void showPreview(int keyIndex, PointerTracker tracker) {
|
||||||
int oldKeyIndex = mOldPreviewKeyIndex;
|
int oldKeyIndex = mOldPreviewKeyIndex;
|
||||||
mOldPreviewKeyIndex = keyIndex;
|
mOldPreviewKeyIndex = keyIndex;
|
||||||
// We should re-draw popup preview when 1) we need to hide the preview, 2) we will show
|
if ((mShowPreview && oldKeyIndex != keyIndex) || mKeyboard.needSpacebarPreview(keyIndex)) {
|
||||||
// the space key preview and 3) pointer moves off the space key to other letter key, we
|
|
||||||
// should hide the preview of the previous key.
|
|
||||||
final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
|
|
||||||
|| (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher()
|
|
||||||
&& SubtypeSwitcher.getInstance().needsToDisplayLanguage()
|
|
||||||
&& (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
|
|
||||||
// If key changed and preview is on or the key is space (language switch is enabled)
|
|
||||||
if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview))) {
|
|
||||||
if (keyIndex == KeyDetector.NOT_A_KEY) {
|
if (keyIndex == KeyDetector.NOT_A_KEY) {
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
mHandler.dismissPreview(mDelayAfterPreview);
|
mHandler.dismissPreview(mDelayAfterPreview);
|
||||||
|
@ -908,10 +905,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
if (mPreviewText.getParent() == null) {
|
if (mPreviewText.getParent() == null) {
|
||||||
final FrameLayout screenContent = (FrameLayout) getRootView()
|
final FrameLayout screenContent = (FrameLayout) getRootView()
|
||||||
.findViewById(android.R.id.content);
|
.findViewById(android.R.id.content);
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= /* HONEYCOMB */ 11) {
|
||||||
screenContent.addView(mPreviewText, new FrameLayout.LayoutParams(0, 0));
|
screenContent.addView(mPreviewText, new FrameLayout.LayoutParams(0, 0));
|
||||||
|
} else {
|
||||||
|
// Insert LinearLayout to be able to setMargin because pre-Honeycomb FrameLayout
|
||||||
|
// could not handle setMargin properly.
|
||||||
|
final LinearLayout placer = new LinearLayout(getContext());
|
||||||
|
screenContent.addView(placer);
|
||||||
|
placer.addView(mPreviewText, new LinearLayout.LayoutParams(0, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Key key = tracker.getKey(keyIndex);
|
final Key key = tracker.getKey(keyIndex);
|
||||||
// If keyIndex is invalid or IME is already closed, we must not show key preview.
|
// If keyIndex is invalid or IME is already closed, we must not show key preview.
|
||||||
// Trying to show preview PopupWindow while root window is closed causes
|
// Trying to show preview PopupWindow while root window is closed causes
|
||||||
// WindowManager.BadTokenException.
|
// WindowManager.BadTokenException.
|
||||||
|
@ -943,10 +948,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
+ mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
|
+ mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
|
||||||
final int popupHeight = mPreviewHeight;
|
final int popupHeight = mPreviewHeight;
|
||||||
final ViewGroup.LayoutParams lp = mPreviewText.getLayoutParams();
|
final ViewGroup.LayoutParams lp = mPreviewText.getLayoutParams();
|
||||||
if (lp != null) {
|
|
||||||
lp.width = popupWidth;
|
lp.width = popupWidth;
|
||||||
lp.height = popupHeight;
|
lp.height = popupHeight;
|
||||||
}
|
|
||||||
|
|
||||||
int popupPreviewX = keyDrawX - (popupWidth - keyDrawWidth) / 2;
|
int popupPreviewX = keyDrawX - (popupWidth - keyDrawWidth) / 2;
|
||||||
int popupPreviewY = key.mY - popupHeight + mPreviewOffset;
|
int popupPreviewY = key.mY - popupHeight + mPreviewOffset;
|
||||||
|
@ -1172,15 +1175,14 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
|
|
||||||
private PointerTracker getPointerTracker(final int id) {
|
private PointerTracker getPointerTracker(final int id) {
|
||||||
final ArrayList<PointerTracker> pointers = mPointerTrackers;
|
final ArrayList<PointerTracker> pointers = mPointerTrackers;
|
||||||
final Key[] keys = mKeys;
|
|
||||||
final KeyboardActionListener listener = mKeyboardActionListener;
|
final KeyboardActionListener listener = mKeyboardActionListener;
|
||||||
|
|
||||||
// Create pointer trackers until we can get 'id+1'-th tracker, if needed.
|
// Create pointer trackers until we can get 'id+1'-th tracker, if needed.
|
||||||
for (int i = pointers.size(); i <= id; i++) {
|
for (int i = pointers.size(); i <= id; i++) {
|
||||||
final PointerTracker tracker =
|
final PointerTracker tracker =
|
||||||
new PointerTracker(i, mHandler, mKeyDetector, this, getResources());
|
new PointerTracker(i, mHandler, mKeyDetector, this, getResources());
|
||||||
if (keys != null)
|
if (mKeyboard != null)
|
||||||
tracker.setKeyboard(mKeyboard, keys, mKeyHysteresisDistance);
|
tracker.setKeyboard(mKeyboard, mKeyHysteresisDistance);
|
||||||
if (listener != null)
|
if (listener != null)
|
||||||
tracker.setOnKeyboardActionListener(listener);
|
tracker.setOnKeyboardActionListener(listener);
|
||||||
pointers.add(tracker);
|
pointers.add(tracker);
|
||||||
|
|
|
@ -26,6 +26,9 @@ import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.ColorMatrix;
|
||||||
|
import android.graphics.ColorMatrixColorFilter;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Paint.Align;
|
import android.graphics.Paint.Align;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -33,15 +36,18 @@ import android.graphics.Rect;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import java.lang.ref.SoftReference;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
// TODO: We should remove this class
|
// TODO: We should remove this class
|
||||||
public class LatinKeyboard extends Keyboard {
|
public class LatinKeyboard extends Keyboard {
|
||||||
public static final int OPACITY_FULLY_OPAQUE = 255;
|
|
||||||
private static final int SPACE_LED_LENGTH_PERCENT = 80;
|
private static final int SPACE_LED_LENGTH_PERCENT = 80;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance();
|
||||||
|
|
||||||
/* Space key and its icons, drawables and colors. */
|
/* Space key and its icons, drawables and colors. */
|
||||||
private final Key mSpaceKey;
|
private final Key mSpaceKey;
|
||||||
|
@ -59,14 +65,18 @@ public class LatinKeyboard extends Keyboard {
|
||||||
private int mSpaceDragLastDiff;
|
private int mSpaceDragLastDiff;
|
||||||
private boolean mCurrentlyInSpace;
|
private boolean mCurrentlyInSpace;
|
||||||
private SlidingLocaleDrawable mSlidingLocaleIcon;
|
private SlidingLocaleDrawable mSlidingLocaleIcon;
|
||||||
|
private final HashMap<Integer, SoftReference<BitmapDrawable>> mSpaceDrawableCache =
|
||||||
|
new HashMap<Integer, SoftReference<BitmapDrawable>>();
|
||||||
|
|
||||||
/* Shortcut key and its icons if available */
|
/* Shortcut key and its icons if available */
|
||||||
private final Key mShortcutKey;
|
private final Key mShortcutKey;
|
||||||
private final Drawable mEnabledShortcutIcon;
|
private final Drawable mEnabledShortcutIcon;
|
||||||
private final Drawable mDisabledShortcutIcon;
|
private final Drawable mDisabledShortcutIcon;
|
||||||
|
|
||||||
private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f;
|
// Minimum width of spacebar dragging to trigger the language switch (represented by the number
|
||||||
// Minimum width of space key preview (proportional to keyboard width)
|
// of the most common key width of this keyboard).
|
||||||
|
private static final int SPACEBAR_DRAG_WIDTH = 3;
|
||||||
|
// Minimum width of space key preview (proportional to keyboard width).
|
||||||
private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f;
|
private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f;
|
||||||
// Height in space key the language name will be drawn. (proportional to space key height)
|
// Height in space key the language name will be drawn. (proportional to space key height)
|
||||||
public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
|
public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
|
||||||
|
@ -137,6 +147,12 @@ public class LatinKeyboard extends Keyboard {
|
||||||
return newColor;
|
return newColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ColorFilter getSpacebarDrawableFilter(float fadeFactor) {
|
||||||
|
final ColorMatrix colorMatrix = new ColorMatrix();
|
||||||
|
colorMatrix.setScale(1, 1, 1, fadeFactor);
|
||||||
|
return new ColorMatrixColorFilter(colorMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
public void updateShortcutKey(boolean available, LatinKeyboardView view) {
|
public void updateShortcutKey(boolean available, LatinKeyboardView view) {
|
||||||
if (mShortcutKey == null)
|
if (mShortcutKey == null)
|
||||||
return;
|
return;
|
||||||
|
@ -157,21 +173,16 @@ public class LatinKeyboard extends Keyboard {
|
||||||
private void updateSpacebarForLocale(boolean isAutoCorrection) {
|
private void updateSpacebarForLocale(boolean isAutoCorrection) {
|
||||||
if (mSpaceKey == null)
|
if (mSpaceKey == null)
|
||||||
return;
|
return;
|
||||||
final Resources res = mContext.getResources();
|
|
||||||
// If application locales are explicitly selected.
|
// If application locales are explicitly selected.
|
||||||
if (SubtypeSwitcher.getInstance().needsToDisplayLanguage()) {
|
if (mSubtypeSwitcher.needsToDisplayLanguage()) {
|
||||||
mSpaceKey.setIcon(new BitmapDrawable(res,
|
mSpaceKey.setIcon(getSpaceDrawable(
|
||||||
drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
|
mSubtypeSwitcher.getInputLocale(), isAutoCorrection));
|
||||||
} else {
|
} else if (isAutoCorrection) {
|
||||||
// sym_keyboard_space_led can be shared with Black and White symbol themes.
|
mSpaceKey.setIcon(getSpaceDrawable(null, true));
|
||||||
if (isAutoCorrection) {
|
|
||||||
mSpaceKey.setIcon(new BitmapDrawable(res,
|
|
||||||
drawSpacebar(OPACITY_FULLY_OPAQUE, isAutoCorrection)));
|
|
||||||
} else {
|
} else {
|
||||||
mSpaceKey.setIcon(mSpaceIcon);
|
mSpaceKey.setIcon(mSpaceIcon);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Compute width of text with specified text size using paint.
|
// Compute width of text with specified text size using paint.
|
||||||
private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) {
|
private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) {
|
||||||
|
@ -223,19 +234,31 @@ public class LatinKeyboard extends Keyboard {
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap drawSpacebar(int opacity, boolean isAutoCorrection) {
|
private BitmapDrawable getSpaceDrawable(Locale locale, boolean isAutoCorrection) {
|
||||||
|
final Integer hashCode = Arrays.hashCode(
|
||||||
|
new Object[] { locale, isAutoCorrection, mSpacebarTextFadeFactor });
|
||||||
|
final SoftReference<BitmapDrawable> ref = mSpaceDrawableCache.get(hashCode);
|
||||||
|
BitmapDrawable drawable = (ref == null) ? null : ref.get();
|
||||||
|
if (drawable == null) {
|
||||||
|
drawable = new BitmapDrawable(mContext.getResources(), drawSpacebar(
|
||||||
|
locale, isAutoCorrection, mSpacebarTextFadeFactor));
|
||||||
|
mSpaceDrawableCache.put(hashCode, new SoftReference<BitmapDrawable>(drawable));
|
||||||
|
}
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap drawSpacebar(Locale inputLocale, boolean isAutoCorrection,
|
||||||
|
float textFadeFactor) {
|
||||||
final int width = mSpaceKey.mWidth;
|
final int width = mSpaceKey.mWidth;
|
||||||
final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
|
final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
|
||||||
final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
final Canvas canvas = new Canvas(buffer);
|
final Canvas canvas = new Canvas(buffer);
|
||||||
final Resources res = mContext.getResources();
|
final Resources res = mContext.getResources();
|
||||||
canvas.drawColor(res.getColor(android.R.color.transparent), PorterDuff.Mode.CLEAR);
|
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
|
|
||||||
// If application locales are explicitly selected.
|
// If application locales are explicitly selected.
|
||||||
if (subtypeSwitcher.needsToDisplayLanguage()) {
|
if (inputLocale != null) {
|
||||||
final Paint paint = new Paint();
|
final Paint paint = new Paint();
|
||||||
paint.setAlpha(opacity);
|
|
||||||
paint.setAntiAlias(true);
|
paint.setAntiAlias(true);
|
||||||
paint.setTextAlign(Align.CENTER);
|
paint.setTextAlign(Align.CENTER);
|
||||||
|
|
||||||
|
@ -253,7 +276,7 @@ public class LatinKeyboard extends Keyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean allowVariableTextSize = true;
|
final boolean allowVariableTextSize = true;
|
||||||
final String language = layoutSpacebar(paint, subtypeSwitcher.getInputLocale(),
|
final String language = layoutSpacebar(paint, inputLocale,
|
||||||
mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
|
mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height,
|
||||||
getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize),
|
getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize),
|
||||||
allowVariableTextSize);
|
allowVariableTextSize);
|
||||||
|
@ -265,14 +288,16 @@ public class LatinKeyboard extends Keyboard {
|
||||||
final float textHeight = -paint.ascent() + descent;
|
final float textHeight = -paint.ascent() + descent;
|
||||||
final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
|
final float baseline = (mSpaceIcon != null) ? height * SPACEBAR_LANGUAGE_BASELINE
|
||||||
: height / 2 + textHeight / 2;
|
: height / 2 + textHeight / 2;
|
||||||
paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, mSpacebarTextFadeFactor));
|
paint.setColor(getSpacebarTextColor(mSpacebarTextShadowColor, textFadeFactor));
|
||||||
canvas.drawText(language, width / 2, baseline - descent - 1, paint);
|
canvas.drawText(language, width / 2, baseline - descent - 1, paint);
|
||||||
paint.setColor(getSpacebarTextColor(mSpacebarTextColor, mSpacebarTextFadeFactor));
|
paint.setColor(getSpacebarTextColor(mSpacebarTextColor, textFadeFactor));
|
||||||
canvas.drawText(language, width / 2, baseline - descent, paint);
|
canvas.drawText(language, width / 2, baseline - descent, paint);
|
||||||
|
|
||||||
// Put arrows that are already layed out on either side of the text
|
// Put arrows that are already layed out on either side of the text
|
||||||
if (subtypeSwitcher.useSpacebarLanguageSwitcher()
|
if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()
|
||||||
&& subtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
|
&& mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
|
||||||
|
mButtonArrowLeftIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor));
|
||||||
|
mButtonArrowRightIcon.setColorFilter(getSpacebarDrawableFilter(textFadeFactor));
|
||||||
mButtonArrowLeftIcon.draw(canvas);
|
mButtonArrowLeftIcon.draw(canvas);
|
||||||
mButtonArrowRightIcon.draw(canvas);
|
mButtonArrowRightIcon.draw(canvas);
|
||||||
}
|
}
|
||||||
|
@ -316,9 +341,25 @@ public class LatinKeyboard extends Keyboard {
|
||||||
mSpaceKey.getPreviewIcon().invalidateSelf();
|
mSpaceKey.getPreviewIcon().invalidateSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is called when "popup on keypress" is off.
|
||||||
|
@Override
|
||||||
|
public boolean needSpacebarPreview(int keyIndex) {
|
||||||
|
if (!mSubtypeSwitcher.useSpacebarLanguageSwitcher())
|
||||||
|
return false;
|
||||||
|
// Dismiss key preview.
|
||||||
|
if (keyIndex == KeyDetector.NOT_A_KEY)
|
||||||
|
return true;
|
||||||
|
// Key is not a spacebar.
|
||||||
|
if (keyIndex != mSpaceKeyIndexArray[0])
|
||||||
|
return false;
|
||||||
|
// The language switcher will be displayed only when the dragging distance is greater
|
||||||
|
// than average key width of this keyboard.
|
||||||
|
return Math.abs(mSpaceDragLastDiff) > getMostCommonKeyWidth();
|
||||||
|
}
|
||||||
|
|
||||||
public int getLanguageChangeDirection() {
|
public int getLanguageChangeDirection() {
|
||||||
if (mSpaceKey == null || SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() <= 1
|
if (mSpaceKey == null || SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() <= 1
|
||||||
|| Math.abs(mSpaceDragLastDiff) < mSpaceKey.mWidth * SPACEBAR_DRAG_THRESHOLD) {
|
|| Math.abs(mSpaceDragLastDiff) < getMostCommonKeyWidth() * SPACEBAR_DRAG_WIDTH) {
|
||||||
return 0; // No change
|
return 0; // No change
|
||||||
}
|
}
|
||||||
return mSpaceDragLastDiff > 0 ? 1 : -1;
|
return mSpaceDragLastDiff > 0 ? 1 : -1;
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class MiniKeyboardBuilder {
|
||||||
/* package */ static class MiniKeyboardLayoutParams {
|
/* package */ static class MiniKeyboardLayoutParams {
|
||||||
public final int mKeyWidth;
|
public final int mKeyWidth;
|
||||||
public final int mRowHeight;
|
public final int mRowHeight;
|
||||||
/* package */ final boolean mTopRowNeedsCentering;
|
/* package */ final int mTopRowAdjustment;
|
||||||
public final int mNumRows;
|
public final int mNumRows;
|
||||||
public final int mNumColumns;
|
public final int mNumColumns;
|
||||||
public final int mLeftKeys;
|
public final int mLeftKeys;
|
||||||
|
@ -55,29 +55,52 @@ public class MiniKeyboardBuilder {
|
||||||
if (parentKeyboardWidth / keyWidth < maxColumns)
|
if (parentKeyboardWidth / keyWidth < maxColumns)
|
||||||
throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: "
|
throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: "
|
||||||
+ parentKeyboardWidth + " " + keyWidth + " " + maxColumns);
|
+ parentKeyboardWidth + " " + keyWidth + " " + maxColumns);
|
||||||
final int numRows = (numKeys + maxColumns - 1) / maxColumns;
|
|
||||||
mKeyWidth = keyWidth;
|
mKeyWidth = keyWidth;
|
||||||
mRowHeight = rowHeight;
|
mRowHeight = rowHeight;
|
||||||
mNumRows = numRows;
|
|
||||||
|
|
||||||
final int numColumns = Math.min(numKeys, maxColumns);
|
final int numRows = (numKeys + maxColumns - 1) / maxColumns;
|
||||||
final int topRowKeys = numKeys % numColumns;
|
mNumRows = numRows;
|
||||||
|
final int numColumns = getOptimizedColumns(numKeys, maxColumns);
|
||||||
mNumColumns = numColumns;
|
mNumColumns = numColumns;
|
||||||
mTopRowNeedsCentering = topRowKeys != 0 && (numColumns - topRowKeys) % 2 != 0;
|
|
||||||
|
|
||||||
final int numLeftKeys = (numColumns - 1) / 2;
|
final int numLeftKeys = (numColumns - 1) / 2;
|
||||||
final int numRightKeys = numColumns - numLeftKeys; // including default key.
|
final int numRightKeys = numColumns - numLeftKeys; // including default key.
|
||||||
final int maxLeftKeys = coordXInParent / keyWidth;
|
final int maxLeftKeys = coordXInParent / keyWidth;
|
||||||
final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth);
|
final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth);
|
||||||
|
int leftKeys, rightKeys;
|
||||||
if (numLeftKeys > maxLeftKeys) {
|
if (numLeftKeys > maxLeftKeys) {
|
||||||
mLeftKeys = maxLeftKeys;
|
leftKeys = maxLeftKeys;
|
||||||
mRightKeys = numColumns - maxLeftKeys;
|
rightKeys = numColumns - maxLeftKeys;
|
||||||
} else if (numRightKeys > maxRightKeys) {
|
} else if (numRightKeys > maxRightKeys) {
|
||||||
mLeftKeys = numColumns - maxRightKeys;
|
leftKeys = numColumns - maxRightKeys;
|
||||||
mRightKeys = maxRightKeys;
|
rightKeys = maxRightKeys;
|
||||||
} else {
|
} else {
|
||||||
mLeftKeys = numLeftKeys;
|
leftKeys = numLeftKeys;
|
||||||
mRightKeys = numRightKeys;
|
rightKeys = numRightKeys;
|
||||||
|
}
|
||||||
|
// Shift right if the left edge of mini keyboard is on the edge of parent keyboard
|
||||||
|
// unless the parent key is on the left edge.
|
||||||
|
if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) {
|
||||||
|
leftKeys--;
|
||||||
|
rightKeys++;
|
||||||
|
}
|
||||||
|
// Shift left if the right edge of mini keyboard is on the edge of parent keyboard
|
||||||
|
// unless the parent key is on the right edge.
|
||||||
|
if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) {
|
||||||
|
leftKeys++;
|
||||||
|
rightKeys--;
|
||||||
|
}
|
||||||
|
mLeftKeys = leftKeys;
|
||||||
|
mRightKeys = rightKeys;
|
||||||
|
|
||||||
|
// Centering of the top row.
|
||||||
|
final boolean onEdge = (leftKeys == 0 || rightKeys == 1);
|
||||||
|
if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) {
|
||||||
|
mTopRowAdjustment = 0;
|
||||||
|
} else if (mLeftKeys < mRightKeys - 1) {
|
||||||
|
mTopRowAdjustment = 1;
|
||||||
|
} else {
|
||||||
|
mTopRowAdjustment = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +136,32 @@ public class MiniKeyboardBuilder {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getTopRowEmptySlots(int numKeys, int numColumns) {
|
||||||
|
final int remainingKeys = numKeys % numColumns;
|
||||||
|
if (remainingKeys == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return numColumns - remainingKeys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getOptimizedColumns(int numKeys, int maxColumns) {
|
||||||
|
int numColumns = Math.min(numKeys, maxColumns);
|
||||||
|
while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) {
|
||||||
|
numColumns--;
|
||||||
|
}
|
||||||
|
return numColumns;
|
||||||
|
}
|
||||||
|
|
||||||
public int getDefaultKeyCoordX() {
|
public int getDefaultKeyCoordX() {
|
||||||
return mLeftKeys * mKeyWidth;
|
return mLeftKeys * mKeyWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getX(int n, int row) {
|
public int getX(int n, int row) {
|
||||||
final int x = getColumnPos(n) * mKeyWidth + getDefaultKeyCoordX();
|
final int x = getColumnPos(n) * mKeyWidth + getDefaultKeyCoordX();
|
||||||
if (isLastRow(row) && mTopRowNeedsCentering)
|
if (isTopRow(row)) {
|
||||||
return x - mKeyWidth / 2;
|
return x + mTopRowAdjustment * (mKeyWidth / 2);
|
||||||
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,27 +172,27 @@ public class MiniKeyboardBuilder {
|
||||||
public int getRowFlags(int row) {
|
public int getRowFlags(int row) {
|
||||||
int rowFlags = 0;
|
int rowFlags = 0;
|
||||||
if (row == 0) rowFlags |= Keyboard.EDGE_TOP;
|
if (row == 0) rowFlags |= Keyboard.EDGE_TOP;
|
||||||
if (isLastRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
|
if (isTopRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM;
|
||||||
return rowFlags;
|
return rowFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLastRow(int rowCount) {
|
private boolean isTopRow(int rowCount) {
|
||||||
return rowCount == mNumRows - 1;
|
return rowCount == mNumRows - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key popupKey) {
|
public MiniKeyboardBuilder(KeyboardView view, int layoutTemplateResId, Key parentKey) {
|
||||||
final Context context = view.getContext();
|
final Context context = view.getContext();
|
||||||
mRes = context.getResources();
|
mRes = context.getResources();
|
||||||
final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null);
|
final MiniKeyboard keyboard = new MiniKeyboard(context, layoutTemplateResId, null);
|
||||||
mKeyboard = keyboard;
|
mKeyboard = keyboard;
|
||||||
mPopupCharacters = popupKey.mPopupCharacters;
|
mPopupCharacters = parentKey.mPopupCharacters;
|
||||||
|
|
||||||
final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, keyboard.getKeyWidth());
|
final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, keyboard.getKeyWidth());
|
||||||
final MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
|
final MiniKeyboardLayoutParams params = new MiniKeyboardLayoutParams(
|
||||||
mPopupCharacters.length, popupKey.mMaxPopupColumn,
|
mPopupCharacters.length, parentKey.mMaxPopupColumn,
|
||||||
keyWidth, keyboard.getRowHeight(),
|
keyWidth, keyboard.getRowHeight(),
|
||||||
popupKey.mX + (popupKey.mWidth + popupKey.mGap) / 2 - keyWidth / 2,
|
parentKey.mX + (parentKey.mWidth + parentKey.mGap) / 2 - keyWidth / 2,
|
||||||
view.getMeasuredWidth());
|
view.getMeasuredWidth());
|
||||||
mParams = params;
|
mParams = params;
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
|
|
||||||
package com.android.inputmethod.keyboard;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
public class MiniKeyboardKeyDetector extends KeyDetector {
|
import java.util.List;
|
||||||
private static final int MAX_NEARBY_KEYS = 1;
|
|
||||||
|
|
||||||
|
public class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
private final int mSlideAllowanceSquare;
|
private final int mSlideAllowanceSquare;
|
||||||
private final int mSlideAllowanceSquareTop;
|
private final int mSlideAllowanceSquareTop;
|
||||||
|
|
||||||
|
@ -31,20 +31,21 @@ public class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getMaxNearbyKeys() {
|
protected int getMaxNearbyKeys() {
|
||||||
return MAX_NEARBY_KEYS;
|
// No nearby key will be returned.
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
|
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
|
||||||
final Key[] keys = getKeys();
|
final List<Key> keys = getKeys();
|
||||||
final int touchX = getTouchX(x);
|
final int touchX = getTouchX(x);
|
||||||
final int touchY = getTouchY(y);
|
final int touchY = getTouchY(y);
|
||||||
|
|
||||||
int nearestIndex = NOT_A_KEY;
|
int nearestIndex = NOT_A_KEY;
|
||||||
int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
||||||
final int keyCount = keys.length;
|
final int keyCount = keys.size();
|
||||||
for (int index = 0; index < keyCount; index++) {
|
for (int index = 0; index < keyCount; index++) {
|
||||||
final int dist = keys[index].squaredDistanceToEdge(touchX, touchY);
|
final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY);
|
||||||
if (dist < nearestDist) {
|
if (dist < nearestDist) {
|
||||||
nearestIndex = index;
|
nearestIndex = index;
|
||||||
nearestDist = dist;
|
nearestDist = dist;
|
||||||
|
@ -52,7 +53,7 @@ public class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allCodes != null && nearestIndex != NOT_A_KEY)
|
if (allCodes != null && nearestIndex != NOT_A_KEY)
|
||||||
allCodes[0] = keys[nearestIndex].mCode;
|
allCodes[0] = keys.get(nearestIndex).mCode;
|
||||||
return nearestIndex;
|
return nearestIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class PointerTracker {
|
public class PointerTracker {
|
||||||
private static final String TAG = PointerTracker.class.getSimpleName();
|
private static final String TAG = PointerTracker.class.getSimpleName();
|
||||||
|
@ -63,7 +64,7 @@ public class PointerTracker {
|
||||||
private final int mTouchNoiseThresholdDistanceSquared;
|
private final int mTouchNoiseThresholdDistanceSquared;
|
||||||
|
|
||||||
private Keyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
private Key[] mKeys;
|
private List<Key> mKeys;
|
||||||
private int mKeyHysteresisDistanceSquared = -1;
|
private int mKeyHysteresisDistanceSquared = -1;
|
||||||
private int mKeyQuarterWidthSquared;
|
private int mKeyQuarterWidthSquared;
|
||||||
|
|
||||||
|
@ -109,8 +110,8 @@ public class PointerTracker {
|
||||||
public void onSwipeDown() {}
|
public void onSwipeDown() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy,
|
public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector,
|
||||||
Resources res) {
|
UIProxy proxy, Resources res) {
|
||||||
if (proxy == null || handler == null || keyDetector == null)
|
if (proxy == null || handler == null || keyDetector == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
mPointerId = id;
|
mPointerId = id;
|
||||||
|
@ -197,11 +198,11 @@ public class PointerTracker {
|
||||||
mListener.onCancelInput();
|
mListener.onCancelInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyboard(Keyboard keyboard, Key[] keys, float keyHysteresisDistance) {
|
public void setKeyboard(Keyboard keyboard, float keyHysteresisDistance) {
|
||||||
if (keyboard == null || keys == null || keyHysteresisDistance < 0)
|
if (keyboard == null || keyHysteresisDistance < 0)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
mKeyboard = keyboard;
|
mKeyboard = keyboard;
|
||||||
mKeys = keys;
|
mKeys = keyboard.getKeys();
|
||||||
mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
|
mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
|
||||||
final int keyQuarterWidth = keyboard.getKeyWidth() / 4;
|
final int keyQuarterWidth = keyboard.getKeyWidth() / 4;
|
||||||
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
|
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
|
||||||
|
@ -214,11 +215,11 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidKeyIndex(int keyIndex) {
|
private boolean isValidKeyIndex(int keyIndex) {
|
||||||
return keyIndex >= 0 && keyIndex < mKeys.length;
|
return keyIndex >= 0 && keyIndex < mKeys.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Key getKey(int keyIndex) {
|
public Key getKey(int keyIndex) {
|
||||||
return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null;
|
return isValidKeyIndex(keyIndex) ? mKeys.get(keyIndex) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isModifierCode(int primaryCode) {
|
private static boolean isModifierCode(int primaryCode) {
|
||||||
|
@ -258,12 +259,14 @@ public class PointerTracker {
|
||||||
mPreviousKey = keyIndex;
|
mPreviousKey = keyIndex;
|
||||||
if (keyIndex != oldKeyIndex) {
|
if (keyIndex != oldKeyIndex) {
|
||||||
if (isValidKeyIndex(oldKeyIndex)) {
|
if (isValidKeyIndex(oldKeyIndex)) {
|
||||||
mKeys[oldKeyIndex].onReleased();
|
final Key oldKey = mKeys.get(oldKeyIndex);
|
||||||
mProxy.invalidateKey(mKeys[oldKeyIndex]);
|
oldKey.onReleased();
|
||||||
|
mProxy.invalidateKey(oldKey);
|
||||||
}
|
}
|
||||||
if (isValidKeyIndex(keyIndex)) {
|
if (isValidKeyIndex(keyIndex)) {
|
||||||
mKeys[keyIndex].onPressed();
|
final Key newKey = mKeys.get(keyIndex);
|
||||||
mProxy.invalidateKey(mKeys[keyIndex]);
|
newKey.onPressed();
|
||||||
|
mProxy.invalidateKey(newKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,9 +491,6 @@ public class PointerTracker {
|
||||||
if (!mIsRepeatableKey) {
|
if (!mIsRepeatableKey) {
|
||||||
detectAndSendKey(keyIndex, x, y);
|
detectAndSendKey(keyIndex, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidKeyIndex(keyIndex))
|
|
||||||
mProxy.invalidateKey(mKeys[keyIndex]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
|
public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
|
||||||
|
@ -508,9 +508,6 @@ public class PointerTracker {
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
|
showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY);
|
||||||
mIsInSlidingKeyInput = false;
|
mIsInSlidingKeyInput = false;
|
||||||
int keyIndex = mKeyState.getKeyIndex();
|
|
||||||
if (isValidKeyIndex(keyIndex))
|
|
||||||
mProxy.invalidateKey(mKeys[keyIndex]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void repeatKey(int keyIndex) {
|
public void repeatKey(int keyIndex) {
|
||||||
|
@ -539,7 +536,7 @@ public class PointerTracker {
|
||||||
if (newKey == curKey) {
|
if (newKey == curKey) {
|
||||||
return true;
|
return true;
|
||||||
} else if (isValidKeyIndex(curKey)) {
|
} else if (isValidKeyIndex(curKey)) {
|
||||||
return mKeys[curKey].squaredDistanceToEdge(x, y) < mKeyHysteresisDistanceSquared;
|
return mKeys.get(curKey).squaredDistanceToEdge(x, y) < mKeyHysteresisDistanceSquared;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.inputmethod.keyboard;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class ProximityKeyDetector extends KeyDetector {
|
|
||||||
private static final String TAG = ProximityKeyDetector.class.getSimpleName();
|
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
|
|
||||||
private static final int MAX_NEARBY_KEYS = 12;
|
|
||||||
|
|
||||||
// working area
|
|
||||||
private final int[] mDistances = new int[MAX_NEARBY_KEYS];
|
|
||||||
private final int[] mIndices = new int[MAX_NEARBY_KEYS];
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getMaxNearbyKeys() {
|
|
||||||
return MAX_NEARBY_KEYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeNearbyKeys() {
|
|
||||||
Arrays.fill(mDistances, Integer.MAX_VALUE);
|
|
||||||
Arrays.fill(mIndices, NOT_A_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert the key into nearby keys buffer and sort nearby keys by ascending order of distance.
|
|
||||||
*
|
|
||||||
* @param keyIndex index of the key.
|
|
||||||
* @param distance distance between the key's edge and user touched point.
|
|
||||||
* @return order of the key in the nearby buffer, 0 if it is the nearest key.
|
|
||||||
*/
|
|
||||||
private int sortNearbyKeys(int keyIndex, int distance) {
|
|
||||||
final int[] distances = mDistances;
|
|
||||||
final int[] indices = mIndices;
|
|
||||||
for (int insertPos = 0; insertPos < distances.length; insertPos++) {
|
|
||||||
if (distance < distances[insertPos]) {
|
|
||||||
final int nextPos = insertPos + 1;
|
|
||||||
if (nextPos < distances.length) {
|
|
||||||
System.arraycopy(distances, insertPos, distances, nextPos,
|
|
||||||
distances.length - nextPos);
|
|
||||||
System.arraycopy(indices, insertPos, indices, nextPos,
|
|
||||||
indices.length - nextPos);
|
|
||||||
}
|
|
||||||
distances[insertPos] = distance;
|
|
||||||
indices[insertPos] = keyIndex;
|
|
||||||
return insertPos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return distances.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getNearbyKeyCodes(final int[] allCodes) {
|
|
||||||
final Key[] keys = getKeys();
|
|
||||||
final int[] indices = mIndices;
|
|
||||||
|
|
||||||
// allCodes[0] should always have the key code even if it is a non-letter key.
|
|
||||||
if (indices[0] == NOT_A_KEY) {
|
|
||||||
allCodes[0] = NOT_A_CODE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numCodes = 0;
|
|
||||||
for (int j = 0; j < indices.length && numCodes < allCodes.length; j++) {
|
|
||||||
final int index = indices[j];
|
|
||||||
if (index == NOT_A_KEY)
|
|
||||||
break;
|
|
||||||
final int code = keys[index].mCode;
|
|
||||||
// filter out a non-letter key from nearby keys
|
|
||||||
if (code < Keyboard.CODE_SPACE)
|
|
||||||
continue;
|
|
||||||
allCodes[numCodes++] = code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
|
|
||||||
final Key[] keys = getKeys();
|
|
||||||
final int touchX = getTouchX(x);
|
|
||||||
final int touchY = getTouchY(y);
|
|
||||||
|
|
||||||
initializeNearbyKeys();
|
|
||||||
int primaryIndex = NOT_A_KEY;
|
|
||||||
for (final int index : mKeyboard.getNearestKeys(touchX, touchY)) {
|
|
||||||
final Key key = keys[index];
|
|
||||||
final boolean isInside = key.isInside(touchX, touchY);
|
|
||||||
final int distance = key.squaredDistanceToEdge(touchX, touchY);
|
|
||||||
if (isInside || (mProximityCorrectOn && distance < mProximityThresholdSquare)) {
|
|
||||||
final int insertedPosition = sortNearbyKeys(index, distance);
|
|
||||||
if (insertedPosition == 0 && isInside)
|
|
||||||
primaryIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allCodes != null && allCodes.length > 0) {
|
|
||||||
getNearbyKeyCodes(allCodes);
|
|
||||||
if (DEBUG) {
|
|
||||||
Log.d(TAG, "x=" + x + " y=" + y
|
|
||||||
+ " primary="
|
|
||||||
+ (primaryIndex == NOT_A_KEY ? "none" : keys[primaryIndex].mCode)
|
|
||||||
+ " codes=" + Arrays.toString(allCodes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return primaryIndex;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,6 +23,7 @@ import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.ColorFilter;
|
import android.graphics.ColorFilter;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
|
@ -63,9 +64,8 @@ public class SlidingLocaleDrawable extends Drawable {
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
final TextPaint textPaint = new TextPaint();
|
final TextPaint textPaint = new TextPaint();
|
||||||
textPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18));
|
textPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18));
|
||||||
textPaint.setColor(android.R.color.transparent);
|
textPaint.setColor(Color.TRANSPARENT);
|
||||||
textPaint.setTextAlign(Align.CENTER);
|
textPaint.setTextAlign(Align.CENTER);
|
||||||
textPaint.setAlpha(LatinKeyboard.OPACITY_FULLY_OPAQUE);
|
|
||||||
textPaint.setAntiAlias(true);
|
textPaint.setAntiAlias(true);
|
||||||
mTextPaint = textPaint;
|
mTextPaint = textPaint;
|
||||||
mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
|
mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
|
||||||
|
|
|
@ -30,6 +30,11 @@ import android.net.Uri;
|
||||||
public class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
|
public class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
final LatinIME mService;
|
final LatinIME mService;
|
||||||
|
/**
|
||||||
|
* The action of the intent for publishing that new dictionary data is available.
|
||||||
|
*/
|
||||||
|
/* package */ static final String NEW_DICTIONARY_INTENT_ACTION =
|
||||||
|
"com.android.inputmethod.latin.dictionarypack.newdict";
|
||||||
|
|
||||||
public DictionaryPackInstallBroadcastReceiver(final LatinIME service) {
|
public DictionaryPackInstallBroadcastReceiver(final LatinIME service) {
|
||||||
mService = service;
|
mService = service;
|
||||||
|
@ -77,6 +82,8 @@ public class DictionaryPackInstallBroadcastReceiver extends BroadcastReceiver {
|
||||||
// TODO: Only reload dictionary on REMOVED when the removed package is the one we
|
// TODO: Only reload dictionary on REMOVED when the removed package is the one we
|
||||||
// read dictionary from?
|
// read dictionary from?
|
||||||
mService.resetSuggestMainDict();
|
mService.resetSuggestMainDict();
|
||||||
|
} else if (action.equals(NEW_DICTIONARY_INTENT_ACTION)) {
|
||||||
|
mService.resetSuggestMainDict();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,6 +440,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
||||||
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||||
packageFilter.addDataScheme(SCHEME_PACKAGE);
|
packageFilter.addDataScheme(SCHEME_PACKAGE);
|
||||||
registerReceiver(mDictionaryPackInstallReceiver, packageFilter);
|
registerReceiver(mDictionaryPackInstallReceiver, packageFilter);
|
||||||
|
|
||||||
|
final IntentFilter newDictFilter = new IntentFilter();
|
||||||
|
newDictFilter.addAction(
|
||||||
|
DictionaryPackInstallBroadcastReceiver.NEW_DICTIONARY_INTENT_ACTION);
|
||||||
|
registerReceiver(mDictionaryPackInstallReceiver, newDictFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSuggest() {
|
private void initSuggest() {
|
||||||
|
|
|
@ -145,7 +145,7 @@ static void prof_out(void) {
|
||||||
#define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75
|
#define WORDS_WITH_EXCESSIVE_CHARACTER_OUT_OF_PROXIMITY_DEMOTION_RATE 75
|
||||||
#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60
|
#define WORDS_WITH_TRANSPOSED_CHARACTERS_DEMOTION_RATE 60
|
||||||
#define FULL_MATCHED_WORDS_PROMOTION_RATE 120
|
#define FULL_MATCHED_WORDS_PROMOTION_RATE 120
|
||||||
#define WORDS_WITH_JUST_ONE_PROXIMITY_CHARACTER_PROMOTION_RATE 110
|
#define WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE 90
|
||||||
|
|
||||||
// This should be greater than or equal to MAX_WORD_LENGTH defined in BinaryDictionary.java
|
// This should be greater than or equal to MAX_WORD_LENGTH defined in BinaryDictionary.java
|
||||||
// This is only used for the size of array. Not to be used in c functions.
|
// This is only used for the size of array. Not to be used in c functions.
|
||||||
|
|
|
@ -552,13 +552,13 @@ inline int UnigramDictionary::calculateFinalFreq(const int inputIndex, const int
|
||||||
if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0) {
|
if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0) {
|
||||||
finalFreq = capped255MultForFullMatchAccentsOrCapitalizationDifference(finalFreq);
|
finalFreq = capped255MultForFullMatchAccentsOrCapitalizationDifference(finalFreq);
|
||||||
}
|
}
|
||||||
} else if (lengthFreq / 2 == matchWeight && transposedPos < 0 && skipPos < 0
|
} else if (sameLength && transposedPos < 0 && skipPos < 0 && excessivePos < 0 && depth > 1) {
|
||||||
&& excessivePos < 0 && depth > 1) {
|
// A word with proximity corrections
|
||||||
// Full match except only one proximity correction
|
|
||||||
if (DEBUG_DICT) {
|
if (DEBUG_DICT) {
|
||||||
LOGI("Found one proximity correction.");
|
LOGI("Found one proximity correction.");
|
||||||
}
|
}
|
||||||
multiplyRate(WORDS_WITH_JUST_ONE_PROXIMITY_CHARACTER_PROMOTION_RATE, &finalFreq);
|
finalFreq *= 2;
|
||||||
|
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
|
||||||
}
|
}
|
||||||
if (sameLength) finalFreq *= FULL_WORD_MULTIPLIER;
|
if (sameLength) finalFreq *= FULL_WORD_MULTIPLIER;
|
||||||
return finalFreq;
|
return finalFreq;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,6 @@ import com.android.inputmethod.keyboard.Key;
|
||||||
import com.android.inputmethod.keyboard.KeyDetector;
|
import com.android.inputmethod.keyboard.KeyDetector;
|
||||||
import com.android.inputmethod.keyboard.KeyboardId;
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
import com.android.inputmethod.keyboard.LatinKeyboard;
|
import com.android.inputmethod.keyboard.LatinKeyboard;
|
||||||
import com.android.inputmethod.keyboard.ProximityKeyDetector;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -38,7 +37,7 @@ public class SuggestHelper {
|
||||||
// (and not try to find a dictionary provider for a specified locale)
|
// (and not try to find a dictionary provider for a specified locale)
|
||||||
mSuggest = new Suggest(context, dictionaryId, null);
|
mSuggest = new Suggest(context, dictionaryId, null);
|
||||||
mKeyboard = new LatinKeyboard(context, keyboardId);
|
mKeyboard = new LatinKeyboard(context, keyboardId);
|
||||||
mKeyDetector = new ProximityKeyDetector();
|
mKeyDetector = new KeyDetector();
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ public class SuggestHelper {
|
||||||
KeyboardId keyboardId) {
|
KeyboardId keyboardId) {
|
||||||
mSuggest = new Suggest(dictionaryPath, startOffset, length, null);
|
mSuggest = new Suggest(dictionaryPath, startOffset, length, null);
|
||||||
mKeyboard = new LatinKeyboard(context, keyboardId);
|
mKeyboard = new LatinKeyboard(context, keyboardId);
|
||||||
mKeyDetector = new ProximityKeyDetector();
|
mKeyDetector = new KeyDetector();
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +54,7 @@ public class SuggestHelper {
|
||||||
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
|
mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
|
||||||
mKeyDetector.setKeyboard(mKeyboard, 0, 0);
|
mKeyDetector.setKeyboard(mKeyboard, 0, 0);
|
||||||
mKeyDetector.setProximityCorrectionEnabled(true);
|
mKeyDetector.setProximityCorrectionEnabled(true);
|
||||||
mKeyDetector.setProximityThreshold(KeyDetector.getMostCommonKeyWidth(mKeyboard));
|
mKeyDetector.setProximityThreshold(mKeyboard.getMostCommonKeyWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCorrectionMode(int correctionMode) {
|
public void setCorrectionMode(int correctionMode) {
|
||||||
|
|
Loading…
Reference in New Issue