Merge "Move some inner static class to top class in new package"
commit
26dae3f4e8
|
@ -26,9 +26,9 @@
|
||||||
android:paddingLeft="40dip"
|
android:paddingLeft="40dip"
|
||||||
android:paddingRight="40dip"
|
android:paddingRight="40dip"
|
||||||
>
|
>
|
||||||
<com.android.inputmethod.latin.BaseKeyboardView
|
<com.android.inputmethod.keyboard.KeyboardView
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/BaseKeyboardView"
|
android:id="@+id/KeyboardView"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.android.inputmethod.latin.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/LatinkeyboardBaseView"
|
android:id="@+id/LatinkeyboardBaseView"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.android.inputmethod.latin.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.android.inputmethod.latin.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/LatinkeyboardBaseView"
|
android:id="@+id/LatinkeyboardBaseView"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.android.inputmethod.latin.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/LatinkeyboardBaseView"
|
android:id="@+id/LatinkeyboardBaseView"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.android.inputmethod.latin.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/LatinkeyboardBaseView"
|
android:id="@+id/LatinkeyboardBaseView"
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.android.inputmethod.latin.LatinKeyboardView
|
<com.android.inputmethod.keyboard.LatinKeyboardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/LatinkeyboardBaseView"
|
android:id="@+id/LatinkeyboardBaseView"
|
||||||
|
|
|
@ -25,9 +25,9 @@
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:background="@drawable/keyboard_popup_panel_background"
|
android:background="@drawable/keyboard_popup_panel_background"
|
||||||
>
|
>
|
||||||
<com.android.inputmethod.latin.BaseKeyboardView
|
<com.android.inputmethod.keyboard.KeyboardView
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/BaseKeyboardView"
|
android:id="@+id/KeyboardView"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
android:paddingLeft="16dip"
|
android:paddingLeft="16dip"
|
||||||
android:paddingRight="16dip"
|
android:paddingRight="16dip"
|
||||||
>
|
>
|
||||||
<com.android.inputmethod.latin.BaseKeyboardView
|
<com.android.inputmethod.keyboard.KeyboardView
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/BaseKeyboardView"
|
android:id="@+id/KeyboardView"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
android:paddingLeft="24dip"
|
android:paddingLeft="24dip"
|
||||||
android:paddingRight="24dip"
|
android:paddingRight="24dip"
|
||||||
>
|
>
|
||||||
<com.android.inputmethod.latin.BaseKeyboardView
|
<com.android.inputmethod.keyboard.KeyboardView
|
||||||
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||||
android:id="@+id/BaseKeyboardView"
|
android:id="@+id/KeyboardView"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboardView">
|
<declare-styleable name="KeyboardView">
|
||||||
<!-- Default KeyboardView style. -->
|
<!-- Default KeyboardView style. -->
|
||||||
<attr name="keyboardViewStyle" format="reference" />
|
<attr name="keyboardViewStyle" format="reference" />
|
||||||
|
|
||||||
|
@ -68,14 +68,14 @@
|
||||||
</attr>
|
</attr>
|
||||||
|
|
||||||
<attr name="colorScheme">
|
<attr name="colorScheme">
|
||||||
<!-- This should be aligned with BaseKeyboardView.COLOR_SCHEME_* -->
|
<!-- This should be aligned with KeyboardView.COLOR_SCHEME_* -->
|
||||||
<enum name="white" value="0" />
|
<enum name="white" value="0" />
|
||||||
<enum name="black" value="1" />
|
<enum name="black" value="1" />
|
||||||
</attr>
|
</attr>
|
||||||
|
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboard">
|
<declare-styleable name="Keyboard">
|
||||||
<!-- Default width of a key, in pixels or percentage of display width. -->
|
<!-- Default width of a key, in pixels or percentage of display width. -->
|
||||||
<attr name="keyWidth" format="dimension|fraction" />
|
<attr name="keyWidth" format="dimension|fraction" />
|
||||||
<!-- Default height of a key, in pixels or percentage of display width. -->
|
<!-- Default height of a key, in pixels or percentage of display width. -->
|
||||||
|
@ -86,7 +86,7 @@
|
||||||
<attr name="verticalGap" format="dimension|fraction" />
|
<attr name="verticalGap" format="dimension|fraction" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboard_Key">
|
<declare-styleable name="Keyboard_Key">
|
||||||
<!-- The unicode value or comma-separated values that this key outputs. -->
|
<!-- The unicode value or comma-separated values that this key outputs. -->
|
||||||
<attr name="codes" format="integer|string" />
|
<attr name="codes" format="integer|string" />
|
||||||
<!-- The XML keyboard layout of any popup keyboard. -->
|
<!-- The XML keyboard layout of any popup keyboard. -->
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
<attr name="keyLabel" format="string" />
|
<attr name="keyLabel" format="string" />
|
||||||
<!-- The key label option -->
|
<!-- The key label option -->
|
||||||
<attr name="keyLabelOption">
|
<attr name="keyLabelOption">
|
||||||
<!-- This should be aligned with BaseKeyboardView.KEY_LABEL_OPTION_* -->
|
<!-- This should be aligned with KeyboardView.KEY_LABEL_OPTION_* -->
|
||||||
<flag name="alignLeft" value="1" />
|
<flag name="alignLeft" value="1" />
|
||||||
<flag name="alignRight" value="2" />
|
<flag name="alignRight" value="2" />
|
||||||
<flag name="alignBottom" value="8" />
|
<flag name="alignBottom" value="8" />
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
<attr name="shiftedIcon" format="reference" />
|
<attr name="shiftedIcon" format="reference" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboard_Row">
|
<declare-styleable name="Keyboard_Row">
|
||||||
<!-- Row edge flags. -->
|
<!-- Row edge flags. -->
|
||||||
<attr name="rowEdgeFlags">
|
<attr name="rowEdgeFlags">
|
||||||
<!-- Row is anchored to the top of the keyboard. -->
|
<!-- Row is anchored to the top of the keyboard. -->
|
||||||
|
@ -145,12 +145,12 @@
|
||||||
</attr>
|
</attr>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboard_Include">
|
<declare-styleable name="Keyboard_Include">
|
||||||
<attr name="keyboardLayout" format="reference" />
|
<attr name="keyboardLayout" format="reference" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboard_Case">
|
<declare-styleable name="Keyboard_Case">
|
||||||
<!-- This should be aligned with KeyboardSwitcher.MODE_* -->
|
<!-- This should be aligned with KeyboardId.MODE_* -->
|
||||||
<attr name="mode">
|
<attr name="mode">
|
||||||
<enum name="text" value="0" />
|
<enum name="text" value="0" />
|
||||||
<enum name="url" value="1" />
|
<enum name="url" value="1" />
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
</attr>
|
</attr>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
<declare-styleable name="BaseKeyboard_KeyStyle">
|
<declare-styleable name="Keyboard_KeyStyle">
|
||||||
<attr name="styleName" format="string" />
|
<attr name="styleName" format="string" />
|
||||||
<attr name="parentStyle" format="string" />
|
<attr name="parentStyle" format="string" />
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<style name="BaseKeyboardView">
|
<style name="KeyboardView">
|
||||||
<item name="android:background">@drawable/keyboard_background</item>
|
<item name="android:background">@drawable/keyboard_background</item>
|
||||||
|
|
||||||
<item name="keyBackground">@drawable/btn_keyboard_key</item>
|
<item name="keyBackground">@drawable/btn_keyboard_key</item>
|
||||||
|
|
|
@ -0,0 +1,305 @@
|
||||||
|
/*
|
||||||
|
* 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 com.android.inputmethod.keyboard.KeyboardParser.ParseException;
|
||||||
|
import com.android.inputmethod.keyboard.KeyStyles.KeyStyle;
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for describing the position and characteristics of a single key in the keyboard.
|
||||||
|
*/
|
||||||
|
public class Key {
|
||||||
|
/**
|
||||||
|
* All the key codes (unicode or custom code) that this key could generate, zero'th
|
||||||
|
* being the most important.
|
||||||
|
*/
|
||||||
|
public int[] codes;
|
||||||
|
/** The unicode that this key generates in manual temporary upper case mode. */
|
||||||
|
public int manualTemporaryUpperCaseCode;
|
||||||
|
|
||||||
|
/** Label to display */
|
||||||
|
public CharSequence label;
|
||||||
|
/** Option of the label */
|
||||||
|
public int labelOption;
|
||||||
|
|
||||||
|
/** Icon to display instead of a label. Icon takes precedence over a label */
|
||||||
|
public Drawable icon;
|
||||||
|
/** Hint icon to display on the key in conjunction with the label */
|
||||||
|
public Drawable hintIcon;
|
||||||
|
/** Preview version of the icon, for the preview popup */
|
||||||
|
/**
|
||||||
|
* The hint icon to display on the key when keyboard is in manual temporary upper case
|
||||||
|
* mode.
|
||||||
|
*/
|
||||||
|
public Drawable manualTemporaryUpperCaseHintIcon;
|
||||||
|
|
||||||
|
public Drawable iconPreview;
|
||||||
|
/** Width of the key, not including the gap */
|
||||||
|
public int width;
|
||||||
|
/** Height of the key, not including the gap */
|
||||||
|
public int height;
|
||||||
|
/** The horizontal gap before this key */
|
||||||
|
public int gap;
|
||||||
|
/** Whether this key is sticky, i.e., a toggle key */
|
||||||
|
public boolean sticky;
|
||||||
|
/** X coordinate of the key in the keyboard layout */
|
||||||
|
public int x;
|
||||||
|
/** Y coordinate of the key in the keyboard layout */
|
||||||
|
public int y;
|
||||||
|
/** The current pressed state of this key */
|
||||||
|
public boolean pressed;
|
||||||
|
/** If this is a sticky key, is it on? */
|
||||||
|
public boolean on;
|
||||||
|
/** Text to output when pressed. This can be multiple characters, like ".com" */
|
||||||
|
public CharSequence text;
|
||||||
|
/** Popup characters */
|
||||||
|
public CharSequence popupCharacters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags that specify the anchoring to edges of the keyboard for detecting touch events
|
||||||
|
* that are just out of the boundary of the key. This is a bit mask of
|
||||||
|
* {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT},
|
||||||
|
* {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}.
|
||||||
|
*/
|
||||||
|
public int edgeFlags;
|
||||||
|
/** Whether this is a modifier key, such as Shift or Alt */
|
||||||
|
public boolean modifier;
|
||||||
|
/** The Keyboard that this key belongs to */
|
||||||
|
protected final Keyboard keyboard;
|
||||||
|
/**
|
||||||
|
* If this key pops up a mini keyboard, this is the resource id for the XML layout for that
|
||||||
|
* keyboard.
|
||||||
|
*/
|
||||||
|
public int popupResId;
|
||||||
|
/** Whether this key repeats itself when held down */
|
||||||
|
public boolean repeatable;
|
||||||
|
|
||||||
|
|
||||||
|
private final static int[] KEY_STATE_NORMAL_ON = {
|
||||||
|
android.R.attr.state_checkable,
|
||||||
|
android.R.attr.state_checked
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static int[] KEY_STATE_PRESSED_ON = {
|
||||||
|
android.R.attr.state_pressed,
|
||||||
|
android.R.attr.state_checkable,
|
||||||
|
android.R.attr.state_checked
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static int[] KEY_STATE_NORMAL_OFF = {
|
||||||
|
android.R.attr.state_checkable
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static int[] KEY_STATE_PRESSED_OFF = {
|
||||||
|
android.R.attr.state_pressed,
|
||||||
|
android.R.attr.state_checkable
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static int[] KEY_STATE_NORMAL = {
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static int[] KEY_STATE_PRESSED = {
|
||||||
|
android.R.attr.state_pressed
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Create an empty key with no attributes. */
|
||||||
|
public Key(Row parent) {
|
||||||
|
keyboard = parent.parent;
|
||||||
|
height = parent.defaultHeight;
|
||||||
|
gap = parent.defaultHorizontalGap;
|
||||||
|
width = parent.defaultWidth - gap;
|
||||||
|
edgeFlags = parent.rowEdgeFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a key with the given top-left coordinate and extract its attributes from
|
||||||
|
* the XML parser.
|
||||||
|
* @param res resources associated with the caller's context
|
||||||
|
* @param parent the row that this key belongs to. The row must already be attached to
|
||||||
|
* a {@link Keyboard}.
|
||||||
|
* @param x the x coordinate of the top-left
|
||||||
|
* @param y the y coordinate of the top-left
|
||||||
|
* @param parser the XML parser containing the attributes for this key
|
||||||
|
*/
|
||||||
|
public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser,
|
||||||
|
KeyStyles keyStyles) {
|
||||||
|
this(parent);
|
||||||
|
|
||||||
|
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
|
R.styleable.Keyboard);
|
||||||
|
height = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_keyHeight,
|
||||||
|
keyboard.mDisplayHeight, parent.defaultHeight);
|
||||||
|
gap = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_horizontalGap,
|
||||||
|
keyboard.mDisplayWidth, parent.defaultHorizontalGap);
|
||||||
|
width = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_keyWidth,
|
||||||
|
keyboard.mDisplayWidth, parent.defaultWidth) - gap;
|
||||||
|
a.recycle();
|
||||||
|
|
||||||
|
a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.Keyboard_Key);
|
||||||
|
|
||||||
|
final KeyStyle style;
|
||||||
|
if (a.hasValue(R.styleable.Keyboard_Key_keyStyle)) {
|
||||||
|
String styleName = a.getString(R.styleable.Keyboard_Key_keyStyle);
|
||||||
|
style = keyStyles.getKeyStyle(styleName);
|
||||||
|
if (style == null)
|
||||||
|
throw new ParseException("Unknown key style: " + styleName, parser);
|
||||||
|
} else {
|
||||||
|
style = keyStyles.getEmptyKeyStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Horizontal gap is divided equally to both sides of the key.
|
||||||
|
this.x = x + gap / 2;
|
||||||
|
this.y = y;
|
||||||
|
|
||||||
|
codes = style.getIntArray(a, R.styleable.Keyboard_Key_codes);
|
||||||
|
iconPreview = style.getDrawable(a, R.styleable.Keyboard_Key_iconPreview);
|
||||||
|
Keyboard.setDefaultBounds(iconPreview);
|
||||||
|
popupCharacters = style.getText(a, R.styleable.Keyboard_Key_popupCharacters);
|
||||||
|
popupResId = style.getResourceId(a, R.styleable.Keyboard_Key_popupKeyboard, 0);
|
||||||
|
repeatable = style.getBoolean(a, R.styleable.Keyboard_Key_isRepeatable, false);
|
||||||
|
modifier = style.getBoolean(a, R.styleable.Keyboard_Key_isModifier, false);
|
||||||
|
sticky = style.getBoolean(a, R.styleable.Keyboard_Key_isSticky, false);
|
||||||
|
edgeFlags = style.getFlag(a, R.styleable.Keyboard_Key_keyEdgeFlags, 0);
|
||||||
|
edgeFlags |= parent.rowEdgeFlags;
|
||||||
|
|
||||||
|
icon = style.getDrawable(a, R.styleable.Keyboard_Key_keyIcon);
|
||||||
|
Keyboard.setDefaultBounds(icon);
|
||||||
|
hintIcon = style.getDrawable(a, R.styleable.Keyboard_Key_keyHintIcon);
|
||||||
|
Keyboard.setDefaultBounds(hintIcon);
|
||||||
|
manualTemporaryUpperCaseHintIcon = style.getDrawable(a,
|
||||||
|
R.styleable.Keyboard_Key_manualTemporaryUpperCaseHintIcon);
|
||||||
|
Keyboard.setDefaultBounds(manualTemporaryUpperCaseHintIcon);
|
||||||
|
|
||||||
|
label = style.getText(a, R.styleable.Keyboard_Key_keyLabel);
|
||||||
|
labelOption = style.getFlag(a, R.styleable.Keyboard_Key_keyLabelOption, 0);
|
||||||
|
manualTemporaryUpperCaseCode = style.getInt(a,
|
||||||
|
R.styleable.Keyboard_Key_manualTemporaryUpperCaseCode, 0);
|
||||||
|
text = style.getText(a, R.styleable.Keyboard_Key_keyOutputText);
|
||||||
|
final Drawable shiftedIcon = style.getDrawable(a,
|
||||||
|
R.styleable.Keyboard_Key_shiftedIcon);
|
||||||
|
if (shiftedIcon != null)
|
||||||
|
keyboard.getShiftedIcons().put(this, shiftedIcon);
|
||||||
|
|
||||||
|
if (codes == null && !TextUtils.isEmpty(label)) {
|
||||||
|
codes = new int[] { label.charAt(0) };
|
||||||
|
}
|
||||||
|
a.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs the key that it has been pressed, in case it needs to change its appearance or
|
||||||
|
* state.
|
||||||
|
* @see #onReleased(boolean)
|
||||||
|
*/
|
||||||
|
public void onPressed() {
|
||||||
|
pressed = !pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the pressed state of the key. If it is a sticky key, it will also change the
|
||||||
|
* toggled state of the key if the finger was release inside.
|
||||||
|
* @param inside whether the finger was released inside the key
|
||||||
|
* @see #onPressed()
|
||||||
|
*/
|
||||||
|
public void onReleased(boolean inside) {
|
||||||
|
pressed = !pressed;
|
||||||
|
if (sticky) {
|
||||||
|
on = !on;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects if a point falls inside this key.
|
||||||
|
* @param x the x-coordinate of the point
|
||||||
|
* @param y the y-coordinate of the point
|
||||||
|
* @return whether or not the point falls inside the key. If the key is attached to an
|
||||||
|
* edge, it will assume that all points between the key and the edge are considered to be
|
||||||
|
* inside the key.
|
||||||
|
*/
|
||||||
|
public boolean isInside(int x, int y) {
|
||||||
|
boolean leftEdge = (edgeFlags & Keyboard.EDGE_LEFT) > 0;
|
||||||
|
boolean rightEdge = (edgeFlags & Keyboard.EDGE_RIGHT) > 0;
|
||||||
|
boolean topEdge = (edgeFlags & Keyboard.EDGE_TOP) > 0;
|
||||||
|
boolean bottomEdge = (edgeFlags & Keyboard.EDGE_BOTTOM) > 0;
|
||||||
|
if ((x >= this.x || (leftEdge && x <= this.x + this.width))
|
||||||
|
&& (x < this.x + this.width || (rightEdge && x >= this.x))
|
||||||
|
&& (y >= this.y || (topEdge && y <= this.y + this.height))
|
||||||
|
&& (y < this.y + this.height || (bottomEdge && y >= this.y))) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the square of the distance to the nearest edge of the key and the given point.
|
||||||
|
* @param x the x-coordinate of the point
|
||||||
|
* @param y the y-coordinate of the point
|
||||||
|
* @return the square of the distance of the point from the nearest edge of the key
|
||||||
|
*/
|
||||||
|
public int squaredDistanceToEdge(int x, int y) {
|
||||||
|
final int left = this.x;
|
||||||
|
final int right = left + this.width;
|
||||||
|
final int top = this.y;
|
||||||
|
final int bottom = top + this.height;
|
||||||
|
final int edgeX = x < left ? left : (x > right ? right : x);
|
||||||
|
final int edgeY = y < top ? top : (y > bottom ? bottom : y);
|
||||||
|
final int dx = x - edgeX;
|
||||||
|
final int dy = y - edgeY;
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the drawable state for the key, based on the current state and type of the key.
|
||||||
|
* @return the drawable state of the key.
|
||||||
|
* @see android.graphics.drawable.StateListDrawable#setState(int[])
|
||||||
|
*/
|
||||||
|
public int[] getCurrentDrawableState() {
|
||||||
|
int[] states = KEY_STATE_NORMAL;
|
||||||
|
|
||||||
|
if (on) {
|
||||||
|
if (pressed) {
|
||||||
|
states = KEY_STATE_PRESSED_ON;
|
||||||
|
} else {
|
||||||
|
states = KEY_STATE_NORMAL_ON;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sticky) {
|
||||||
|
if (pressed) {
|
||||||
|
states = KEY_STATE_PRESSED_OFF;
|
||||||
|
} else {
|
||||||
|
states = KEY_STATE_NORMAL_OFF;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pressed) {
|
||||||
|
states = KEY_STATE_PRESSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,15 +14,15 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
abstract class KeyDetector {
|
public abstract class KeyDetector {
|
||||||
protected BaseKeyboard mKeyboard;
|
public static final int NOT_A_KEY = -1;
|
||||||
|
|
||||||
|
protected Keyboard mKeyboard;
|
||||||
|
|
||||||
private Key[] mKeys;
|
private Key[] mKeys;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ abstract class KeyDetector {
|
||||||
|
|
||||||
protected int mProximityThresholdSquare;
|
protected int mProximityThresholdSquare;
|
||||||
|
|
||||||
public Key[] setKeyboard(BaseKeyboard keyboard, float correctionX, float correctionY) {
|
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;
|
||||||
|
@ -84,7 +84,7 @@ abstract class KeyDetector {
|
||||||
*/
|
*/
|
||||||
public int[] newCodeArray() {
|
public int[] newCodeArray() {
|
||||||
int[] codes = new int[getMaxNearbyKeys()];
|
int[] codes = new int[getMaxNearbyKeys()];
|
||||||
Arrays.fill(codes, BaseKeyboardView.NOT_A_KEY);
|
Arrays.fill(codes, NOT_A_KEY);
|
||||||
return codes;
|
return codes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboardParser.ParseException;
|
import com.android.inputmethod.keyboard.KeyboardParser.ParseException;
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.content.res.XmlResourceParser;
|
import android.content.res.XmlResourceParser;
|
||||||
|
@ -48,30 +49,37 @@ public class KeyStyles {
|
||||||
private EmptyKeyStyle() {
|
private EmptyKeyStyle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int[] getIntArray(TypedArray a, int index) {
|
public int[] getIntArray(TypedArray a, int index) {
|
||||||
return parseIntArray(a, index);
|
return parseIntArray(a, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Drawable getDrawable(TypedArray a, int index) {
|
public Drawable getDrawable(TypedArray a, int index) {
|
||||||
return a.getDrawable(index);
|
return a.getDrawable(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CharSequence getText(TypedArray a, int index) {
|
public CharSequence getText(TypedArray a, int index) {
|
||||||
return a.getText(index);
|
return a.getText(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getResourceId(TypedArray a, int index, int defaultValue) {
|
public int getResourceId(TypedArray a, int index, int defaultValue) {
|
||||||
return a.getResourceId(index, defaultValue);
|
return a.getResourceId(index, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getInt(TypedArray a, int index, int defaultValue) {
|
public int getInt(TypedArray a, int index, int defaultValue) {
|
||||||
return a.getInt(index, defaultValue);
|
return a.getInt(index, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getFlag(TypedArray a, int index, int defaultValue) {
|
public int getFlag(TypedArray a, int index, int defaultValue) {
|
||||||
return a.getInt(index, defaultValue);
|
return a.getInt(index, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
|
public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
|
||||||
return a.getBoolean(index, defaultValue);
|
return a.getBoolean(index, defaultValue);
|
||||||
}
|
}
|
||||||
|
@ -156,18 +164,18 @@ public class KeyStyles {
|
||||||
|
|
||||||
private void parseKeyStyleAttributes(TypedArray a) {
|
private void parseKeyStyleAttributes(TypedArray a) {
|
||||||
// TODO: Currently not all Key attributes can be declared as style.
|
// TODO: Currently not all Key attributes can be declared as style.
|
||||||
readIntArray(a, R.styleable.BaseKeyboard_Key_codes);
|
readIntArray(a, R.styleable.Keyboard_Key_codes);
|
||||||
readText(a, R.styleable.BaseKeyboard_Key_keyLabel);
|
readText(a, R.styleable.Keyboard_Key_keyLabel);
|
||||||
readFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption);
|
readFlag(a, R.styleable.Keyboard_Key_keyLabelOption);
|
||||||
readText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
|
readText(a, R.styleable.Keyboard_Key_keyOutputText);
|
||||||
readDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
|
readDrawable(a, R.styleable.Keyboard_Key_keyIcon);
|
||||||
readDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
|
readDrawable(a, R.styleable.Keyboard_Key_iconPreview);
|
||||||
readDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
|
readDrawable(a, R.styleable.Keyboard_Key_keyHintIcon);
|
||||||
readDrawable(a, R.styleable.BaseKeyboard_Key_shiftedIcon);
|
readDrawable(a, R.styleable.Keyboard_Key_shiftedIcon);
|
||||||
readResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard);
|
readResourceId(a, R.styleable.Keyboard_Key_popupKeyboard);
|
||||||
readBoolean(a, R.styleable.BaseKeyboard_Key_isModifier);
|
readBoolean(a, R.styleable.Keyboard_Key_isModifier);
|
||||||
readBoolean(a, R.styleable.BaseKeyboard_Key_isSticky);
|
readBoolean(a, R.styleable.Keyboard_Key_isSticky);
|
||||||
readBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable);
|
readBoolean(a, R.styleable.Keyboard_Key_isRepeatable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readDrawable(TypedArray a, int index) {
|
private void readDrawable(TypedArray a, int index) {
|
||||||
|
@ -211,14 +219,14 @@ public class KeyStyles {
|
||||||
|
|
||||||
public void parseKeyStyleAttributes(TypedArray a, TypedArray keyAttrs,
|
public void parseKeyStyleAttributes(TypedArray a, TypedArray keyAttrs,
|
||||||
XmlResourceParser parser) {
|
XmlResourceParser parser) {
|
||||||
String styleName = a.getString(R.styleable.BaseKeyboard_KeyStyle_styleName);
|
String styleName = a.getString(R.styleable.Keyboard_KeyStyle_styleName);
|
||||||
if (mStyles.containsKey(styleName))
|
if (mStyles.containsKey(styleName))
|
||||||
throw new ParseException("duplicate key style declared: " + styleName, parser);
|
throw new ParseException("duplicate key style declared: " + styleName, parser);
|
||||||
|
|
||||||
final DeclaredKeyStyle style = new DeclaredKeyStyle();
|
final DeclaredKeyStyle style = new DeclaredKeyStyle();
|
||||||
if (a.hasValue(R.styleable.BaseKeyboard_KeyStyle_parentStyle)) {
|
if (a.hasValue(R.styleable.Keyboard_KeyStyle_parentStyle)) {
|
||||||
String parentStyle = a.getString(
|
String parentStyle = a.getString(
|
||||||
R.styleable.BaseKeyboard_KeyStyle_parentStyle);
|
R.styleable.Keyboard_KeyStyle_parentStyle);
|
||||||
final DeclaredKeyStyle parent = mStyles.get(parentStyle);
|
final DeclaredKeyStyle parent = mStyles.get(parentStyle);
|
||||||
if (parent == null)
|
if (parent == null)
|
||||||
throw new ParseException("Unknown parentStyle " + parent, parser);
|
throw new ParseException("Unknown parentStyle " + parent, parser);
|
|
@ -0,0 +1,386 @@
|
||||||
|
/*
|
||||||
|
* 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 com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
|
||||||
|
* consists of rows of keys.
|
||||||
|
* <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
|
||||||
|
* <pre>
|
||||||
|
* <Keyboard
|
||||||
|
* latin:keyWidth="%10p"
|
||||||
|
* latin:keyHeight="50px"
|
||||||
|
* latin:horizontalGap="2px"
|
||||||
|
* latin:verticalGap="2px" >
|
||||||
|
* <Row latin:keyWidth="32px" >
|
||||||
|
* <Key latin:keyLabel="A" />
|
||||||
|
* ...
|
||||||
|
* </Row>
|
||||||
|
* ...
|
||||||
|
* </Keyboard>
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public class Keyboard {
|
||||||
|
|
||||||
|
static final String TAG = "Keyboard";
|
||||||
|
|
||||||
|
public static final int EDGE_LEFT = 0x01;
|
||||||
|
public static final int EDGE_RIGHT = 0x02;
|
||||||
|
public static final int EDGE_TOP = 0x04;
|
||||||
|
public static final int EDGE_BOTTOM = 0x08;
|
||||||
|
|
||||||
|
public static final int KEYCODE_SHIFT = -1;
|
||||||
|
public static final int KEYCODE_MODE_CHANGE = -2;
|
||||||
|
public static final int KEYCODE_CANCEL = -3;
|
||||||
|
public static final int KEYCODE_DONE = -4;
|
||||||
|
public static final int KEYCODE_DELETE = -5;
|
||||||
|
public static final int KEYCODE_ALT = -6;
|
||||||
|
|
||||||
|
/** Horizontal gap default for all rows */
|
||||||
|
int mDefaultHorizontalGap;
|
||||||
|
|
||||||
|
/** Default key width */
|
||||||
|
int mDefaultWidth;
|
||||||
|
|
||||||
|
/** Default key height */
|
||||||
|
int mDefaultHeight;
|
||||||
|
|
||||||
|
/** Default gap between rows */
|
||||||
|
int mDefaultVerticalGap;
|
||||||
|
|
||||||
|
/** Is the keyboard in the shifted state */
|
||||||
|
private boolean mShifted;
|
||||||
|
|
||||||
|
/** List of shift keys in this keyboard */
|
||||||
|
private final List<Key> mShiftKeys = new ArrayList<Key>();
|
||||||
|
|
||||||
|
/** List of shift keys and its shifted state icon */
|
||||||
|
private final HashMap<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>();
|
||||||
|
|
||||||
|
/** Total height of the keyboard, including the padding and keys */
|
||||||
|
private int mTotalHeight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total width of the keyboard, including left side gaps and keys, but not any gaps on the
|
||||||
|
* right side.
|
||||||
|
*/
|
||||||
|
private int mTotalWidth;
|
||||||
|
|
||||||
|
/** List of keys in this keyboard */
|
||||||
|
private final List<Key> mKeys = new ArrayList<Key>();
|
||||||
|
|
||||||
|
/** Width of the screen available to fit the keyboard */
|
||||||
|
final int mDisplayWidth;
|
||||||
|
|
||||||
|
/** Height of the screen */
|
||||||
|
final int mDisplayHeight;
|
||||||
|
|
||||||
|
protected final KeyboardId mId;
|
||||||
|
|
||||||
|
// Variables for pre-computing nearest keys.
|
||||||
|
|
||||||
|
public final int GRID_WIDTH;
|
||||||
|
public final int GRID_HEIGHT;
|
||||||
|
private final int GRID_SIZE;
|
||||||
|
private int mCellWidth;
|
||||||
|
private int mCellHeight;
|
||||||
|
private int[][] mGridNeighbors;
|
||||||
|
private int mProximityThreshold;
|
||||||
|
private static int[] EMPTY_INT_ARRAY = new int[0];
|
||||||
|
/** Number of key widths from current touch point to search for nearest keys. */
|
||||||
|
private static float SEARCH_DISTANCE = 1.2f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a keyboard from the given xml key layout file.
|
||||||
|
* @param context the application or service context
|
||||||
|
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||||
|
*/
|
||||||
|
public Keyboard(Context context, int xmlLayoutResId) {
|
||||||
|
this(context, xmlLayoutResId, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a keyboard from the given keyboard identifier.
|
||||||
|
* @param context the application or service context
|
||||||
|
* @param id keyboard identifier
|
||||||
|
*/
|
||||||
|
public Keyboard(Context context, KeyboardId id) {
|
||||||
|
this(context, id.getXmlId(), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a keyboard from the given xml key layout file.
|
||||||
|
* @param context the application or service context
|
||||||
|
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
||||||
|
* @param id keyboard identifier
|
||||||
|
*/
|
||||||
|
private Keyboard(Context context, int xmlLayoutResId, KeyboardId id) {
|
||||||
|
this(context, xmlLayoutResId, id,
|
||||||
|
context.getResources().getDisplayMetrics().widthPixels,
|
||||||
|
context.getResources().getDisplayMetrics().heightPixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Keyboard(Context context, int xmlLayoutResId, KeyboardId id, int width,
|
||||||
|
int height) {
|
||||||
|
Resources res = context.getResources();
|
||||||
|
GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
|
||||||
|
GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
|
||||||
|
GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
|
||||||
|
|
||||||
|
mDisplayWidth = width;
|
||||||
|
mDisplayHeight = height;
|
||||||
|
|
||||||
|
mDefaultHorizontalGap = 0;
|
||||||
|
setKeyWidth(mDisplayWidth / 10);
|
||||||
|
mDefaultVerticalGap = 0;
|
||||||
|
mDefaultHeight = mDefaultWidth;
|
||||||
|
mId = id;
|
||||||
|
loadKeyboard(context, xmlLayoutResId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Creates a blank keyboard from the given resource file and populates it with the specified
|
||||||
|
* characters in left-to-right, top-to-bottom fashion, using the specified number of columns.
|
||||||
|
* </p>
|
||||||
|
* <p>If the specified number of columns is -1, then the keyboard will fit as many keys as
|
||||||
|
* possible in each row.</p>
|
||||||
|
* @param context the application or service context
|
||||||
|
* @param layoutTemplateResId the layout template file, containing no keys.
|
||||||
|
* @param characters the list of characters to display on the keyboard. One key will be created
|
||||||
|
* for each character.
|
||||||
|
* @param columns the number of columns of keys to display. If this number is greater than the
|
||||||
|
* number of keys that can fit in a row, it will be ignored. If this number is -1, the
|
||||||
|
* keyboard will fit as many keys as possible in each row.
|
||||||
|
*/
|
||||||
|
public Keyboard(Context context, int layoutTemplateResId,
|
||||||
|
CharSequence characters, int columns, int horizontalPadding) {
|
||||||
|
this(context, layoutTemplateResId);
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int column = 0;
|
||||||
|
mTotalWidth = 0;
|
||||||
|
|
||||||
|
Row row = new Row(this);
|
||||||
|
row.defaultHeight = mDefaultHeight;
|
||||||
|
row.defaultWidth = mDefaultWidth;
|
||||||
|
row.defaultHorizontalGap = mDefaultHorizontalGap;
|
||||||
|
row.verticalGap = mDefaultVerticalGap;
|
||||||
|
row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
|
||||||
|
final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
|
||||||
|
for (int i = 0; i < characters.length(); i++) {
|
||||||
|
char c = characters.charAt(i);
|
||||||
|
if (column >= maxColumns
|
||||||
|
|| x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
|
||||||
|
x = 0;
|
||||||
|
y += mDefaultVerticalGap + mDefaultHeight;
|
||||||
|
column = 0;
|
||||||
|
}
|
||||||
|
final Key key = new Key(row);
|
||||||
|
// Horizontal gap is divided equally to both sides of the key.
|
||||||
|
key.x = x + key.gap / 2;
|
||||||
|
key.y = y;
|
||||||
|
key.label = String.valueOf(c);
|
||||||
|
key.codes = new int[] { c };
|
||||||
|
column++;
|
||||||
|
x += key.width + key.gap;
|
||||||
|
mKeys.add(key);
|
||||||
|
if (x > mTotalWidth) {
|
||||||
|
mTotalWidth = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mTotalHeight = y + mDefaultHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyboardId getKeyboardId() {
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Key> getKeys() {
|
||||||
|
return mKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getHorizontalGap() {
|
||||||
|
return mDefaultHorizontalGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setHorizontalGap(int gap) {
|
||||||
|
mDefaultHorizontalGap = gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getVerticalGap() {
|
||||||
|
return mDefaultVerticalGap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setVerticalGap(int gap) {
|
||||||
|
mDefaultVerticalGap = gap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getKeyHeight() {
|
||||||
|
return mDefaultHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setKeyHeight(int height) {
|
||||||
|
mDefaultHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getKeyWidth() {
|
||||||
|
return mDefaultWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setKeyWidth(int width) {
|
||||||
|
mDefaultWidth = width;
|
||||||
|
final int threshold = (int) (width * SEARCH_DISTANCE);
|
||||||
|
mProximityThreshold = threshold * threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total height of the keyboard
|
||||||
|
* @return the total height of the keyboard
|
||||||
|
*/
|
||||||
|
public int getHeight() {
|
||||||
|
return mTotalHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinWidth() {
|
||||||
|
return mTotalWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeyboardHeight() {
|
||||||
|
return mDisplayHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeyboardWidth() {
|
||||||
|
return mDisplayWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setShifted(boolean shiftState) {
|
||||||
|
for (final Key key : mShiftKeys) {
|
||||||
|
key.on = shiftState;
|
||||||
|
}
|
||||||
|
if (mShifted != shiftState) {
|
||||||
|
mShifted = shiftState;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShiftedOrShiftLocked() {
|
||||||
|
return mShifted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Key> getShiftKeys() {
|
||||||
|
return mShiftKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Key, Drawable> getShiftedIcons() {
|
||||||
|
return mShiftedIcons;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeNearestNeighbors() {
|
||||||
|
// Round-up so we don't have any pixels outside the grid
|
||||||
|
mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
|
||||||
|
mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
|
||||||
|
mGridNeighbors = new int[GRID_SIZE][];
|
||||||
|
final int[] indices = new int[mKeys.size()];
|
||||||
|
final int gridWidth = GRID_WIDTH * mCellWidth;
|
||||||
|
final int gridHeight = GRID_HEIGHT * mCellHeight;
|
||||||
|
final int threshold = mProximityThreshold;
|
||||||
|
for (int x = 0; x < gridWidth; x += mCellWidth) {
|
||||||
|
for (int y = 0; y < gridHeight; y += mCellHeight) {
|
||||||
|
final int centerX = x + mCellWidth / 2;
|
||||||
|
final int centerY = y + mCellHeight / 2;
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < mKeys.size(); i++) {
|
||||||
|
final Key key = mKeys.get(i);
|
||||||
|
if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
|
||||||
|
indices[count++] = i;
|
||||||
|
}
|
||||||
|
final int[] cell = new int[count];
|
||||||
|
System.arraycopy(indices, 0, cell, 0, count);
|
||||||
|
mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the indices of the keys that are closest to the given point.
|
||||||
|
* @param x the x-coordinate of the point
|
||||||
|
* @param y the y-coordinate of the point
|
||||||
|
* @return the array of integer indices for the nearest keys to the given point. If the given
|
||||||
|
* point is out of range, then an array of size zero is returned.
|
||||||
|
*/
|
||||||
|
public int[] getNearestKeys(int x, int y) {
|
||||||
|
if (mGridNeighbors == null) computeNearestNeighbors();
|
||||||
|
if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
|
||||||
|
int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
|
||||||
|
if (index < GRID_SIZE) {
|
||||||
|
return mGridNeighbors[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EMPTY_INT_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO should be private
|
||||||
|
protected Row createRowFromXml(Resources res, XmlResourceParser parser) {
|
||||||
|
return new Row(res, this, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO should be private
|
||||||
|
protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
|
||||||
|
XmlResourceParser parser, KeyStyles keyStyles) {
|
||||||
|
return new Key(res, parent, x, y, parser, keyStyles);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadKeyboard(Context context, int xmlLayoutResId) {
|
||||||
|
try {
|
||||||
|
final Resources res = context.getResources();
|
||||||
|
KeyboardParser parser = new KeyboardParser(this, res);
|
||||||
|
parser.parseKeyboard(res.getXml(xmlLayoutResId));
|
||||||
|
// mTotalWidth is the width of this keyboard which is maximum width of row.
|
||||||
|
mTotalWidth = parser.getMaxRowWidth();
|
||||||
|
mTotalHeight = parser.getTotalHeight();
|
||||||
|
} catch (XmlPullParserException e) {
|
||||||
|
Log.w(TAG, "keyboard XML parse error: " + e);
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, "keyboard XML parse error: " + e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void setDefaultBounds(Drawable drawable) {
|
||||||
|
if (drawable != null)
|
||||||
|
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
|
||||||
|
drawable.getIntrinsicHeight());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public interface KeyboardActionListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user presses a key. This is sent before the
|
||||||
|
* {@link #onKey} is called. For keys that repeat, this is only
|
||||||
|
* called once.
|
||||||
|
*
|
||||||
|
* @param primaryCode
|
||||||
|
* the unicode of the key being pressed. If the touch is
|
||||||
|
* not on a valid key, the value will be zero.
|
||||||
|
*/
|
||||||
|
void onPress(int primaryCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user releases a key. This is sent after the
|
||||||
|
* {@link #onKey} is called. For keys that repeat, this is only
|
||||||
|
* called once.
|
||||||
|
*
|
||||||
|
* @param primaryCode
|
||||||
|
* the code of the key that was released
|
||||||
|
*/
|
||||||
|
void onRelease(int primaryCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a key press to the listener.
|
||||||
|
*
|
||||||
|
* @param primaryCode
|
||||||
|
* this is the key that was pressed
|
||||||
|
* @param keyCodes
|
||||||
|
* the codes for all the possible alternative keys with
|
||||||
|
* the primary code being the first. If the primary key
|
||||||
|
* code is a single character such as an alphabet or
|
||||||
|
* number or symbol, the alternatives will include other
|
||||||
|
* characters that may be on the same key or adjacent
|
||||||
|
* keys. These codes are useful to correct for
|
||||||
|
* accidental presses of a key adjacent to the intended
|
||||||
|
* key.
|
||||||
|
* @param x
|
||||||
|
* x-coordinate pixel of touched event. If onKey is not called by onTouchEvent,
|
||||||
|
* the value should be NOT_A_TOUCH_COORDINATE.
|
||||||
|
* @param y
|
||||||
|
* y-coordinate pixel of touched event. If onKey is not called by onTouchEvent,
|
||||||
|
* the value should be NOT_A_TOUCH_COORDINATE.
|
||||||
|
*/
|
||||||
|
void onKey(int primaryCode, int[] keyCodes, int x, int y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a sequence of characters to the listener.
|
||||||
|
*
|
||||||
|
* @param text
|
||||||
|
* the sequence of characters to be displayed.
|
||||||
|
*/
|
||||||
|
void onText(CharSequence text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when user released a finger outside any key.
|
||||||
|
*/
|
||||||
|
void onCancel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user quickly moves the finger from right to
|
||||||
|
* left.
|
||||||
|
*/
|
||||||
|
void swipeLeft();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user quickly moves the finger from left to
|
||||||
|
* right.
|
||||||
|
*/
|
||||||
|
void swipeRight();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user quickly moves the finger from up to down.
|
||||||
|
*/
|
||||||
|
void swipeDown();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user quickly moves the finger from down to up.
|
||||||
|
*/
|
||||||
|
void swipeUp();
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* 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 com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the parameters necessary to construct a new LatinKeyboard,
|
||||||
|
* which also serve as a unique identifier for each keyboard type.
|
||||||
|
*/
|
||||||
|
public class KeyboardId {
|
||||||
|
public static final int MODE_TEXT = 0;
|
||||||
|
public static final int MODE_URL = 1;
|
||||||
|
public static final int MODE_EMAIL = 2;
|
||||||
|
public static final int MODE_IM = 3;
|
||||||
|
public static final int MODE_WEB = 4;
|
||||||
|
public static final int MODE_PHONE = 5;
|
||||||
|
public static final int MODE_NUMBER = 6;
|
||||||
|
|
||||||
|
public final Locale mLocale;
|
||||||
|
public final int mOrientation;
|
||||||
|
public final int mMode;
|
||||||
|
public final int mXmlId;
|
||||||
|
public final int mColorScheme;
|
||||||
|
public final boolean mHasSettingsKey;
|
||||||
|
public final boolean mVoiceKeyEnabled;
|
||||||
|
public final boolean mHasVoiceKey;
|
||||||
|
public final int mImeOptions;
|
||||||
|
public final boolean mEnableShiftLock;
|
||||||
|
|
||||||
|
private final int mHashCode;
|
||||||
|
|
||||||
|
public KeyboardId(Locale locale, int orientation, int mode,
|
||||||
|
int xmlId, int colorScheme, boolean hasSettingsKey, boolean voiceKeyEnabled,
|
||||||
|
boolean hasVoiceKey, int imeOptions, boolean enableShiftLock) {
|
||||||
|
this.mLocale = locale;
|
||||||
|
this.mOrientation = orientation;
|
||||||
|
this.mMode = mode;
|
||||||
|
this.mXmlId = xmlId;
|
||||||
|
this.mColorScheme = colorScheme;
|
||||||
|
this.mHasSettingsKey = hasSettingsKey;
|
||||||
|
this.mVoiceKeyEnabled = voiceKeyEnabled;
|
||||||
|
this.mHasVoiceKey = hasVoiceKey;
|
||||||
|
// We are interested only in IME_MASK_ACTION enum value and IME_FLAG_NO_ENTER_ACTION.
|
||||||
|
this.mImeOptions = imeOptions
|
||||||
|
& (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
|
||||||
|
this.mEnableShiftLock = enableShiftLock;
|
||||||
|
|
||||||
|
this.mHashCode = Arrays.hashCode(new Object[] {
|
||||||
|
locale,
|
||||||
|
orientation,
|
||||||
|
mode,
|
||||||
|
xmlId,
|
||||||
|
colorScheme,
|
||||||
|
hasSettingsKey,
|
||||||
|
voiceKeyEnabled,
|
||||||
|
hasVoiceKey,
|
||||||
|
imeOptions,
|
||||||
|
enableShiftLock,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getXmlId() {
|
||||||
|
return mXmlId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAlphabetMode() {
|
||||||
|
return mXmlId == R.xml.kbd_qwerty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object other) {
|
||||||
|
return other instanceof KeyboardId && equals((KeyboardId) other);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean equals(KeyboardId other) {
|
||||||
|
return other.mLocale.equals(this.mLocale)
|
||||||
|
&& other.mOrientation == this.mOrientation
|
||||||
|
&& other.mMode == this.mMode
|
||||||
|
&& other.mXmlId == this.mXmlId
|
||||||
|
&& other.mColorScheme == this.mColorScheme
|
||||||
|
&& other.mHasSettingsKey == this.mHasSettingsKey
|
||||||
|
&& other.mVoiceKeyEnabled == this.mVoiceKeyEnabled
|
||||||
|
&& other.mHasVoiceKey == this.mHasVoiceKey
|
||||||
|
&& other.mImeOptions == this.mImeOptions
|
||||||
|
&& other.mEnableShiftLock == this.mEnableShiftLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return mHashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("[%s %s %5s imeOptions=0x%08x xml=0x%08x %s%s%s%s%s]",
|
||||||
|
mLocale,
|
||||||
|
(mOrientation == 1 ? "port" : "land"),
|
||||||
|
modeName(mMode),
|
||||||
|
mImeOptions,
|
||||||
|
mXmlId,
|
||||||
|
colorSchemeName(mColorScheme),
|
||||||
|
(mHasSettingsKey ? " hasSettingsKey" : ""),
|
||||||
|
(mVoiceKeyEnabled ? " voiceKeyEnabled" : ""),
|
||||||
|
(mHasVoiceKey ? " hasVoiceKey" : ""),
|
||||||
|
(mEnableShiftLock ? " enableShiftLock" : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String modeName(int mode) {
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_TEXT: return "text";
|
||||||
|
case MODE_URL: return "url";
|
||||||
|
case MODE_EMAIL: return "email";
|
||||||
|
case MODE_IM: return "im";
|
||||||
|
case MODE_WEB: return "web";
|
||||||
|
case MODE_PHONE: return "phone";
|
||||||
|
case MODE_NUMBER: return "number";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String colorSchemeName(int colorScheme) {
|
||||||
|
switch (colorScheme) {
|
||||||
|
case KeyboardView.COLOR_SCHEME_WHITE: return "white";
|
||||||
|
case KeyboardView.COLOR_SCHEME_BLACK: return "black";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,11 +14,9 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Row;
|
|
||||||
import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ import java.util.List;
|
||||||
/**
|
/**
|
||||||
* Parser for BaseKeyboard.
|
* Parser for BaseKeyboard.
|
||||||
*
|
*
|
||||||
* This class parses Keyboard XML file and fill out keys in BaseKeyboard.
|
* This class parses Keyboard XML file and fill out keys in Keyboard.
|
||||||
* The Keyboard XML file looks like:
|
* The Keyboard XML file looks like:
|
||||||
* <pre>
|
* <pre>
|
||||||
* >!-- xml/keyboard.xml --<
|
* >!-- xml/keyboard.xml --<
|
||||||
|
@ -102,8 +100,8 @@ import java.util.List;
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class BaseKeyboardParser {
|
public class KeyboardParser {
|
||||||
private static final String TAG = "BaseKeyboardParser";
|
private static final String TAG = "KeyboardParser";
|
||||||
private static final boolean DEBUG_TAG = false;
|
private static final boolean DEBUG_TAG = false;
|
||||||
|
|
||||||
// Keyboard XML Tags
|
// Keyboard XML Tags
|
||||||
|
@ -118,7 +116,7 @@ public class BaseKeyboardParser {
|
||||||
private static final String TAG_DEFAULT = "default";
|
private static final String TAG_DEFAULT = "default";
|
||||||
private static final String TAG_KEY_STYLE = "key-style";
|
private static final String TAG_KEY_STYLE = "key-style";
|
||||||
|
|
||||||
private final BaseKeyboard mKeyboard;
|
private final Keyboard mKeyboard;
|
||||||
private final Resources mResources;
|
private final Resources mResources;
|
||||||
|
|
||||||
private int mCurrentX = 0;
|
private int mCurrentX = 0;
|
||||||
|
@ -128,7 +126,7 @@ public class BaseKeyboardParser {
|
||||||
private Row mCurrentRow = null;
|
private Row mCurrentRow = null;
|
||||||
private final KeyStyles mKeyStyles = new KeyStyles();
|
private final KeyStyles mKeyStyles = new KeyStyles();
|
||||||
|
|
||||||
public BaseKeyboardParser(BaseKeyboard keyboard, Resources res) {
|
public KeyboardParser(Keyboard keyboard, Resources res) {
|
||||||
mKeyboard = keyboard;
|
mKeyboard = keyboard;
|
||||||
mResources = res;
|
mResources = res;
|
||||||
}
|
}
|
||||||
|
@ -160,19 +158,19 @@ public class BaseKeyboardParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseKeyboardAttributes(XmlResourceParser parser) {
|
private void parseKeyboardAttributes(XmlResourceParser parser) {
|
||||||
final BaseKeyboard keyboard = mKeyboard;
|
final Keyboard keyboard = mKeyboard;
|
||||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboard);
|
R.styleable.Keyboard);
|
||||||
final int width = keyboard.getKeyboardWidth();
|
final int width = keyboard.getKeyboardWidth();
|
||||||
final int height = keyboard.getKeyboardHeight();
|
final int height = keyboard.getKeyboardHeight();
|
||||||
keyboard.setKeyWidth(getDimensionOrFraction(a,
|
keyboard.setKeyWidth(getDimensionOrFraction(a,
|
||||||
R.styleable.BaseKeyboard_keyWidth, width, width / 10));
|
R.styleable.Keyboard_keyWidth, width, width / 10));
|
||||||
keyboard.setKeyHeight(getDimensionOrFraction(a,
|
keyboard.setKeyHeight(getDimensionOrFraction(a,
|
||||||
R.styleable.BaseKeyboard_keyHeight, height, 50));
|
R.styleable.Keyboard_keyHeight, height, 50));
|
||||||
keyboard.setHorizontalGap(getDimensionOrFraction(a,
|
keyboard.setHorizontalGap(getDimensionOrFraction(a,
|
||||||
R.styleable.BaseKeyboard_horizontalGap, width, 0));
|
R.styleable.Keyboard_horizontalGap, width, 0));
|
||||||
keyboard.setVerticalGap(getDimensionOrFraction(a,
|
keyboard.setVerticalGap(getDimensionOrFraction(a,
|
||||||
R.styleable.BaseKeyboard_verticalGap, height, 0));
|
R.styleable.Keyboard_verticalGap, height, 0));
|
||||||
a.recycle();
|
a.recycle();
|
||||||
if (DEBUG_TAG) Log.d(TAG, "id=" + keyboard.mId);
|
if (DEBUG_TAG) Log.d(TAG, "id=" + keyboard.mId);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +264,7 @@ public class BaseKeyboardParser {
|
||||||
mKeyStyles);
|
mKeyStyles);
|
||||||
checkEndTag(TAG_KEY, parser);
|
checkEndTag(TAG_KEY, parser);
|
||||||
keys.add(key);
|
keys.add(key);
|
||||||
if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT)
|
if (key.codes[0] == Keyboard.KEYCODE_SHIFT)
|
||||||
mKeyboard.getShiftKeys().add(key);
|
mKeyboard.getShiftKeys().add(key);
|
||||||
endKey(key);
|
endKey(key);
|
||||||
}
|
}
|
||||||
|
@ -278,8 +276,8 @@ public class BaseKeyboardParser {
|
||||||
checkEndTag(TAG_SPACER, parser);
|
checkEndTag(TAG_SPACER, parser);
|
||||||
} else {
|
} else {
|
||||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboard);
|
R.styleable.Keyboard);
|
||||||
final int gap = getDimensionOrFraction(a, R.styleable.BaseKeyboard_horizontalGap,
|
final int gap = getDimensionOrFraction(a, R.styleable.Keyboard_horizontalGap,
|
||||||
mKeyboard.getKeyboardWidth(), 0);
|
mKeyboard.getKeyboardWidth(), 0);
|
||||||
a.recycle();
|
a.recycle();
|
||||||
checkEndTag(TAG_SPACER, parser);
|
checkEndTag(TAG_SPACER, parser);
|
||||||
|
@ -303,9 +301,9 @@ public class BaseKeyboardParser {
|
||||||
checkEndTag(TAG_INCLUDE, parser);
|
checkEndTag(TAG_INCLUDE, parser);
|
||||||
} else {
|
} else {
|
||||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboard_Include);
|
R.styleable.Keyboard_Include);
|
||||||
final int keyboardLayout = a.getResourceId(
|
final int keyboardLayout = a.getResourceId(
|
||||||
R.styleable.BaseKeyboard_Include_keyboardLayout, 0);
|
R.styleable.Keyboard_Include_keyboardLayout, 0);
|
||||||
a.recycle();
|
a.recycle();
|
||||||
|
|
||||||
checkEndTag(TAG_INCLUDE, parser);
|
checkEndTag(TAG_INCLUDE, parser);
|
||||||
|
@ -395,25 +393,25 @@ public class BaseKeyboardParser {
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboard_Case);
|
R.styleable.Keyboard_Case);
|
||||||
final TypedArray viewAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray viewAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboardView);
|
R.styleable.KeyboardView);
|
||||||
try {
|
try {
|
||||||
final boolean modeMatched = matchInteger(a,
|
final boolean modeMatched = matchInteger(a,
|
||||||
R.styleable.BaseKeyboard_Case_mode, id.mMode);
|
R.styleable.Keyboard_Case_mode, id.mMode);
|
||||||
final boolean settingsKeyMatched = matchBoolean(a,
|
final boolean settingsKeyMatched = matchBoolean(a,
|
||||||
R.styleable.BaseKeyboard_Case_hasSettingsKey, id.mHasSettingsKey);
|
R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey);
|
||||||
final boolean voiceEnabledMatched = matchBoolean(a,
|
final boolean voiceEnabledMatched = matchBoolean(a,
|
||||||
R.styleable.BaseKeyboard_Case_voiceKeyEnabled, id.mVoiceKeyEnabled);
|
R.styleable.Keyboard_Case_voiceKeyEnabled, id.mVoiceKeyEnabled);
|
||||||
final boolean voiceKeyMatched = matchBoolean(a,
|
final boolean voiceKeyMatched = matchBoolean(a,
|
||||||
R.styleable.BaseKeyboard_Case_hasVoiceKey, id.mHasVoiceKey);
|
R.styleable.Keyboard_Case_hasVoiceKey, id.mHasVoiceKey);
|
||||||
final boolean colorSchemeMatched = matchInteger(viewAttr,
|
final boolean colorSchemeMatched = matchInteger(viewAttr,
|
||||||
R.styleable.BaseKeyboardView_colorScheme, id.mColorScheme);
|
R.styleable.KeyboardView_colorScheme, id.mColorScheme);
|
||||||
// As noted at KeyboardSwitcher.KeyboardId class, we are interested only in
|
// As noted at KeyboardSwitcher.KeyboardId class, we are interested only in
|
||||||
// enum value masked by IME_MASK_ACTION and IME_FLAG_NO_ENTER_ACTION. So matching
|
// enum value masked by IME_MASK_ACTION and IME_FLAG_NO_ENTER_ACTION. So matching
|
||||||
// this attribute with id.mImeOptions as integer value is enough for our purpose.
|
// this attribute with id.mImeOptions as integer value is enough for our purpose.
|
||||||
final boolean imeOptionsMatched = matchInteger(a,
|
final boolean imeOptionsMatched = matchInteger(a,
|
||||||
R.styleable.BaseKeyboard_Case_imeOptions, id.mImeOptions);
|
R.styleable.Keyboard_Case_imeOptions, id.mImeOptions);
|
||||||
final boolean selected = modeMatched && settingsKeyMatched && voiceEnabledMatched
|
final boolean selected = modeMatched && settingsKeyMatched && voiceEnabledMatched
|
||||||
&& voiceKeyMatched && colorSchemeMatched && imeOptionsMatched;
|
&& voiceKeyMatched && colorSchemeMatched && imeOptionsMatched;
|
||||||
|
|
||||||
|
@ -421,15 +419,15 @@ public class BaseKeyboardParser {
|
||||||
Log.d(TAG, String.format(
|
Log.d(TAG, String.format(
|
||||||
"parseCaseCondition: %s%s%s%s%s%s%s",
|
"parseCaseCondition: %s%s%s%s%s%s%s",
|
||||||
Boolean.toString(selected).toUpperCase(),
|
Boolean.toString(selected).toUpperCase(),
|
||||||
debugInteger(a, R.styleable.BaseKeyboard_Case_mode, "mode"),
|
debugInteger(a, R.styleable.Keyboard_Case_mode, "mode"),
|
||||||
debugBoolean(a, R.styleable.BaseKeyboard_Case_hasSettingsKey,
|
debugBoolean(a, R.styleable.Keyboard_Case_hasSettingsKey,
|
||||||
"hasSettingsKey"),
|
"hasSettingsKey"),
|
||||||
debugBoolean(a, R.styleable.BaseKeyboard_Case_voiceKeyEnabled,
|
debugBoolean(a, R.styleable.Keyboard_Case_voiceKeyEnabled,
|
||||||
"voiceKeyEnabled"),
|
"voiceKeyEnabled"),
|
||||||
debugBoolean(a, R.styleable.BaseKeyboard_Case_hasVoiceKey, "hasVoiceKey"),
|
debugBoolean(a, R.styleable.Keyboard_Case_hasVoiceKey, "hasVoiceKey"),
|
||||||
debugInteger(viewAttr, R.styleable.BaseKeyboardView_colorScheme,
|
debugInteger(viewAttr, R.styleable.KeyboardView_colorScheme,
|
||||||
"colorScheme"),
|
"colorScheme"),
|
||||||
debugInteger(a, R.styleable.BaseKeyboard_Case_imeOptions, "imeOptions")));
|
debugInteger(a, R.styleable.Keyboard_Case_imeOptions, "imeOptions")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return selected;
|
return selected;
|
||||||
|
@ -464,11 +462,11 @@ public class BaseKeyboardParser {
|
||||||
private void parseKeyStyle(XmlResourceParser parser, List<Key> keys)
|
private void parseKeyStyle(XmlResourceParser parser, List<Key> keys)
|
||||||
throws XmlPullParserException, IOException {
|
throws XmlPullParserException, IOException {
|
||||||
TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboard_KeyStyle);
|
R.styleable.Keyboard_KeyStyle);
|
||||||
TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.BaseKeyboard_Key);
|
R.styleable.Keyboard_Key);
|
||||||
try {
|
try {
|
||||||
if (!a.hasValue(R.styleable.BaseKeyboard_KeyStyle_styleName))
|
if (!a.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
|
||||||
throw new ParseException("<" + TAG_KEY_STYLE
|
throw new ParseException("<" + TAG_KEY_STYLE
|
||||||
+ "/> needs styleName attribute", parser);
|
+ "/> needs styleName attribute", parser);
|
||||||
if (keys != null)
|
if (keys != null)
|
|
@ -14,9 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
import com.android.inputmethod.latin.LatinImeLogger;
|
||||||
|
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;
|
||||||
|
@ -49,27 +51,26 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A view that renders a virtual {@link LatinKeyboard}. It handles rendering of keys and
|
* A view that renders a virtual {@link Keyboard}. It handles rendering of keys and detecting key
|
||||||
* detecting key presses and touch movements.
|
* presses and touch movements.
|
||||||
*
|
*
|
||||||
* TODO: References to LatinKeyboard in this class should be replaced with ones to its base class.
|
* TODO: References to LatinKeyboard in this class should be replaced with ones to its base class.
|
||||||
*
|
*
|
||||||
* @attr ref R.styleable#BaseKeyboardView_keyBackground
|
* @attr ref R.styleable#KeyboardView_keyBackground
|
||||||
* @attr ref R.styleable#BaseKeyboardView_keyPreviewLayout
|
* @attr ref R.styleable#KeyboardView_keyPreviewLayout
|
||||||
* @attr ref R.styleable#BaseKeyboardView_keyPreviewOffset
|
* @attr ref R.styleable#KeyboardView_keyPreviewOffset
|
||||||
* @attr ref R.styleable#BaseKeyboardView_labelTextSize
|
* @attr ref R.styleable#KeyboardView_labelTextSize
|
||||||
* @attr ref R.styleable#BaseKeyboardView_keyTextSize
|
* @attr ref R.styleable#KeyboardView_keyTextSize
|
||||||
* @attr ref R.styleable#BaseKeyboardView_keyTextColor
|
* @attr ref R.styleable#KeyboardView_keyTextColor
|
||||||
* @attr ref R.styleable#BaseKeyboardView_verticalCorrection
|
* @attr ref R.styleable#KeyboardView_verticalCorrection
|
||||||
* @attr ref R.styleable#BaseKeyboardView_popupLayout
|
* @attr ref R.styleable#KeyboardView_popupLayout
|
||||||
*/
|
*/
|
||||||
public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
private static final String TAG = "BaseKeyboardView";
|
private static final String TAG = "KeyboardView";
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
private static final boolean DEBUG_SHOW_ALIGN = false;
|
private static final boolean DEBUG_SHOW_ALIGN = false;
|
||||||
private static final boolean DEBUG_KEYBOARD_GRID = false;
|
private static final boolean DEBUG_KEYBOARD_GRID = false;
|
||||||
|
@ -79,93 +80,10 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
|
|
||||||
public static final int NOT_A_TOUCH_COORDINATE = -1;
|
public static final int NOT_A_TOUCH_COORDINATE = -1;
|
||||||
|
|
||||||
public interface OnKeyboardActionListener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the user presses a key. This is sent before the
|
|
||||||
* {@link #onKey} is called. For keys that repeat, this is only
|
|
||||||
* called once.
|
|
||||||
*
|
|
||||||
* @param primaryCode
|
|
||||||
* the unicode of the key being pressed. If the touch is
|
|
||||||
* not on a valid key, the value will be zero.
|
|
||||||
*/
|
|
||||||
void onPress(int primaryCode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the user releases a key. This is sent after the
|
|
||||||
* {@link #onKey} is called. For keys that repeat, this is only
|
|
||||||
* called once.
|
|
||||||
*
|
|
||||||
* @param primaryCode
|
|
||||||
* the code of the key that was released
|
|
||||||
*/
|
|
||||||
void onRelease(int primaryCode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a key press to the listener.
|
|
||||||
*
|
|
||||||
* @param primaryCode
|
|
||||||
* this is the key that was pressed
|
|
||||||
* @param keyCodes
|
|
||||||
* the codes for all the possible alternative keys with
|
|
||||||
* the primary code being the first. If the primary key
|
|
||||||
* code is a single character such as an alphabet or
|
|
||||||
* number or symbol, the alternatives will include other
|
|
||||||
* characters that may be on the same key or adjacent
|
|
||||||
* keys. These codes are useful to correct for
|
|
||||||
* accidental presses of a key adjacent to the intended
|
|
||||||
* key.
|
|
||||||
* @param x
|
|
||||||
* x-coordinate pixel of touched event. If onKey is not called by onTouchEvent,
|
|
||||||
* the value should be NOT_A_TOUCH_COORDINATE.
|
|
||||||
* @param y
|
|
||||||
* y-coordinate pixel of touched event. If onKey is not called by onTouchEvent,
|
|
||||||
* the value should be NOT_A_TOUCH_COORDINATE.
|
|
||||||
*/
|
|
||||||
void onKey(int primaryCode, int[] keyCodes, int x, int y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a sequence of characters to the listener.
|
|
||||||
*
|
|
||||||
* @param text
|
|
||||||
* the sequence of characters to be displayed.
|
|
||||||
*/
|
|
||||||
void onText(CharSequence text);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user released a finger outside any key.
|
|
||||||
*/
|
|
||||||
void onCancel();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the user quickly moves the finger from right to
|
|
||||||
* left.
|
|
||||||
*/
|
|
||||||
void swipeLeft();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the user quickly moves the finger from left to
|
|
||||||
* right.
|
|
||||||
*/
|
|
||||||
void swipeRight();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the user quickly moves the finger from up to down.
|
|
||||||
*/
|
|
||||||
void swipeDown();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the user quickly moves the finger from down to up.
|
|
||||||
*/
|
|
||||||
void swipeUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timing constants
|
// Timing constants
|
||||||
private final int mKeyRepeatInterval;
|
private final int mKeyRepeatInterval;
|
||||||
|
|
||||||
// Miscellaneous constants
|
// Miscellaneous constants
|
||||||
/* package */ static final int NOT_A_KEY = -1;
|
|
||||||
private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };
|
private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable };
|
||||||
private static final int HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL = -1;
|
private static final int HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL = -1;
|
||||||
|
|
||||||
|
@ -187,7 +105,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
private int mPopupLayout;
|
private int mPopupLayout;
|
||||||
|
|
||||||
// Main keyboard
|
// Main keyboard
|
||||||
private BaseKeyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
private Key[] mKeys;
|
private Key[] mKeys;
|
||||||
|
|
||||||
// Key preview popup
|
// Key preview popup
|
||||||
|
@ -196,7 +114,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
private PopupWindow mPreviewPopup;
|
private PopupWindow mPreviewPopup;
|
||||||
private int mPreviewTextSizeLarge;
|
private int mPreviewTextSizeLarge;
|
||||||
private int[] mOffsetInWindow;
|
private int[] mOffsetInWindow;
|
||||||
private int mOldPreviewKeyIndex = NOT_A_KEY;
|
private int mOldPreviewKeyIndex = KeyDetector.NOT_A_KEY;
|
||||||
private boolean mShowPreview = true;
|
private boolean mShowPreview = true;
|
||||||
private boolean mShowTouchPoints = true;
|
private boolean mShowTouchPoints = true;
|
||||||
private int mPopupPreviewOffsetX;
|
private int mPopupPreviewOffsetX;
|
||||||
|
@ -208,7 +126,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
|
|
||||||
// Popup mini keyboard
|
// Popup mini keyboard
|
||||||
private PopupWindow mMiniKeyboardPopup;
|
private PopupWindow mMiniKeyboardPopup;
|
||||||
private BaseKeyboardView mMiniKeyboard;
|
private KeyboardView mMiniKeyboard;
|
||||||
private View mMiniKeyboardParent;
|
private View mMiniKeyboardParent;
|
||||||
private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>();
|
private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>();
|
||||||
private int mMiniKeyboardOriginX;
|
private int mMiniKeyboardOriginX;
|
||||||
|
@ -218,13 +136,13 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
private final float mMiniKeyboardSlideAllowance;
|
private final float mMiniKeyboardSlideAllowance;
|
||||||
private int mMiniKeyboardTrackerId;
|
private int mMiniKeyboardTrackerId;
|
||||||
|
|
||||||
/** Listener for {@link OnKeyboardActionListener}. */
|
/** Listener for {@link KeyboardActionListener}. */
|
||||||
private OnKeyboardActionListener mKeyboardActionListener;
|
private KeyboardActionListener mKeyboardActionListener;
|
||||||
|
|
||||||
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
|
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
|
||||||
|
|
||||||
// TODO: Let the PointerTracker class manage this pointer queue
|
// TODO: Let the PointerTracker class manage this pointer queue
|
||||||
private final PointerQueue mPointerQueue = new PointerQueue();
|
private final PointerTrackerQueue mPointerQueue = new PointerTrackerQueue();
|
||||||
|
|
||||||
private final boolean mHasDistinctMultitouch;
|
private final boolean mHasDistinctMultitouch;
|
||||||
private int mOldPointerCount = 1;
|
private int mOldPointerCount = 1;
|
||||||
|
@ -370,63 +288,15 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static class PointerQueue {
|
public KeyboardView(Context context, AttributeSet attrs) {
|
||||||
private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
|
|
||||||
|
|
||||||
public void add(PointerTracker tracker) {
|
|
||||||
mQueue.add(tracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int lastIndexOf(PointerTracker tracker) {
|
|
||||||
LinkedList<PointerTracker> queue = mQueue;
|
|
||||||
for (int index = queue.size() - 1; index >= 0; index--) {
|
|
||||||
PointerTracker t = queue.get(index);
|
|
||||||
if (t == tracker)
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) {
|
|
||||||
LinkedList<PointerTracker> queue = mQueue;
|
|
||||||
int oldestPos = 0;
|
|
||||||
for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
|
|
||||||
if (t.isModifier()) {
|
|
||||||
oldestPos++;
|
|
||||||
} else {
|
|
||||||
t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
|
|
||||||
t.setAlreadyProcessed();
|
|
||||||
queue.remove(oldestPos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) {
|
|
||||||
for (PointerTracker t : mQueue) {
|
|
||||||
if (t == tracker)
|
|
||||||
continue;
|
|
||||||
t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
|
|
||||||
t.setAlreadyProcessed();
|
|
||||||
}
|
|
||||||
mQueue.clear();
|
|
||||||
if (tracker != null)
|
|
||||||
mQueue.add(tracker);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(PointerTracker tracker) {
|
|
||||||
mQueue.remove(tracker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseKeyboardView(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, R.attr.keyboardViewStyle);
|
this(context, attrs, R.attr.keyboardViewStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseKeyboardView(Context context, AttributeSet attrs, int defStyle) {
|
public KeyboardView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
TypedArray a = context.obtainStyledAttributes(
|
TypedArray a = context.obtainStyledAttributes(
|
||||||
attrs, R.styleable.BaseKeyboardView, defStyle, R.style.BaseKeyboardView);
|
attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
||||||
LayoutInflater inflate =
|
LayoutInflater inflate =
|
||||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
int previewLayout = 0;
|
int previewLayout = 0;
|
||||||
|
@ -438,53 +308,53 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
int attr = a.getIndex(i);
|
int attr = a.getIndex(i);
|
||||||
|
|
||||||
switch (attr) {
|
switch (attr) {
|
||||||
case R.styleable.BaseKeyboardView_keyBackground:
|
case R.styleable.KeyboardView_keyBackground:
|
||||||
mKeyBackground = a.getDrawable(attr);
|
mKeyBackground = a.getDrawable(attr);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyHysteresisDistance:
|
case R.styleable.KeyboardView_keyHysteresisDistance:
|
||||||
mKeyHysteresisDistance = a.getDimensionPixelOffset(attr, 0);
|
mKeyHysteresisDistance = a.getDimensionPixelOffset(attr, 0);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_verticalCorrection:
|
case R.styleable.KeyboardView_verticalCorrection:
|
||||||
mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
|
mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyPreviewLayout:
|
case R.styleable.KeyboardView_keyPreviewLayout:
|
||||||
previewLayout = a.getResourceId(attr, 0);
|
previewLayout = a.getResourceId(attr, 0);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyPreviewOffset:
|
case R.styleable.KeyboardView_keyPreviewOffset:
|
||||||
mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
|
mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyPreviewHeight:
|
case R.styleable.KeyboardView_keyPreviewHeight:
|
||||||
mPreviewHeight = a.getDimensionPixelSize(attr, 80);
|
mPreviewHeight = a.getDimensionPixelSize(attr, 80);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyLetterSize:
|
case R.styleable.KeyboardView_keyLetterSize:
|
||||||
mKeyLetterSize = a.getDimensionPixelSize(attr, 18);
|
mKeyLetterSize = a.getDimensionPixelSize(attr, 18);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyTextColor:
|
case R.styleable.KeyboardView_keyTextColor:
|
||||||
mKeyTextColor = a.getColor(attr, 0xFF000000);
|
mKeyTextColor = a.getColor(attr, 0xFF000000);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyTextColorDisabled:
|
case R.styleable.KeyboardView_keyTextColorDisabled:
|
||||||
mKeyTextColorDisabled = a.getColor(attr, 0xFF000000);
|
mKeyTextColorDisabled = a.getColor(attr, 0xFF000000);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_labelTextSize:
|
case R.styleable.KeyboardView_labelTextSize:
|
||||||
mLabelTextSize = a.getDimensionPixelSize(attr, 14);
|
mLabelTextSize = a.getDimensionPixelSize(attr, 14);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_popupLayout:
|
case R.styleable.KeyboardView_popupLayout:
|
||||||
mPopupLayout = a.getResourceId(attr, 0);
|
mPopupLayout = a.getResourceId(attr, 0);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_shadowColor:
|
case R.styleable.KeyboardView_shadowColor:
|
||||||
mShadowColor = a.getColor(attr, 0);
|
mShadowColor = a.getColor(attr, 0);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_shadowRadius:
|
case R.styleable.KeyboardView_shadowRadius:
|
||||||
mShadowRadius = a.getFloat(attr, 0f);
|
mShadowRadius = a.getFloat(attr, 0f);
|
||||||
break;
|
break;
|
||||||
// TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
|
// TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
|
||||||
case R.styleable.BaseKeyboardView_backgroundDimAmount:
|
case R.styleable.KeyboardView_backgroundDimAmount:
|
||||||
mBackgroundDimAmount = a.getFloat(attr, 0.5f);
|
mBackgroundDimAmount = a.getFloat(attr, 0.5f);
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_keyLetterStyle:
|
case R.styleable.KeyboardView_keyLetterStyle:
|
||||||
mKeyLetterStyle = Typeface.defaultFromStyle(a.getInt(attr, Typeface.NORMAL));
|
mKeyLetterStyle = Typeface.defaultFromStyle(a.getInt(attr, Typeface.NORMAL));
|
||||||
break;
|
break;
|
||||||
case R.styleable.BaseKeyboardView_colorScheme:
|
case R.styleable.KeyboardView_colorScheme:
|
||||||
mColorScheme = a.getInt(attr, COLOR_SCHEME_WHITE);
|
mColorScheme = a.getInt(attr, COLOR_SCHEME_WHITE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -575,7 +445,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
|
mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
|
public void setOnKeyboardActionListener(KeyboardActionListener listener) {
|
||||||
mKeyboardActionListener = listener;
|
mKeyboardActionListener = listener;
|
||||||
for (PointerTracker tracker : mPointerTrackers) {
|
for (PointerTracker tracker : mPointerTrackers) {
|
||||||
tracker.setOnKeyboardActionListener(listener);
|
tracker.setOnKeyboardActionListener(listener);
|
||||||
|
@ -583,21 +453,21 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link OnKeyboardActionListener} object.
|
* Returns the {@link KeyboardActionListener} object.
|
||||||
* @return the listener attached to this keyboard
|
* @return the listener attached to this keyboard
|
||||||
*/
|
*/
|
||||||
protected OnKeyboardActionListener getOnKeyboardActionListener() {
|
protected KeyboardActionListener getOnKeyboardActionListener() {
|
||||||
return mKeyboardActionListener;
|
return mKeyboardActionListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
|
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
|
||||||
* view will re-layout itself to accommodate the keyboard.
|
* view will re-layout itself to accommodate the keyboard.
|
||||||
* @see BaseKeyboard
|
* @see Keyboard
|
||||||
* @see #getKeyboard()
|
* @see #getKeyboard()
|
||||||
* @param keyboard the keyboard to display in this view
|
* @param keyboard the keyboard to display in this view
|
||||||
*/
|
*/
|
||||||
protected void setKeyboard(BaseKeyboard keyboard) {
|
public void setKeyboard(Keyboard keyboard) {
|
||||||
if (mKeyboard != null) {
|
if (mKeyboard != null) {
|
||||||
dismissKeyPreview();
|
dismissKeyPreview();
|
||||||
}
|
}
|
||||||
|
@ -622,9 +492,9 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
/**
|
/**
|
||||||
* Returns the current keyboard being displayed by this view.
|
* Returns the current keyboard being displayed by this view.
|
||||||
* @return the currently attached keyboard
|
* @return the currently attached keyboard
|
||||||
* @see #setKeyboard(BaseKeyboard)
|
* @see #setKeyboard(Keyboard)
|
||||||
*/
|
*/
|
||||||
protected BaseKeyboard getKeyboard() {
|
public Keyboard getKeyboard() {
|
||||||
return mKeyboard;
|
return mKeyboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,6 +502,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
* Return whether the device has distinct multi-touch panel.
|
* Return whether the device has distinct multi-touch panel.
|
||||||
* @return true if the device has distinct multi-touch panel.
|
* @return true if the device has distinct multi-touch panel.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public boolean hasDistinctMultitouch() {
|
public boolean hasDistinctMultitouch() {
|
||||||
return mHasDistinctMultitouch;
|
return mHasDistinctMultitouch;
|
||||||
}
|
}
|
||||||
|
@ -670,7 +541,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When enabled, calls to {@link OnKeyboardActionListener#onKey} will include key
|
* When enabled, calls to {@link KeyboardActionListener#onKey} will include key
|
||||||
* codes for adjacent keys. When disabled, only the primary key code will be
|
* codes for adjacent keys. When disabled, only the primary key code will be
|
||||||
* reported.
|
* reported.
|
||||||
* @param enabled whether or not the proximity correction is enabled
|
* @param enabled whether or not the proximity correction is enabled
|
||||||
|
@ -715,7 +586,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
* @param keyboard
|
* @param keyboard
|
||||||
* @param keys
|
* @param keys
|
||||||
*/
|
*/
|
||||||
private void computeProximityThreshold(BaseKeyboard keyboard, Key[] keys) {
|
private void computeProximityThreshold(Keyboard keyboard, Key[] keys) {
|
||||||
if (keyboard == null || keys == null || keys.length == 0) return;
|
if (keyboard == null || keys == null || keys.length == 0) return;
|
||||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||||
int maxCount = 0;
|
int maxCount = 0;
|
||||||
|
@ -750,6 +621,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
canvas.drawBitmap(mBuffer, 0, 0, null);
|
canvas.drawBitmap(mBuffer, 0, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private void onBufferDraw() {
|
private void onBufferDraw() {
|
||||||
if (mBuffer == null || mKeyboardChanged) {
|
if (mBuffer == null || mKeyboardChanged) {
|
||||||
if (mBuffer == null || mKeyboardChanged &&
|
if (mBuffer == null || mKeyboardChanged &&
|
||||||
|
@ -1020,22 +892,24 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
private void dismissKeyPreview() {
|
private void dismissKeyPreview() {
|
||||||
for (PointerTracker tracker : mPointerTrackers)
|
for (PointerTracker tracker : mPointerTrackers)
|
||||||
tracker.releaseKey();
|
tracker.releaseKey();
|
||||||
showPreview(NOT_A_KEY, null);
|
showPreview(KeyDetector.NOT_A_KEY, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
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
|
// We should re-draw popup preview when 1) we need to hide the preview, 2) we will show
|
||||||
// the space key preview and 3) pointer moves off the space key to other letter key, we
|
// 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.
|
// should hide the preview of the previous key.
|
||||||
|
@SuppressWarnings("unused")
|
||||||
final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
|
final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
|
||||||
|| (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
|
|| (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
|
||||||
&& SubtypeSwitcher.getInstance().needsToDisplayLanguage()
|
&& SubtypeSwitcher.getInstance().needsToDisplayLanguage()
|
||||||
&& (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
|
&& (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
|
||||||
// If key changed and preview is on or the key is space (language switch is enabled)
|
// If key changed and preview is on or the key is space (language switch is enabled)
|
||||||
if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview))) {
|
if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview))) {
|
||||||
if (keyIndex == NOT_A_KEY) {
|
if (keyIndex == KeyDetector.NOT_A_KEY) {
|
||||||
mHandler.cancelPopupPreview();
|
mHandler.cancelPopupPreview();
|
||||||
mHandler.dismissPreview(mDelayAfterPreview);
|
mHandler.dismissPreview(mDelayAfterPreview);
|
||||||
} else if (tracker != null) {
|
} else if (tracker != null) {
|
||||||
|
@ -1145,9 +1019,10 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
* Invalidates a key so that it will be redrawn on the next repaint. Use this method if only
|
* Invalidates a key so that it will be redrawn on the next repaint. Use this method if only
|
||||||
* one key is changing it's content. Any changes that affect the position or size of the key
|
* one key is changing it's content. Any changes that affect the position or size of the key
|
||||||
* may not be honored.
|
* may not be honored.
|
||||||
* @param key key in the attached {@link BaseKeyboard}.
|
* @param key key in the attached {@link Keyboard}.
|
||||||
* @see #invalidateAllKeys
|
* @see #invalidateAllKeys
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void invalidateKey(Key key) {
|
public void invalidateKey(Key key) {
|
||||||
if (key == null)
|
if (key == null)
|
||||||
return;
|
return;
|
||||||
|
@ -1183,7 +1058,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
private void onLongPressShiftKey(PointerTracker tracker) {
|
private void onLongPressShiftKey(PointerTracker tracker) {
|
||||||
tracker.setAlreadyProcessed();
|
tracker.setAlreadyProcessed();
|
||||||
mPointerQueue.remove(tracker);
|
mPointerQueue.remove(tracker);
|
||||||
mKeyboardActionListener.onKey(LatinKeyboardView.KEYCODE_CAPSLOCK, null, 0, 0);
|
mKeyboardActionListener.onKey(LatinKeyboard.KEYCODE_CAPSLOCK, null, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private View inflateMiniKeyboardContainer(Key popupKey) {
|
private View inflateMiniKeyboardContainer(Key popupKey) {
|
||||||
|
@ -1194,34 +1069,43 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
if (container == null)
|
if (container == null)
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
|
|
||||||
BaseKeyboardView miniKeyboard =
|
KeyboardView miniKeyboard =
|
||||||
(BaseKeyboardView)container.findViewById(R.id.BaseKeyboardView);
|
(KeyboardView)container.findViewById(R.id.KeyboardView);
|
||||||
miniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() {
|
miniKeyboard.setOnKeyboardActionListener(new KeyboardActionListener() {
|
||||||
|
@Override
|
||||||
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
||||||
mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y);
|
mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y);
|
||||||
dismissPopupKeyboard();
|
dismissPopupKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onText(CharSequence text) {
|
public void onText(CharSequence text) {
|
||||||
mKeyboardActionListener.onText(text);
|
mKeyboardActionListener.onText(text);
|
||||||
dismissPopupKeyboard();
|
dismissPopupKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onCancel() {
|
public void onCancel() {
|
||||||
dismissPopupKeyboard();
|
dismissPopupKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void swipeLeft() {
|
public void swipeLeft() {
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void swipeRight() {
|
public void swipeRight() {
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void swipeUp() {
|
public void swipeUp() {
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void swipeDown() {
|
public void swipeDown() {
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void onPress(int primaryCode) {
|
public void onPress(int primaryCode) {
|
||||||
mKeyboardActionListener.onPress(primaryCode);
|
mKeyboardActionListener.onPress(primaryCode);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void onRelease(int primaryCode) {
|
public void onRelease(int primaryCode) {
|
||||||
mKeyboardActionListener.onRelease(primaryCode);
|
mKeyboardActionListener.onRelease(primaryCode);
|
||||||
}
|
}
|
||||||
|
@ -1231,12 +1115,12 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
// Remove gesture detector on mini-keyboard
|
// Remove gesture detector on mini-keyboard
|
||||||
miniKeyboard.mGestureDetector = null;
|
miniKeyboard.mGestureDetector = null;
|
||||||
|
|
||||||
BaseKeyboard keyboard;
|
Keyboard keyboard;
|
||||||
if (popupKey.popupCharacters != null) {
|
if (popupKey.popupCharacters != null) {
|
||||||
keyboard = new BaseKeyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
|
keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
|
||||||
-1, getPaddingLeft() + getPaddingRight());
|
-1, getPaddingLeft() + getPaddingRight());
|
||||||
} else {
|
} else {
|
||||||
keyboard = new BaseKeyboard(getContext(), popupKeyboardId);
|
keyboard = new Keyboard(getContext(), popupKeyboardId);
|
||||||
}
|
}
|
||||||
miniKeyboard.setKeyboard(keyboard);
|
miniKeyboard.setKeyboard(keyboard);
|
||||||
miniKeyboard.setPopupParent(this);
|
miniKeyboard.setPopupParent(this);
|
||||||
|
@ -1256,8 +1140,8 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
// and bottom edge flags on.
|
// and bottom edge flags on.
|
||||||
// When you want to use one row mini-keyboard from xml file, make sure that the row has
|
// When you want to use one row mini-keyboard from xml file, make sure that the row has
|
||||||
// both top and bottom edge flags set.
|
// both top and bottom edge flags set.
|
||||||
return (edgeFlags & BaseKeyboard.EDGE_TOP) != 0
|
return (edgeFlags & Keyboard.EDGE_TOP) != 0
|
||||||
&& (edgeFlags & BaseKeyboard.EDGE_BOTTOM) != 0;
|
&& (edgeFlags & Keyboard.EDGE_BOTTOM) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1279,7 +1163,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
container = inflateMiniKeyboardContainer(popupKey);
|
container = inflateMiniKeyboardContainer(popupKey);
|
||||||
mMiniKeyboardCache.put(popupKey, container);
|
mMiniKeyboardCache.put(popupKey, container);
|
||||||
}
|
}
|
||||||
mMiniKeyboard = (BaseKeyboardView)container.findViewById(R.id.BaseKeyboardView);
|
mMiniKeyboard = (KeyboardView)container.findViewById(R.id.KeyboardView);
|
||||||
if (mWindowOffset == null) {
|
if (mWindowOffset == null) {
|
||||||
mWindowOffset = new int[2];
|
mWindowOffset = new int[2];
|
||||||
getLocationInWindow(mWindowOffset);
|
getLocationInWindow(mWindowOffset);
|
||||||
|
@ -1325,7 +1209,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||||
mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1];
|
mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1];
|
||||||
mMiniKeyboard.setPopupOffset(adjustedX, y);
|
mMiniKeyboard.setPopupOffset(adjustedX, y);
|
||||||
// TODO: change the below line to use getLatinKeyboard() instead of getKeyboard()
|
// TODO: change the below line to use getLatinKeyboard() instead of getKeyboard()
|
||||||
BaseKeyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard();
|
Keyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard();
|
||||||
if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null
|
if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null
|
||||||
? false : mKeyboard.isShiftedOrShiftLocked())) {
|
? false : mKeyboard.isShiftedOrShiftLocked())) {
|
||||||
mMiniKeyboard.invalidateAllKeys();
|
mMiniKeyboard.invalidateAllKeys();
|
||||||
|
@ -1376,7 +1260,7 @@ public class BaseKeyboardView 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 Key[] keys = mKeys;
|
||||||
final OnKeyboardActionListener 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++) {
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* 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.content.res.Resources;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
|
||||||
|
public class LatinKey extends Key {
|
||||||
|
|
||||||
|
// functional normal state (with properties)
|
||||||
|
private final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
|
||||||
|
android.R.attr.state_single
|
||||||
|
};
|
||||||
|
|
||||||
|
// functional pressed state (with properties)
|
||||||
|
private final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
|
||||||
|
android.R.attr.state_single,
|
||||||
|
android.R.attr.state_pressed
|
||||||
|
};
|
||||||
|
|
||||||
|
private boolean mShiftLockEnabled;
|
||||||
|
|
||||||
|
public LatinKey(Resources res, Row parent, int x, int y,
|
||||||
|
XmlResourceParser parser, KeyStyles keyStyles) {
|
||||||
|
super(res, parent, x, y, parser, keyStyles);
|
||||||
|
if (popupCharacters != null && popupCharacters.length() == 0) {
|
||||||
|
// If there is a keyboard with no keys specified in popupCharacters
|
||||||
|
popupResId = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableShiftLock() {
|
||||||
|
mShiftLockEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sticky is used for shift key. If a key is not sticky and is modifier,
|
||||||
|
// the key will be treated as functional.
|
||||||
|
private boolean isFunctionalKey() {
|
||||||
|
return !sticky && modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReleased(boolean inside) {
|
||||||
|
if (!mShiftLockEnabled) {
|
||||||
|
super.onReleased(inside);
|
||||||
|
} else {
|
||||||
|
pressed = !pressed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overriding this method so that we can reduce the target area for certain keys.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isInside(int x, int y) {
|
||||||
|
boolean result = (keyboard instanceof LatinKeyboard)
|
||||||
|
&& ((LatinKeyboard)keyboard).isInside(this, x, y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isInsideSuper(int x, int y) {
|
||||||
|
return super.isInside(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getCurrentDrawableState() {
|
||||||
|
if (isFunctionalKey()) {
|
||||||
|
if (pressed) {
|
||||||
|
return KEY_STATE_FUNCTIONAL_PRESSED;
|
||||||
|
} else {
|
||||||
|
return KEY_STATE_FUNCTIONAL_NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.getCurrentDrawableState();
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,11 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.LatinIME;
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
@ -22,28 +26,33 @@ import android.content.res.TypedArray;
|
||||||
import android.content.res.XmlResourceParser;
|
import android.content.res.XmlResourceParser;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.ColorFilter;
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Paint.Align;
|
import android.graphics.Paint.Align;
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.Rect;
|
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 android.text.TextPaint;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.ViewConfiguration;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class LatinKeyboard extends BaseKeyboard {
|
public class LatinKeyboard extends Keyboard {
|
||||||
|
|
||||||
private static final boolean DEBUG_PREFERRED_LETTER = false;
|
private static final boolean DEBUG_PREFERRED_LETTER = false;
|
||||||
private static final String TAG = "LatinKeyboard";
|
private static final String TAG = "LatinKeyboard";
|
||||||
private static final int OPACITY_FULLY_OPAQUE = 255;
|
|
||||||
|
public static final int KEYCODE_OPTIONS = -100;
|
||||||
|
public static final int KEYCODE_OPTIONS_LONGPRESS = -101;
|
||||||
|
// TODO: remove this once LatinIME stops referring to this.
|
||||||
|
public static final int KEYCODE_VOICE = -102;
|
||||||
|
public static final int KEYCODE_NEXT_LANGUAGE = -104;
|
||||||
|
public static final int KEYCODE_PREV_LANGUAGE = -105;
|
||||||
|
public static final int KEYCODE_CAPSLOCK = -106;
|
||||||
|
|
||||||
|
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 Drawable mShiftLockPreviewIcon;
|
private Drawable mShiftLockPreviewIcon;
|
||||||
|
@ -76,22 +85,22 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
// Minimum width of space key preview (proportional to keyboard width)
|
// 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)
|
||||||
private static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
|
public static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f;
|
||||||
// If the full language name needs to be smaller than this value to be drawn on space key,
|
// If the full language name needs to be smaller than this value to be drawn on space key,
|
||||||
// its short language name will be used instead.
|
// its short language name will be used instead.
|
||||||
private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
|
private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
|
||||||
|
|
||||||
private static int sSpacebarVerticalCorrection;
|
private static int sSpacebarVerticalCorrection;
|
||||||
|
|
||||||
public LatinKeyboard(Context context, KeyboardSwitcher.KeyboardId id) {
|
public LatinKeyboard(Context context, KeyboardId id) {
|
||||||
super(context, id);
|
super(context, id);
|
||||||
final Resources res = context.getResources();
|
final Resources res = context.getResources();
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mRes = res;
|
mRes = res;
|
||||||
if (id.mColorScheme == BaseKeyboardView.COLOR_SCHEME_BLACK) {
|
if (id.mColorScheme == KeyboardView.COLOR_SCHEME_BLACK) {
|
||||||
mSpaceBarTextShadowColor = res.getColor(
|
mSpaceBarTextShadowColor = res.getColor(
|
||||||
R.color.latinkeyboard_bar_language_shadow_black);
|
R.color.latinkeyboard_bar_language_shadow_black);
|
||||||
} else { // default color scheme is BaseKeyboardView.COLOR_SCHEME_WHITE
|
} else { // default color scheme is KeyboardView.COLOR_SCHEME_WHITE
|
||||||
mSpaceBarTextShadowColor = res.getColor(
|
mSpaceBarTextShadowColor = res.getColor(
|
||||||
R.color.latinkeyboard_bar_language_shadow_white);
|
R.color.latinkeyboard_bar_language_shadow_white);
|
||||||
}
|
}
|
||||||
|
@ -181,7 +190,7 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
|
return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ LatinKeyboardShiftState getKeyboardShiftState() {
|
public LatinKeyboardShiftState getKeyboardShiftState() {
|
||||||
return mShiftState;
|
return mShiftState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,11 +199,11 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPhoneKeyboard() {
|
public boolean isPhoneKeyboard() {
|
||||||
return mId.mMode == KeyboardSwitcher.MODE_PHONE;
|
return mId.mMode == KeyboardId.MODE_PHONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNumberKeyboard() {
|
public boolean isNumberKeyboard() {
|
||||||
return mId.mMode == KeyboardSwitcher.MODE_NUMBER;
|
return mId.mMode == KeyboardId.MODE_NUMBER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -272,6 +281,7 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion) {
|
private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion) {
|
||||||
final int width = mSpaceKey.width;
|
final int width = mSpaceKey.width;
|
||||||
final int height = mSpaceIcon.getIntrinsicHeight();
|
final int height = mSpaceIcon.getIntrinsicHeight();
|
||||||
|
@ -334,7 +344,8 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
final int width = Math.max(mSpaceKey.width,
|
final int width = Math.max(mSpaceKey.width,
|
||||||
(int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
|
(int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
|
||||||
final int height = mSpacePreviewIcon.getIntrinsicHeight();
|
final int height = mSpacePreviewIcon.getIntrinsicHeight();
|
||||||
mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, width, height);
|
mSlidingLocaleIcon =
|
||||||
|
new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height);
|
||||||
mSlidingLocaleIcon.setBounds(0, 0, width, height);
|
mSlidingLocaleIcon.setBounds(0, 0, width, height);
|
||||||
mSpaceKey.iconPreview = mSlidingLocaleIcon;
|
mSpaceKey.iconPreview = mSlidingLocaleIcon;
|
||||||
}
|
}
|
||||||
|
@ -380,6 +391,7 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
* Does the magic of locking the touch gesture into the spacebar when
|
* Does the magic of locking the touch gesture into the spacebar when
|
||||||
* switching input languages.
|
* switching input languages.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public boolean isInside(LatinKey key, int x, int y) {
|
public boolean isInside(LatinKey key, int x, int y) {
|
||||||
final int code = key.codes[0];
|
final int code = key.codes[0];
|
||||||
if (code == KEYCODE_SHIFT || code == KEYCODE_DELETE) {
|
if (code == KEYCODE_SHIFT || code == KEYCODE_DELETE) {
|
||||||
|
@ -528,193 +540,4 @@ public class LatinKeyboard extends BaseKeyboard {
|
||||||
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
|
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
|
||||||
return textSize;
|
return textSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LatinKey extends BaseKeyboard.Key {
|
|
||||||
|
|
||||||
// functional normal state (with properties)
|
|
||||||
private final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
|
|
||||||
android.R.attr.state_single
|
|
||||||
};
|
|
||||||
|
|
||||||
// functional pressed state (with properties)
|
|
||||||
private final int[] KEY_STATE_FUNCTIONAL_PRESSED = {
|
|
||||||
android.R.attr.state_single,
|
|
||||||
android.R.attr.state_pressed
|
|
||||||
};
|
|
||||||
|
|
||||||
private boolean mShiftLockEnabled;
|
|
||||||
|
|
||||||
public LatinKey(Resources res, BaseKeyboard.Row parent, int x, int y,
|
|
||||||
XmlResourceParser parser, KeyStyles keyStyles) {
|
|
||||||
super(res, parent, x, y, parser, keyStyles);
|
|
||||||
if (popupCharacters != null && popupCharacters.length() == 0) {
|
|
||||||
// If there is a keyboard with no keys specified in popupCharacters
|
|
||||||
popupResId = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableShiftLock() {
|
|
||||||
mShiftLockEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sticky is used for shift key. If a key is not sticky and is modifier,
|
|
||||||
// the key will be treated as functional.
|
|
||||||
private boolean isFunctionalKey() {
|
|
||||||
return !sticky && modifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReleased(boolean inside) {
|
|
||||||
if (!mShiftLockEnabled) {
|
|
||||||
super.onReleased(inside);
|
|
||||||
} else {
|
|
||||||
pressed = !pressed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overriding this method so that we can reduce the target area for certain keys.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isInside(int x, int y) {
|
|
||||||
boolean result = (keyboard instanceof LatinKeyboard)
|
|
||||||
&& ((LatinKeyboard)keyboard).isInside(this, x, y);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isInsideSuper(int x, int y) {
|
|
||||||
return super.isInside(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getCurrentDrawableState() {
|
|
||||||
if (isFunctionalKey()) {
|
|
||||||
if (pressed) {
|
|
||||||
return KEY_STATE_FUNCTIONAL_PRESSED;
|
|
||||||
} else {
|
|
||||||
return KEY_STATE_FUNCTIONAL_NORMAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.getCurrentDrawableState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Animation to be displayed on the spacebar preview popup when switching
|
|
||||||
* languages by swiping the spacebar. It draws the current, previous and
|
|
||||||
* next languages and moves them by the delta of touch movement on the spacebar.
|
|
||||||
*/
|
|
||||||
private class SlidingLocaleDrawable extends Drawable {
|
|
||||||
|
|
||||||
private final int mWidth;
|
|
||||||
private final int mHeight;
|
|
||||||
private final Drawable mBackground;
|
|
||||||
private final TextPaint mTextPaint;
|
|
||||||
private final int mMiddleX;
|
|
||||||
private final Drawable mLeftDrawable;
|
|
||||||
private final Drawable mRightDrawable;
|
|
||||||
private final int mThreshold;
|
|
||||||
private int mDiff;
|
|
||||||
private boolean mHitThreshold;
|
|
||||||
private String mCurrentLanguage;
|
|
||||||
private String mNextLanguage;
|
|
||||||
private String mPrevLanguage;
|
|
||||||
|
|
||||||
public SlidingLocaleDrawable(Drawable background, int width, int height) {
|
|
||||||
mBackground = background;
|
|
||||||
setDefaultBounds(mBackground);
|
|
||||||
mWidth = width;
|
|
||||||
mHeight = height;
|
|
||||||
final TextPaint textPaint = new TextPaint();
|
|
||||||
textPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18));
|
|
||||||
textPaint.setColor(R.color.latinkeyboard_transparent);
|
|
||||||
textPaint.setTextAlign(Align.CENTER);
|
|
||||||
textPaint.setAlpha(OPACITY_FULLY_OPAQUE);
|
|
||||||
textPaint.setAntiAlias(true);
|
|
||||||
mTextPaint = textPaint;
|
|
||||||
mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
|
|
||||||
final Resources res = mRes;
|
|
||||||
mLeftDrawable = res.getDrawable(
|
|
||||||
R.drawable.sym_keyboard_feedback_language_arrows_left);
|
|
||||||
mRightDrawable = res.getDrawable(
|
|
||||||
R.drawable.sym_keyboard_feedback_language_arrows_right);
|
|
||||||
mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setDiff(int diff) {
|
|
||||||
if (diff == Integer.MAX_VALUE) {
|
|
||||||
mHitThreshold = false;
|
|
||||||
mCurrentLanguage = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mDiff = diff;
|
|
||||||
if (mDiff > mWidth) mDiff = mWidth;
|
|
||||||
if (mDiff < -mWidth) mDiff = -mWidth;
|
|
||||||
if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
|
|
||||||
invalidateSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(Canvas canvas) {
|
|
||||||
canvas.save();
|
|
||||||
if (mHitThreshold) {
|
|
||||||
Paint paint = mTextPaint;
|
|
||||||
final int width = mWidth;
|
|
||||||
final int height = mHeight;
|
|
||||||
final int diff = mDiff;
|
|
||||||
final Drawable lArrow = mLeftDrawable;
|
|
||||||
final Drawable rArrow = mRightDrawable;
|
|
||||||
canvas.clipRect(0, 0, width, height);
|
|
||||||
if (mCurrentLanguage == null) {
|
|
||||||
SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
|
|
||||||
mCurrentLanguage = subtypeSwitcher.getInputLanguageName();
|
|
||||||
mNextLanguage = subtypeSwitcher.getNextInputLanguageName();
|
|
||||||
mPrevLanguage = subtypeSwitcher.getPreviousInputLanguageName();
|
|
||||||
}
|
|
||||||
// Draw language text with shadow
|
|
||||||
final float baseline = mHeight * SPACEBAR_LANGUAGE_BASELINE - paint.descent();
|
|
||||||
paint.setColor(mRes.getColor(R.color.latinkeyboard_feedback_language_text));
|
|
||||||
canvas.drawText(mCurrentLanguage, width / 2 + diff, baseline, paint);
|
|
||||||
canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint);
|
|
||||||
canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint);
|
|
||||||
|
|
||||||
setDefaultBounds(lArrow);
|
|
||||||
rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width,
|
|
||||||
rArrow.getIntrinsicHeight());
|
|
||||||
lArrow.draw(canvas);
|
|
||||||
rArrow.draw(canvas);
|
|
||||||
}
|
|
||||||
if (mBackground != null) {
|
|
||||||
canvas.translate(mMiddleX, 0);
|
|
||||||
mBackground.draw(canvas);
|
|
||||||
}
|
|
||||||
canvas.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOpacity() {
|
|
||||||
return PixelFormat.TRANSLUCENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAlpha(int alpha) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setColorFilter(ColorFilter cf) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getIntrinsicWidth() {
|
|
||||||
return mWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getIntrinsicHeight() {
|
|
||||||
return mHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,4 +1,22 @@
|
||||||
package com.android.inputmethod.latin;
|
/*
|
||||||
|
* 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 com.android.inputmethod.latin.KeyboardSwitcher;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
import com.android.inputmethod.latin.LatinIMEUtil;
|
||||||
import com.android.inputmethod.voice.VoiceIMEConnector;
|
import com.android.inputmethod.voice.VoiceIMEConnector;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -31,15 +31,7 @@ import android.view.MotionEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class LatinKeyboardView extends BaseKeyboardView {
|
public class LatinKeyboardView extends KeyboardView {
|
||||||
|
|
||||||
public static final int KEYCODE_OPTIONS = -100;
|
|
||||||
public static final int KEYCODE_OPTIONS_LONGPRESS = -101;
|
|
||||||
// TODO: remove this once LatinIME stops referring to this.
|
|
||||||
public static final int KEYCODE_VOICE = -102;
|
|
||||||
public static final int KEYCODE_NEXT_LANGUAGE = -104;
|
|
||||||
public static final int KEYCODE_PREV_LANGUAGE = -105;
|
|
||||||
public static final int KEYCODE_CAPSLOCK = -106;
|
|
||||||
|
|
||||||
/** Whether we've started dropping move events because we found a big jump */
|
/** Whether we've started dropping move events because we found a big jump */
|
||||||
private boolean mDroppingEvents;
|
private boolean mDroppingEvents;
|
||||||
|
@ -84,7 +76,7 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public LatinKeyboard getLatinKeyboard() {
|
public LatinKeyboard getLatinKeyboard() {
|
||||||
BaseKeyboard keyboard = getKeyboard();
|
Keyboard keyboard = getKeyboard();
|
||||||
if (keyboard instanceof LatinKeyboard) {
|
if (keyboard instanceof LatinKeyboard) {
|
||||||
return (LatinKeyboard)keyboard;
|
return (LatinKeyboard)keyboard;
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,8 +87,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
||||||
@Override
|
@Override
|
||||||
protected boolean onLongPress(Key key) {
|
protected boolean onLongPress(Key key) {
|
||||||
int primaryCode = key.codes[0];
|
int primaryCode = key.codes[0];
|
||||||
if (primaryCode == KEYCODE_OPTIONS) {
|
if (primaryCode == LatinKeyboard.KEYCODE_OPTIONS) {
|
||||||
return invokeOnKey(KEYCODE_OPTIONS_LONGPRESS);
|
return invokeOnKey(LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS);
|
||||||
} else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
|
} else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
|
||||||
// Long pressing on 0 in phone number keypad gives you a '+'.
|
// Long pressing on 0 in phone number keypad gives you a '+'.
|
||||||
return invokeOnKey('+');
|
return invokeOnKey('+');
|
||||||
|
@ -107,8 +99,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
||||||
|
|
||||||
private boolean invokeOnKey(int primaryCode) {
|
private boolean invokeOnKey(int primaryCode) {
|
||||||
getOnKeyboardActionListener().onKey(primaryCode, null,
|
getOnKeyboardActionListener().onKey(primaryCode, null,
|
||||||
BaseKeyboardView.NOT_A_TOUCH_COORDINATE,
|
KeyboardView.NOT_A_TOUCH_COORDINATE,
|
||||||
BaseKeyboardView.NOT_A_TOUCH_COORDINATE);
|
KeyboardView.NOT_A_TOUCH_COORDINATE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +215,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
||||||
int languageDirection = keyboard.getLanguageChangeDirection();
|
int languageDirection = keyboard.getLanguageChangeDirection();
|
||||||
if (languageDirection != 0) {
|
if (languageDirection != 0) {
|
||||||
getOnKeyboardActionListener().onKey(
|
getOnKeyboardActionListener().onKey(
|
||||||
languageDirection == 1 ? KEYCODE_NEXT_LANGUAGE : KEYCODE_PREV_LANGUAGE,
|
languageDirection == 1
|
||||||
|
? LatinKeyboard.KEYCODE_NEXT_LANGUAGE : LatinKeyboard.KEYCODE_PREV_LANGUAGE,
|
||||||
null, mLastX, mLastY);
|
null, mLastX, mLastY);
|
||||||
me.setAction(MotionEvent.ACTION_CANCEL);
|
me.setAction(MotionEvent.ACTION_CANCEL);
|
||||||
keyboard.keyReleased();
|
keyboard.keyReleased();
|
||||||
|
@ -236,8 +229,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
||||||
|
|
||||||
/**************************** INSTRUMENTATION *******************************/
|
/**************************** INSTRUMENTATION *******************************/
|
||||||
|
|
||||||
static final boolean DEBUG_AUTO_PLAY = false;
|
public static final boolean DEBUG_AUTO_PLAY = false;
|
||||||
static final boolean DEBUG_LINE = false;
|
public static final boolean DEBUG_LINE = false;
|
||||||
private static final int MSG_TOUCH_DOWN = 1;
|
private static final int MSG_TOUCH_DOWN = 1;
|
||||||
private static final int MSG_TOUCH_UP = 2;
|
private static final int MSG_TOUCH_UP = 2;
|
||||||
|
|
|
@ -14,11 +14,9 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
public class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
|
|
||||||
class MiniKeyboardKeyDetector extends KeyDetector {
|
|
||||||
private static final int MAX_NEARBY_KEYS = 1;
|
private static final int MAX_NEARBY_KEYS = 1;
|
||||||
|
|
||||||
private final int mSlideAllowanceSquare;
|
private final int mSlideAllowanceSquare;
|
||||||
|
@ -42,7 +40,7 @@ class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
final int touchX = getTouchX(x);
|
final int touchX = getTouchX(x);
|
||||||
final int touchY = getTouchY(y);
|
final int touchY = getTouchY(y);
|
||||||
|
|
||||||
int closestKeyIndex = BaseKeyboardView.NOT_A_KEY;
|
int closestKeyIndex = NOT_A_KEY;
|
||||||
int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
||||||
final int keyCount = keys.length;
|
final int keyCount = keys.length;
|
||||||
for (int index = 0; index < keyCount; index++) {
|
for (int index = 0; index < keyCount; index++) {
|
||||||
|
@ -53,7 +51,7 @@ class MiniKeyboardKeyDetector extends KeyDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allKeys != null && closestKeyIndex != BaseKeyboardView.NOT_A_KEY)
|
if (allKeys != null && closestKeyIndex != NOT_A_KEY)
|
||||||
allKeys[0] = keys[closestKeyIndex].codes[0];
|
allKeys[0] = keys[closestKeyIndex].codes[0];
|
||||||
return closestKeyIndex;
|
return closestKeyIndex;
|
||||||
}
|
}
|
|
@ -14,11 +14,11 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
import com.android.inputmethod.keyboard.KeyboardView.UIHandler;
|
||||||
import com.android.inputmethod.latin.BaseKeyboardView.OnKeyboardActionListener;
|
import com.android.inputmethod.latin.LatinIME;
|
||||||
import com.android.inputmethod.latin.BaseKeyboardView.UIHandler;
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -44,16 +44,16 @@ public class PointerTracker {
|
||||||
private final int mMultiTapKeyTimeout;
|
private final int mMultiTapKeyTimeout;
|
||||||
|
|
||||||
// Miscellaneous constants
|
// Miscellaneous constants
|
||||||
private static final int NOT_A_KEY = BaseKeyboardView.NOT_A_KEY;
|
private static final int NOT_A_KEY = KeyDetector.NOT_A_KEY;
|
||||||
private static final int[] KEY_DELETE = { BaseKeyboard.KEYCODE_DELETE };
|
private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE };
|
||||||
|
|
||||||
private final UIProxy mProxy;
|
private final UIProxy mProxy;
|
||||||
private final UIHandler mHandler;
|
private final UIHandler mHandler;
|
||||||
private final KeyDetector mKeyDetector;
|
private final KeyDetector mKeyDetector;
|
||||||
private OnKeyboardActionListener mListener;
|
private KeyboardActionListener mListener;
|
||||||
private final boolean mHasDistinctMultitouch;
|
private final boolean mHasDistinctMultitouch;
|
||||||
|
|
||||||
private BaseKeyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
private Key[] mKeys;
|
private Key[] mKeys;
|
||||||
private int mKeyHysteresisDistanceSquared = -1;
|
private int mKeyHysteresisDistanceSquared = -1;
|
||||||
|
|
||||||
|
@ -181,11 +181,11 @@ public class PointerTracker {
|
||||||
resetMultiTap();
|
resetMultiTap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
|
public void setOnKeyboardActionListener(KeyboardActionListener listener) {
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyboard(BaseKeyboard keyboard, Key[] keys, float keyHysteresisDistance) {
|
public void setKeyboard(Keyboard keyboard, Key[] keys, float keyHysteresisDistance) {
|
||||||
if (keyboard == null || keys == null || keyHysteresisDistance < 0)
|
if (keyboard == null || keys == null || keyHysteresisDistance < 0)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
mKeyboard = keyboard;
|
mKeyboard = keyboard;
|
||||||
|
@ -208,8 +208,8 @@ public class PointerTracker {
|
||||||
if (key == null)
|
if (key == null)
|
||||||
return false;
|
return false;
|
||||||
int primaryCode = key.codes[0];
|
int primaryCode = key.codes[0];
|
||||||
return primaryCode == BaseKeyboard.KEYCODE_SHIFT
|
return primaryCode == Keyboard.KEYCODE_SHIFT
|
||||||
|| primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE;
|
|| primaryCode == Keyboard.KEYCODE_MODE_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isModifier() {
|
public boolean isModifier() {
|
||||||
|
@ -420,7 +420,7 @@ public class PointerTracker {
|
||||||
|
|
||||||
private void startLongPressTimer(int keyIndex) {
|
private void startLongPressTimer(int keyIndex) {
|
||||||
Key key = getKey(keyIndex);
|
Key key = getKey(keyIndex);
|
||||||
if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT) {
|
if (key.codes[0] == Keyboard.KEYCODE_SHIFT) {
|
||||||
mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
|
mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
|
||||||
} else {
|
} else {
|
||||||
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
||||||
|
@ -433,7 +433,7 @@ public class PointerTracker {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void detectAndSendKey(int index, int x, int y, long eventTime) {
|
private void detectAndSendKey(int index, int x, int y, long eventTime) {
|
||||||
final OnKeyboardActionListener listener = mListener;
|
final KeyboardActionListener listener = mListener;
|
||||||
final Key key = getKey(index);
|
final Key key = getKey(index);
|
||||||
|
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
|
@ -453,7 +453,7 @@ public class PointerTracker {
|
||||||
// Multi-tap
|
// Multi-tap
|
||||||
if (mInMultiTap) {
|
if (mInMultiTap) {
|
||||||
if (mTapCount != -1) {
|
if (mTapCount != -1) {
|
||||||
mListener.onKey(BaseKeyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
|
mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
|
||||||
} else {
|
} else {
|
||||||
mTapCount = 0;
|
mTapCount = 0;
|
||||||
}
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* 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 java.util.LinkedList;
|
||||||
|
|
||||||
|
public class PointerTrackerQueue {
|
||||||
|
private LinkedList<PointerTracker> mQueue = new LinkedList<PointerTracker>();
|
||||||
|
|
||||||
|
public void add(PointerTracker tracker) {
|
||||||
|
mQueue.add(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int lastIndexOf(PointerTracker tracker) {
|
||||||
|
LinkedList<PointerTracker> queue = mQueue;
|
||||||
|
for (int index = queue.size() - 1; index >= 0; index--) {
|
||||||
|
PointerTracker t = queue.get(index);
|
||||||
|
if (t == tracker)
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) {
|
||||||
|
LinkedList<PointerTracker> queue = mQueue;
|
||||||
|
int oldestPos = 0;
|
||||||
|
for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) {
|
||||||
|
if (t.isModifier()) {
|
||||||
|
oldestPos++;
|
||||||
|
} else {
|
||||||
|
t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
|
||||||
|
t.setAlreadyProcessed();
|
||||||
|
queue.remove(oldestPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) {
|
||||||
|
for (PointerTracker t : mQueue) {
|
||||||
|
if (t == tracker)
|
||||||
|
continue;
|
||||||
|
t.onUpEvent(t.getLastX(), t.getLastY(), eventTime);
|
||||||
|
t.setAlreadyProcessed();
|
||||||
|
}
|
||||||
|
mQueue.clear();
|
||||||
|
if (tracker != null)
|
||||||
|
mQueue.add(tracker);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(PointerTracker tracker) {
|
||||||
|
mQueue.remove(tracker);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,13 +14,11 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
class ProximityKeyDetector extends KeyDetector {
|
public class ProximityKeyDetector extends KeyDetector {
|
||||||
private static final int MAX_NEARBY_KEYS = 12;
|
private static final int MAX_NEARBY_KEYS = 12;
|
||||||
|
|
||||||
// working area
|
// working area
|
||||||
|
@ -37,8 +35,8 @@ class ProximityKeyDetector extends KeyDetector {
|
||||||
final int touchX = getTouchX(x);
|
final int touchX = getTouchX(x);
|
||||||
final int touchY = getTouchY(y);
|
final int touchY = getTouchY(y);
|
||||||
|
|
||||||
int primaryIndex = BaseKeyboardView.NOT_A_KEY;
|
int primaryIndex = NOT_A_KEY;
|
||||||
int closestKeyIndex = BaseKeyboardView.NOT_A_KEY;
|
int closestKeyIndex = NOT_A_KEY;
|
||||||
int closestKeyDist = mProximityThresholdSquare + 1;
|
int closestKeyDist = mProximityThresholdSquare + 1;
|
||||||
final int[] distances = mDistances;
|
final int[] distances = mDistances;
|
||||||
Arrays.fill(distances, Integer.MAX_VALUE);
|
Arrays.fill(distances, Integer.MAX_VALUE);
|
||||||
|
@ -72,6 +70,6 @@ class ProximityKeyDetector extends KeyDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return primaryIndex == BaseKeyboardView.NOT_A_KEY ? closestKeyIndex : primaryIndex;
|
return primaryIndex == NOT_A_KEY ? closestKeyIndex : primaryIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* 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 com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
|
||||||
|
* Some of the key size defaults can be overridden per row from what the {@link Keyboard}
|
||||||
|
* defines.
|
||||||
|
*/
|
||||||
|
public class Row {
|
||||||
|
/** Default width of a key in this row. */
|
||||||
|
public int defaultWidth;
|
||||||
|
/** Default height of a key in this row. */
|
||||||
|
public int defaultHeight;
|
||||||
|
/** Default horizontal gap between keys in this row. */
|
||||||
|
public int defaultHorizontalGap;
|
||||||
|
/** Vertical gap following this row. */
|
||||||
|
public int verticalGap;
|
||||||
|
/**
|
||||||
|
* Edge flags for this row of keys. Possible values that can be assigned are
|
||||||
|
* {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM}
|
||||||
|
*/
|
||||||
|
public int rowEdgeFlags;
|
||||||
|
|
||||||
|
final Keyboard parent;
|
||||||
|
|
||||||
|
Row(Keyboard parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Row(Resources res, Keyboard parent, XmlResourceParser parser) {
|
||||||
|
this.parent = parent;
|
||||||
|
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
|
R.styleable.Keyboard);
|
||||||
|
defaultWidth = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_keyWidth,
|
||||||
|
parent.mDisplayWidth, parent.mDefaultWidth);
|
||||||
|
defaultHeight = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_keyHeight,
|
||||||
|
parent.mDisplayHeight, parent.mDefaultHeight);
|
||||||
|
defaultHorizontalGap = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_horizontalGap,
|
||||||
|
parent.mDisplayWidth, parent.mDefaultHorizontalGap);
|
||||||
|
verticalGap = KeyboardParser.getDimensionOrFraction(a,
|
||||||
|
R.styleable.Keyboard_verticalGap,
|
||||||
|
parent.mDisplayHeight, parent.mDefaultVerticalGap);
|
||||||
|
a.recycle();
|
||||||
|
a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
|
R.styleable.Keyboard_Row);
|
||||||
|
rowEdgeFlags = a.getInt(R.styleable.Keyboard_Row_rowEdgeFlags, 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* 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 com.android.inputmethod.latin.R;
|
||||||
|
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.Paint.Align;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Animation to be displayed on the spacebar preview popup when switching languages by swiping the
|
||||||
|
* spacebar. It draws the current, previous and next languages and moves them by the delta of touch
|
||||||
|
* movement on the spacebar.
|
||||||
|
*/
|
||||||
|
public class SlidingLocaleDrawable extends Drawable {
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private final Resources mRes;
|
||||||
|
private final int mWidth;
|
||||||
|
private final int mHeight;
|
||||||
|
private final Drawable mBackground;
|
||||||
|
private final TextPaint mTextPaint;
|
||||||
|
private final int mMiddleX;
|
||||||
|
private final Drawable mLeftDrawable;
|
||||||
|
private final Drawable mRightDrawable;
|
||||||
|
private final int mThreshold;
|
||||||
|
private int mDiff;
|
||||||
|
private boolean mHitThreshold;
|
||||||
|
private String mCurrentLanguage;
|
||||||
|
private String mNextLanguage;
|
||||||
|
private String mPrevLanguage;
|
||||||
|
|
||||||
|
public SlidingLocaleDrawable(Context context, Drawable background, int width, int height) {
|
||||||
|
mContext = context;
|
||||||
|
mRes = context.getResources();
|
||||||
|
mBackground = background;
|
||||||
|
LatinKeyboard.setDefaultBounds(mBackground);
|
||||||
|
mWidth = width;
|
||||||
|
mHeight = height;
|
||||||
|
final TextPaint textPaint = new TextPaint();
|
||||||
|
textPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18));
|
||||||
|
textPaint.setColor(R.color.latinkeyboard_transparent);
|
||||||
|
textPaint.setTextAlign(Align.CENTER);
|
||||||
|
textPaint.setAlpha(LatinKeyboard.OPACITY_FULLY_OPAQUE);
|
||||||
|
textPaint.setAntiAlias(true);
|
||||||
|
mTextPaint = textPaint;
|
||||||
|
mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2;
|
||||||
|
final Resources res = mRes;
|
||||||
|
mLeftDrawable = res.getDrawable(
|
||||||
|
R.drawable.sym_keyboard_feedback_language_arrows_left);
|
||||||
|
mRightDrawable = res.getDrawable(
|
||||||
|
R.drawable.sym_keyboard_feedback_language_arrows_right);
|
||||||
|
mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getTextSizeFromTheme(int style, int defValue) {
|
||||||
|
TypedArray array = mContext.getTheme().obtainStyledAttributes(
|
||||||
|
style, new int[] { android.R.attr.textSize });
|
||||||
|
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
|
||||||
|
return textSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDiff(int diff) {
|
||||||
|
if (diff == Integer.MAX_VALUE) {
|
||||||
|
mHitThreshold = false;
|
||||||
|
mCurrentLanguage = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mDiff = diff;
|
||||||
|
if (mDiff > mWidth) mDiff = mWidth;
|
||||||
|
if (mDiff < -mWidth) mDiff = -mWidth;
|
||||||
|
if (Math.abs(mDiff) > mThreshold) mHitThreshold = true;
|
||||||
|
invalidateSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
canvas.save();
|
||||||
|
if (mHitThreshold) {
|
||||||
|
Paint paint = mTextPaint;
|
||||||
|
final int width = mWidth;
|
||||||
|
final int height = mHeight;
|
||||||
|
final int diff = mDiff;
|
||||||
|
final Drawable lArrow = mLeftDrawable;
|
||||||
|
final Drawable rArrow = mRightDrawable;
|
||||||
|
canvas.clipRect(0, 0, width, height);
|
||||||
|
if (mCurrentLanguage == null) {
|
||||||
|
SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
|
||||||
|
mCurrentLanguage = subtypeSwitcher.getInputLanguageName();
|
||||||
|
mNextLanguage = subtypeSwitcher.getNextInputLanguageName();
|
||||||
|
mPrevLanguage = subtypeSwitcher.getPreviousInputLanguageName();
|
||||||
|
}
|
||||||
|
// Draw language text with shadow
|
||||||
|
final float baseline = mHeight * LatinKeyboard.SPACEBAR_LANGUAGE_BASELINE
|
||||||
|
- paint.descent();
|
||||||
|
paint.setColor(mRes.getColor(R.color.latinkeyboard_feedback_language_text));
|
||||||
|
canvas.drawText(mCurrentLanguage, width / 2 + diff, baseline, paint);
|
||||||
|
canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint);
|
||||||
|
canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint);
|
||||||
|
|
||||||
|
LatinKeyboard.setDefaultBounds(lArrow);
|
||||||
|
rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width,
|
||||||
|
rArrow.getIntrinsicHeight());
|
||||||
|
lArrow.draw(canvas);
|
||||||
|
rArrow.draw(canvas);
|
||||||
|
}
|
||||||
|
if (mBackground != null) {
|
||||||
|
canvas.translate(mMiddleX, 0);
|
||||||
|
mBackground.draw(canvas);
|
||||||
|
}
|
||||||
|
canvas.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
|
return PixelFormat.TRANSLUCENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorFilter(ColorFilter cf) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicWidth() {
|
||||||
|
return mWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicHeight() {
|
||||||
|
return mHeight;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,11 +14,11 @@
|
||||||
* the License.
|
* the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.keyboard;
|
||||||
|
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
class SwipeTracker {
|
public class SwipeTracker {
|
||||||
private static final int NUM_PAST = 4;
|
private static final int NUM_PAST = 4;
|
||||||
private static final int LONGEST_PAST_TIME = 200;
|
private static final int LONGEST_PAST_TIME = 200;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ class SwipeTracker {
|
||||||
return mYVelocity;
|
return mYVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static class EventRingBuffer {
|
public static class EventRingBuffer {
|
||||||
private final int bufSize;
|
private final int bufSize;
|
||||||
private final float xBuf[];
|
private final float xBuf[];
|
||||||
private final float yBuf[];
|
private final float yBuf[];
|
|
@ -1,717 +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.latin;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboardParser.ParseException;
|
|
||||||
import com.android.inputmethod.latin.KeyStyles.KeyStyle;
|
|
||||||
import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
|
|
||||||
|
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.content.res.XmlResourceParser;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Xml;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
|
|
||||||
* consists of rows of keys.
|
|
||||||
* <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
|
|
||||||
* <pre>
|
|
||||||
* <Keyboard
|
|
||||||
* latin:keyWidth="%10p"
|
|
||||||
* latin:keyHeight="50px"
|
|
||||||
* latin:horizontalGap="2px"
|
|
||||||
* latin:verticalGap="2px" >
|
|
||||||
* <Row latin:keyWidth="32px" >
|
|
||||||
* <Key latin:keyLabel="A" />
|
|
||||||
* ...
|
|
||||||
* </Row>
|
|
||||||
* ...
|
|
||||||
* </Keyboard>
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
public class BaseKeyboard {
|
|
||||||
|
|
||||||
static final String TAG = "BaseKeyboard";
|
|
||||||
|
|
||||||
public static final int EDGE_LEFT = 0x01;
|
|
||||||
public static final int EDGE_RIGHT = 0x02;
|
|
||||||
public static final int EDGE_TOP = 0x04;
|
|
||||||
public static final int EDGE_BOTTOM = 0x08;
|
|
||||||
|
|
||||||
public static final int KEYCODE_SHIFT = -1;
|
|
||||||
public static final int KEYCODE_MODE_CHANGE = -2;
|
|
||||||
public static final int KEYCODE_CANCEL = -3;
|
|
||||||
public static final int KEYCODE_DONE = -4;
|
|
||||||
public static final int KEYCODE_DELETE = -5;
|
|
||||||
public static final int KEYCODE_ALT = -6;
|
|
||||||
|
|
||||||
/** Horizontal gap default for all rows */
|
|
||||||
private int mDefaultHorizontalGap;
|
|
||||||
|
|
||||||
/** Default key width */
|
|
||||||
private int mDefaultWidth;
|
|
||||||
|
|
||||||
/** Default key height */
|
|
||||||
private int mDefaultHeight;
|
|
||||||
|
|
||||||
/** Default gap between rows */
|
|
||||||
private int mDefaultVerticalGap;
|
|
||||||
|
|
||||||
/** Is the keyboard in the shifted state */
|
|
||||||
private boolean mShifted;
|
|
||||||
|
|
||||||
/** List of shift keys in this keyboard */
|
|
||||||
private final List<Key> mShiftKeys = new ArrayList<Key>();
|
|
||||||
|
|
||||||
/** List of shift keys and its shifted state icon */
|
|
||||||
private final HashMap<Key, Drawable> mShiftedIcons = new HashMap<Key, Drawable>();
|
|
||||||
|
|
||||||
/** Total height of the keyboard, including the padding and keys */
|
|
||||||
private int mTotalHeight;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Total width of the keyboard, including left side gaps and keys, but not any gaps on the
|
|
||||||
* right side.
|
|
||||||
*/
|
|
||||||
private int mTotalWidth;
|
|
||||||
|
|
||||||
/** List of keys in this keyboard */
|
|
||||||
private final List<Key> mKeys = new ArrayList<Key>();
|
|
||||||
|
|
||||||
/** Width of the screen available to fit the keyboard */
|
|
||||||
private final int mDisplayWidth;
|
|
||||||
|
|
||||||
/** Height of the screen */
|
|
||||||
private final int mDisplayHeight;
|
|
||||||
|
|
||||||
protected final KeyboardId mId;
|
|
||||||
|
|
||||||
// Variables for pre-computing nearest keys.
|
|
||||||
|
|
||||||
public final int GRID_WIDTH;
|
|
||||||
public final int GRID_HEIGHT;
|
|
||||||
private final int GRID_SIZE;
|
|
||||||
private int mCellWidth;
|
|
||||||
private int mCellHeight;
|
|
||||||
private int[][] mGridNeighbors;
|
|
||||||
private int mProximityThreshold;
|
|
||||||
private static int[] EMPTY_INT_ARRAY = new int[0];
|
|
||||||
/** Number of key widths from current touch point to search for nearest keys. */
|
|
||||||
private static float SEARCH_DISTANCE = 1.2f;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
|
|
||||||
* Some of the key size defaults can be overridden per row from what the {@link BaseKeyboard}
|
|
||||||
* defines.
|
|
||||||
*/
|
|
||||||
public static class Row {
|
|
||||||
/** Default width of a key in this row. */
|
|
||||||
public int defaultWidth;
|
|
||||||
/** Default height of a key in this row. */
|
|
||||||
public int defaultHeight;
|
|
||||||
/** Default horizontal gap between keys in this row. */
|
|
||||||
public int defaultHorizontalGap;
|
|
||||||
/** Vertical gap following this row. */
|
|
||||||
public int verticalGap;
|
|
||||||
/**
|
|
||||||
* Edge flags for this row of keys. Possible values that can be assigned are
|
|
||||||
* {@link BaseKeyboard#EDGE_TOP EDGE_TOP} and {@link BaseKeyboard#EDGE_BOTTOM EDGE_BOTTOM}
|
|
||||||
*/
|
|
||||||
public int rowEdgeFlags;
|
|
||||||
|
|
||||||
private final BaseKeyboard parent;
|
|
||||||
|
|
||||||
private Row(BaseKeyboard parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Row(Resources res, BaseKeyboard parent, XmlResourceParser parser) {
|
|
||||||
this.parent = parent;
|
|
||||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
|
||||||
R.styleable.BaseKeyboard);
|
|
||||||
defaultWidth = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_keyWidth,
|
|
||||||
parent.mDisplayWidth, parent.mDefaultWidth);
|
|
||||||
defaultHeight = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_keyHeight,
|
|
||||||
parent.mDisplayHeight, parent.mDefaultHeight);
|
|
||||||
defaultHorizontalGap = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_horizontalGap,
|
|
||||||
parent.mDisplayWidth, parent.mDefaultHorizontalGap);
|
|
||||||
verticalGap = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_verticalGap,
|
|
||||||
parent.mDisplayHeight, parent.mDefaultVerticalGap);
|
|
||||||
a.recycle();
|
|
||||||
a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
|
||||||
R.styleable.BaseKeyboard_Row);
|
|
||||||
rowEdgeFlags = a.getInt(R.styleable.BaseKeyboard_Row_rowEdgeFlags, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for describing the position and characteristics of a single key in the keyboard.
|
|
||||||
*/
|
|
||||||
public static class Key {
|
|
||||||
/**
|
|
||||||
* All the key codes (unicode or custom code) that this key could generate, zero'th
|
|
||||||
* being the most important.
|
|
||||||
*/
|
|
||||||
public int[] codes;
|
|
||||||
/** The unicode that this key generates in manual temporary upper case mode. */
|
|
||||||
public int manualTemporaryUpperCaseCode;
|
|
||||||
|
|
||||||
/** Label to display */
|
|
||||||
public CharSequence label;
|
|
||||||
/** Option of the label */
|
|
||||||
public int labelOption;
|
|
||||||
|
|
||||||
/** Icon to display instead of a label. Icon takes precedence over a label */
|
|
||||||
public Drawable icon;
|
|
||||||
/** Hint icon to display on the key in conjunction with the label */
|
|
||||||
public Drawable hintIcon;
|
|
||||||
/** Preview version of the icon, for the preview popup */
|
|
||||||
/**
|
|
||||||
* The hint icon to display on the key when keyboard is in manual temporary upper case
|
|
||||||
* mode.
|
|
||||||
*/
|
|
||||||
public Drawable manualTemporaryUpperCaseHintIcon;
|
|
||||||
|
|
||||||
public Drawable iconPreview;
|
|
||||||
/** Width of the key, not including the gap */
|
|
||||||
public int width;
|
|
||||||
/** Height of the key, not including the gap */
|
|
||||||
public int height;
|
|
||||||
/** The horizontal gap before this key */
|
|
||||||
public int gap;
|
|
||||||
/** Whether this key is sticky, i.e., a toggle key */
|
|
||||||
public boolean sticky;
|
|
||||||
/** X coordinate of the key in the keyboard layout */
|
|
||||||
public int x;
|
|
||||||
/** Y coordinate of the key in the keyboard layout */
|
|
||||||
public int y;
|
|
||||||
/** The current pressed state of this key */
|
|
||||||
public boolean pressed;
|
|
||||||
/** If this is a sticky key, is it on? */
|
|
||||||
public boolean on;
|
|
||||||
/** Text to output when pressed. This can be multiple characters, like ".com" */
|
|
||||||
public CharSequence text;
|
|
||||||
/** Popup characters */
|
|
||||||
public CharSequence popupCharacters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flags that specify the anchoring to edges of the keyboard for detecting touch events
|
|
||||||
* that are just out of the boundary of the key. This is a bit mask of
|
|
||||||
* {@link BaseKeyboard#EDGE_LEFT}, {@link BaseKeyboard#EDGE_RIGHT},
|
|
||||||
* {@link BaseKeyboard#EDGE_TOP} and {@link BaseKeyboard#EDGE_BOTTOM}.
|
|
||||||
*/
|
|
||||||
public int edgeFlags;
|
|
||||||
/** Whether this is a modifier key, such as Shift or Alt */
|
|
||||||
public boolean modifier;
|
|
||||||
/** The BaseKeyboard that this key belongs to */
|
|
||||||
protected final BaseKeyboard keyboard;
|
|
||||||
/**
|
|
||||||
* If this key pops up a mini keyboard, this is the resource id for the XML layout for that
|
|
||||||
* keyboard.
|
|
||||||
*/
|
|
||||||
public int popupResId;
|
|
||||||
/** Whether this key repeats itself when held down */
|
|
||||||
public boolean repeatable;
|
|
||||||
|
|
||||||
|
|
||||||
private final static int[] KEY_STATE_NORMAL_ON = {
|
|
||||||
android.R.attr.state_checkable,
|
|
||||||
android.R.attr.state_checked
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static int[] KEY_STATE_PRESSED_ON = {
|
|
||||||
android.R.attr.state_pressed,
|
|
||||||
android.R.attr.state_checkable,
|
|
||||||
android.R.attr.state_checked
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static int[] KEY_STATE_NORMAL_OFF = {
|
|
||||||
android.R.attr.state_checkable
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static int[] KEY_STATE_PRESSED_OFF = {
|
|
||||||
android.R.attr.state_pressed,
|
|
||||||
android.R.attr.state_checkable
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static int[] KEY_STATE_NORMAL = {
|
|
||||||
};
|
|
||||||
|
|
||||||
private final static int[] KEY_STATE_PRESSED = {
|
|
||||||
android.R.attr.state_pressed
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Create an empty key with no attributes. */
|
|
||||||
public Key(Row parent) {
|
|
||||||
keyboard = parent.parent;
|
|
||||||
height = parent.defaultHeight;
|
|
||||||
gap = parent.defaultHorizontalGap;
|
|
||||||
width = parent.defaultWidth - gap;
|
|
||||||
edgeFlags = parent.rowEdgeFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a key with the given top-left coordinate and extract its attributes from
|
|
||||||
* the XML parser.
|
|
||||||
* @param res resources associated with the caller's context
|
|
||||||
* @param parent the row that this key belongs to. The row must already be attached to
|
|
||||||
* a {@link BaseKeyboard}.
|
|
||||||
* @param x the x coordinate of the top-left
|
|
||||||
* @param y the y coordinate of the top-left
|
|
||||||
* @param parser the XML parser containing the attributes for this key
|
|
||||||
*/
|
|
||||||
public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser,
|
|
||||||
KeyStyles keyStyles) {
|
|
||||||
this(parent);
|
|
||||||
|
|
||||||
TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
|
|
||||||
R.styleable.BaseKeyboard);
|
|
||||||
height = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_keyHeight,
|
|
||||||
keyboard.mDisplayHeight, parent.defaultHeight);
|
|
||||||
gap = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_horizontalGap,
|
|
||||||
keyboard.mDisplayWidth, parent.defaultHorizontalGap);
|
|
||||||
width = BaseKeyboardParser.getDimensionOrFraction(a,
|
|
||||||
R.styleable.BaseKeyboard_keyWidth,
|
|
||||||
keyboard.mDisplayWidth, parent.defaultWidth) - gap;
|
|
||||||
a.recycle();
|
|
||||||
|
|
||||||
a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.BaseKeyboard_Key);
|
|
||||||
|
|
||||||
final KeyStyle style;
|
|
||||||
if (a.hasValue(R.styleable.BaseKeyboard_Key_keyStyle)) {
|
|
||||||
String styleName = a.getString(R.styleable.BaseKeyboard_Key_keyStyle);
|
|
||||||
style = keyStyles.getKeyStyle(styleName);
|
|
||||||
if (style == null)
|
|
||||||
throw new ParseException("Unknown key style: " + styleName, parser);
|
|
||||||
} else {
|
|
||||||
style = keyStyles.getEmptyKeyStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Horizontal gap is divided equally to both sides of the key.
|
|
||||||
this.x = x + gap / 2;
|
|
||||||
this.y = y;
|
|
||||||
|
|
||||||
codes = style.getIntArray(a, R.styleable.BaseKeyboard_Key_codes);
|
|
||||||
iconPreview = style.getDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
|
|
||||||
setDefaultBounds(iconPreview);
|
|
||||||
popupCharacters = style.getText(a, R.styleable.BaseKeyboard_Key_popupCharacters);
|
|
||||||
popupResId = style.getResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard, 0);
|
|
||||||
repeatable = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable, false);
|
|
||||||
modifier = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isModifier, false);
|
|
||||||
sticky = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isSticky, false);
|
|
||||||
edgeFlags = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0);
|
|
||||||
edgeFlags |= parent.rowEdgeFlags;
|
|
||||||
|
|
||||||
icon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
|
|
||||||
setDefaultBounds(icon);
|
|
||||||
hintIcon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
|
|
||||||
setDefaultBounds(hintIcon);
|
|
||||||
manualTemporaryUpperCaseHintIcon = style.getDrawable(a,
|
|
||||||
R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseHintIcon);
|
|
||||||
setDefaultBounds(manualTemporaryUpperCaseHintIcon);
|
|
||||||
|
|
||||||
label = style.getText(a, R.styleable.BaseKeyboard_Key_keyLabel);
|
|
||||||
labelOption = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption, 0);
|
|
||||||
manualTemporaryUpperCaseCode = style.getInt(a,
|
|
||||||
R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseCode, 0);
|
|
||||||
text = style.getText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
|
|
||||||
final Drawable shiftedIcon = style.getDrawable(a,
|
|
||||||
R.styleable.BaseKeyboard_Key_shiftedIcon);
|
|
||||||
if (shiftedIcon != null)
|
|
||||||
keyboard.getShiftedIcons().put(this, shiftedIcon);
|
|
||||||
|
|
||||||
if (codes == null && !TextUtils.isEmpty(label)) {
|
|
||||||
codes = new int[] { label.charAt(0) };
|
|
||||||
}
|
|
||||||
a.recycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Informs the key that it has been pressed, in case it needs to change its appearance or
|
|
||||||
* state.
|
|
||||||
* @see #onReleased(boolean)
|
|
||||||
*/
|
|
||||||
public void onPressed() {
|
|
||||||
pressed = !pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the pressed state of the key. If it is a sticky key, it will also change the
|
|
||||||
* toggled state of the key if the finger was release inside.
|
|
||||||
* @param inside whether the finger was released inside the key
|
|
||||||
* @see #onPressed()
|
|
||||||
*/
|
|
||||||
public void onReleased(boolean inside) {
|
|
||||||
pressed = !pressed;
|
|
||||||
if (sticky) {
|
|
||||||
on = !on;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detects if a point falls inside this key.
|
|
||||||
* @param x the x-coordinate of the point
|
|
||||||
* @param y the y-coordinate of the point
|
|
||||||
* @return whether or not the point falls inside the key. If the key is attached to an
|
|
||||||
* edge, it will assume that all points between the key and the edge are considered to be
|
|
||||||
* inside the key.
|
|
||||||
*/
|
|
||||||
public boolean isInside(int x, int y) {
|
|
||||||
boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0;
|
|
||||||
boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0;
|
|
||||||
boolean topEdge = (edgeFlags & EDGE_TOP) > 0;
|
|
||||||
boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0;
|
|
||||||
if ((x >= this.x || (leftEdge && x <= this.x + this.width))
|
|
||||||
&& (x < this.x + this.width || (rightEdge && x >= this.x))
|
|
||||||
&& (y >= this.y || (topEdge && y <= this.y + this.height))
|
|
||||||
&& (y < this.y + this.height || (bottomEdge && y >= this.y))) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the square of the distance to the nearest edge of the key and the given point.
|
|
||||||
* @param x the x-coordinate of the point
|
|
||||||
* @param y the y-coordinate of the point
|
|
||||||
* @return the square of the distance of the point from the nearest edge of the key
|
|
||||||
*/
|
|
||||||
public int squaredDistanceToEdge(int x, int y) {
|
|
||||||
final int left = this.x;
|
|
||||||
final int right = left + this.width;
|
|
||||||
final int top = this.y;
|
|
||||||
final int bottom = top + this.height;
|
|
||||||
final int edgeX = x < left ? left : (x > right ? right : x);
|
|
||||||
final int edgeY = y < top ? top : (y > bottom ? bottom : y);
|
|
||||||
final int dx = x - edgeX;
|
|
||||||
final int dy = y - edgeY;
|
|
||||||
return dx * dx + dy * dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the drawable state for the key, based on the current state and type of the key.
|
|
||||||
* @return the drawable state of the key.
|
|
||||||
* @see android.graphics.drawable.StateListDrawable#setState(int[])
|
|
||||||
*/
|
|
||||||
public int[] getCurrentDrawableState() {
|
|
||||||
int[] states = KEY_STATE_NORMAL;
|
|
||||||
|
|
||||||
if (on) {
|
|
||||||
if (pressed) {
|
|
||||||
states = KEY_STATE_PRESSED_ON;
|
|
||||||
} else {
|
|
||||||
states = KEY_STATE_NORMAL_ON;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (sticky) {
|
|
||||||
if (pressed) {
|
|
||||||
states = KEY_STATE_PRESSED_OFF;
|
|
||||||
} else {
|
|
||||||
states = KEY_STATE_NORMAL_OFF;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (pressed) {
|
|
||||||
states = KEY_STATE_PRESSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return states;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a keyboard from the given xml key layout file.
|
|
||||||
* @param context the application or service context
|
|
||||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
|
||||||
*/
|
|
||||||
public BaseKeyboard(Context context, int xmlLayoutResId) {
|
|
||||||
this(context, xmlLayoutResId, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a keyboard from the given keyboard identifier.
|
|
||||||
* @param context the application or service context
|
|
||||||
* @param id keyboard identifier
|
|
||||||
*/
|
|
||||||
public BaseKeyboard(Context context, KeyboardId id) {
|
|
||||||
this(context, id.getXmlId(), id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a keyboard from the given xml key layout file.
|
|
||||||
* @param context the application or service context
|
|
||||||
* @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
|
|
||||||
* @param id keyboard identifier
|
|
||||||
*/
|
|
||||||
private BaseKeyboard(Context context, int xmlLayoutResId, KeyboardId id) {
|
|
||||||
this(context, xmlLayoutResId, id,
|
|
||||||
context.getResources().getDisplayMetrics().widthPixels,
|
|
||||||
context.getResources().getDisplayMetrics().heightPixels);
|
|
||||||
}
|
|
||||||
|
|
||||||
private BaseKeyboard(Context context, int xmlLayoutResId, KeyboardId id, int width,
|
|
||||||
int height) {
|
|
||||||
Resources res = context.getResources();
|
|
||||||
GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
|
|
||||||
GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
|
|
||||||
GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
|
|
||||||
|
|
||||||
mDisplayWidth = width;
|
|
||||||
mDisplayHeight = height;
|
|
||||||
|
|
||||||
mDefaultHorizontalGap = 0;
|
|
||||||
setKeyWidth(mDisplayWidth / 10);
|
|
||||||
mDefaultVerticalGap = 0;
|
|
||||||
mDefaultHeight = mDefaultWidth;
|
|
||||||
mId = id;
|
|
||||||
loadKeyboard(context, xmlLayoutResId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Creates a blank keyboard from the given resource file and populates it with the specified
|
|
||||||
* characters in left-to-right, top-to-bottom fashion, using the specified number of columns.
|
|
||||||
* </p>
|
|
||||||
* <p>If the specified number of columns is -1, then the keyboard will fit as many keys as
|
|
||||||
* possible in each row.</p>
|
|
||||||
* @param context the application or service context
|
|
||||||
* @param layoutTemplateResId the layout template file, containing no keys.
|
|
||||||
* @param characters the list of characters to display on the keyboard. One key will be created
|
|
||||||
* for each character.
|
|
||||||
* @param columns the number of columns of keys to display. If this number is greater than the
|
|
||||||
* number of keys that can fit in a row, it will be ignored. If this number is -1, the
|
|
||||||
* keyboard will fit as many keys as possible in each row.
|
|
||||||
*/
|
|
||||||
public BaseKeyboard(Context context, int layoutTemplateResId,
|
|
||||||
CharSequence characters, int columns, int horizontalPadding) {
|
|
||||||
this(context, layoutTemplateResId);
|
|
||||||
int x = 0;
|
|
||||||
int y = 0;
|
|
||||||
int column = 0;
|
|
||||||
mTotalWidth = 0;
|
|
||||||
|
|
||||||
Row row = new Row(this);
|
|
||||||
row.defaultHeight = mDefaultHeight;
|
|
||||||
row.defaultWidth = mDefaultWidth;
|
|
||||||
row.defaultHorizontalGap = mDefaultHorizontalGap;
|
|
||||||
row.verticalGap = mDefaultVerticalGap;
|
|
||||||
row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
|
|
||||||
final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
|
|
||||||
for (int i = 0; i < characters.length(); i++) {
|
|
||||||
char c = characters.charAt(i);
|
|
||||||
if (column >= maxColumns
|
|
||||||
|| x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
|
|
||||||
x = 0;
|
|
||||||
y += mDefaultVerticalGap + mDefaultHeight;
|
|
||||||
column = 0;
|
|
||||||
}
|
|
||||||
final Key key = new Key(row);
|
|
||||||
// Horizontal gap is divided equally to both sides of the key.
|
|
||||||
key.x = x + key.gap / 2;
|
|
||||||
key.y = y;
|
|
||||||
key.label = String.valueOf(c);
|
|
||||||
key.codes = new int[] { c };
|
|
||||||
column++;
|
|
||||||
x += key.width + key.gap;
|
|
||||||
mKeys.add(key);
|
|
||||||
if (x > mTotalWidth) {
|
|
||||||
mTotalWidth = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mTotalHeight = y + mDefaultHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public KeyboardId getKeyboardId() {
|
|
||||||
return mId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Key> getKeys() {
|
|
||||||
return mKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getHorizontalGap() {
|
|
||||||
return mDefaultHorizontalGap;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setHorizontalGap(int gap) {
|
|
||||||
mDefaultHorizontalGap = gap;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getVerticalGap() {
|
|
||||||
return mDefaultVerticalGap;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setVerticalGap(int gap) {
|
|
||||||
mDefaultVerticalGap = gap;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getKeyHeight() {
|
|
||||||
return mDefaultHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setKeyHeight(int height) {
|
|
||||||
mDefaultHeight = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int getKeyWidth() {
|
|
||||||
return mDefaultWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setKeyWidth(int width) {
|
|
||||||
mDefaultWidth = width;
|
|
||||||
final int threshold = (int) (width * SEARCH_DISTANCE);
|
|
||||||
mProximityThreshold = threshold * threshold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the total height of the keyboard
|
|
||||||
* @return the total height of the keyboard
|
|
||||||
*/
|
|
||||||
public int getHeight() {
|
|
||||||
return mTotalHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinWidth() {
|
|
||||||
return mTotalWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKeyboardHeight() {
|
|
||||||
return mDisplayHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKeyboardWidth() {
|
|
||||||
return mDisplayWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean setShifted(boolean shiftState) {
|
|
||||||
for (final Key key : mShiftKeys) {
|
|
||||||
key.on = shiftState;
|
|
||||||
}
|
|
||||||
if (mShifted != shiftState) {
|
|
||||||
mShifted = shiftState;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isShiftedOrShiftLocked() {
|
|
||||||
return mShifted;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Key> getShiftKeys() {
|
|
||||||
return mShiftKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Key, Drawable> getShiftedIcons() {
|
|
||||||
return mShiftedIcons;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void computeNearestNeighbors() {
|
|
||||||
// Round-up so we don't have any pixels outside the grid
|
|
||||||
mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
|
|
||||||
mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
|
|
||||||
mGridNeighbors = new int[GRID_SIZE][];
|
|
||||||
final int[] indices = new int[mKeys.size()];
|
|
||||||
final int gridWidth = GRID_WIDTH * mCellWidth;
|
|
||||||
final int gridHeight = GRID_HEIGHT * mCellHeight;
|
|
||||||
final int threshold = mProximityThreshold;
|
|
||||||
for (int x = 0; x < gridWidth; x += mCellWidth) {
|
|
||||||
for (int y = 0; y < gridHeight; y += mCellHeight) {
|
|
||||||
final int centerX = x + mCellWidth / 2;
|
|
||||||
final int centerY = y + mCellHeight / 2;
|
|
||||||
int count = 0;
|
|
||||||
for (int i = 0; i < mKeys.size(); i++) {
|
|
||||||
final Key key = mKeys.get(i);
|
|
||||||
if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
|
|
||||||
indices[count++] = i;
|
|
||||||
}
|
|
||||||
final int[] cell = new int[count];
|
|
||||||
System.arraycopy(indices, 0, cell, 0, count);
|
|
||||||
mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the indices of the keys that are closest to the given point.
|
|
||||||
* @param x the x-coordinate of the point
|
|
||||||
* @param y the y-coordinate of the point
|
|
||||||
* @return the array of integer indices for the nearest keys to the given point. If the given
|
|
||||||
* point is out of range, then an array of size zero is returned.
|
|
||||||
*/
|
|
||||||
public int[] getNearestKeys(int x, int y) {
|
|
||||||
if (mGridNeighbors == null) computeNearestNeighbors();
|
|
||||||
if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
|
|
||||||
int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
|
|
||||||
if (index < GRID_SIZE) {
|
|
||||||
return mGridNeighbors[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EMPTY_INT_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should be private
|
|
||||||
protected BaseKeyboard.Row createRowFromXml(Resources res, XmlResourceParser parser) {
|
|
||||||
return new BaseKeyboard.Row(res, this, parser);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should be private
|
|
||||||
protected BaseKeyboard.Key createKeyFromXml(Resources res, Row parent, int x, int y,
|
|
||||||
XmlResourceParser parser, KeyStyles keyStyles) {
|
|
||||||
return new BaseKeyboard.Key(res, parent, x, y, parser, keyStyles);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadKeyboard(Context context, int xmlLayoutResId) {
|
|
||||||
try {
|
|
||||||
final Resources res = context.getResources();
|
|
||||||
BaseKeyboardParser parser = new BaseKeyboardParser(this, res);
|
|
||||||
parser.parseKeyboard(res.getXml(xmlLayoutResId));
|
|
||||||
// mTotalWidth is the width of this keyboard which is maximum width of row.
|
|
||||||
mTotalWidth = parser.getMaxRowWidth();
|
|
||||||
mTotalHeight = parser.getTotalHeight();
|
|
||||||
} catch (XmlPullParserException e) {
|
|
||||||
Log.w(TAG, "keyboard XML parse error: " + e);
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.w(TAG, "keyboard XML parse error: " + e);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void setDefaultBounds(Drawable drawable) {
|
|
||||||
if (drawable != null)
|
|
||||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
|
|
||||||
drawable.getIntrinsicHeight());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -57,6 +57,7 @@ public class InputLanguageSelection extends PreferenceActivity {
|
||||||
return this.label;
|
return this.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int compareTo(Object o) {
|
public int compareTo(Object o) {
|
||||||
return sCollator.compare(this.label, ((Loc) o).label);
|
return sCollator.compare(this.label, ((Loc) o).label);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,19 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.KeyboardView;
|
||||||
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboard;
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboardView;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.InflateException;
|
import android.view.InflateException;
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
@ -34,14 +37,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
public static final boolean DEBUG_STATE = false;
|
public static final boolean DEBUG_STATE = false;
|
||||||
|
|
||||||
public static final int MODE_TEXT = 0;
|
|
||||||
public static final int MODE_URL = 1;
|
|
||||||
public static final int MODE_EMAIL = 2;
|
|
||||||
public static final int MODE_IM = 3;
|
|
||||||
public static final int MODE_WEB = 4;
|
|
||||||
public static final int MODE_PHONE = 5;
|
|
||||||
public static final int MODE_NUMBER = 6;
|
|
||||||
|
|
||||||
// Changing DEFAULT_LAYOUT_ID also requires prefs_for_debug.xml to be matched with.
|
// Changing DEFAULT_LAYOUT_ID also requires prefs_for_debug.xml to be matched with.
|
||||||
public static final String DEFAULT_LAYOUT_ID = "5";
|
public static final String DEFAULT_LAYOUT_ID = "5";
|
||||||
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
|
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
|
||||||
|
@ -74,7 +69,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
|
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
|
||||||
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
|
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
|
||||||
|
|
||||||
private int mMode = MODE_TEXT; /* default value */
|
private int mMode = KeyboardId.MODE_TEXT; /* default value */
|
||||||
private int mImeOptions;
|
private int mImeOptions;
|
||||||
private boolean mIsSymbols;
|
private boolean mIsSymbols;
|
||||||
/** mIsAutoCompletionActive indicates that auto completed word will be input instead of
|
/** mIsAutoCompletionActive indicates that auto completed word will be input instead of
|
||||||
|
@ -132,129 +127,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
|
// mSymbolsId and mSymbolsShiftedId to "phone keyboard" and "phone symbols keyboard"
|
||||||
// respectively here for xlarge device's layout switching.
|
// respectively here for xlarge device's layout switching.
|
||||||
mSymbolsId = new KeyboardId(locale, orientation, mode,
|
mSymbolsId = new KeyboardId(locale, orientation, mode,
|
||||||
mode == MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols,
|
mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone : R.xml.kbd_symbols,
|
||||||
colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
|
colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
|
||||||
mSymbolsShiftedId = new KeyboardId(locale, orientation, mode,
|
mSymbolsShiftedId = new KeyboardId(locale, orientation, mode,
|
||||||
mode == MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift,
|
mode == KeyboardId.MODE_PHONE ? R.xml.kbd_phone_symbols : R.xml.kbd_symbols_shift,
|
||||||
colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
|
colorScheme, hasSettingsKey, voiceKeyEnabled, hasVoiceKey, imeOptions, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the parameters necessary to construct a new LatinKeyboard,
|
|
||||||
* which also serve as a unique identifier for each keyboard type.
|
|
||||||
*/
|
|
||||||
public static class KeyboardId {
|
|
||||||
public final Locale mLocale;
|
|
||||||
public final int mOrientation;
|
|
||||||
public final int mMode;
|
|
||||||
public final int mXmlId;
|
|
||||||
public final int mColorScheme;
|
|
||||||
public final boolean mHasSettingsKey;
|
|
||||||
public final boolean mVoiceKeyEnabled;
|
|
||||||
public final boolean mHasVoiceKey;
|
|
||||||
public final int mImeOptions;
|
|
||||||
public final boolean mEnableShiftLock;
|
|
||||||
|
|
||||||
private final int mHashCode;
|
|
||||||
|
|
||||||
public KeyboardId(Locale locale, int orientation, int mode,
|
|
||||||
int xmlId, int colorScheme, boolean hasSettingsKey, boolean voiceKeyEnabled,
|
|
||||||
boolean hasVoiceKey, int imeOptions, boolean enableShiftLock) {
|
|
||||||
this.mLocale = locale;
|
|
||||||
this.mOrientation = orientation;
|
|
||||||
this.mMode = mode;
|
|
||||||
this.mXmlId = xmlId;
|
|
||||||
this.mColorScheme = colorScheme;
|
|
||||||
this.mHasSettingsKey = hasSettingsKey;
|
|
||||||
this.mVoiceKeyEnabled = voiceKeyEnabled;
|
|
||||||
this.mHasVoiceKey = hasVoiceKey;
|
|
||||||
// We are interested only in IME_MASK_ACTION enum value and IME_FLAG_NO_ENTER_ACTION.
|
|
||||||
this.mImeOptions = imeOptions
|
|
||||||
& (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
|
|
||||||
this.mEnableShiftLock = enableShiftLock;
|
|
||||||
|
|
||||||
this.mHashCode = Arrays.hashCode(new Object[] {
|
|
||||||
locale,
|
|
||||||
orientation,
|
|
||||||
mode,
|
|
||||||
xmlId,
|
|
||||||
colorScheme,
|
|
||||||
hasSettingsKey,
|
|
||||||
voiceKeyEnabled,
|
|
||||||
hasVoiceKey,
|
|
||||||
imeOptions,
|
|
||||||
enableShiftLock,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getXmlId() {
|
|
||||||
return mXmlId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAlphabetMode() {
|
|
||||||
return mXmlId == R.xml.kbd_qwerty;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
return other instanceof KeyboardId && equals((KeyboardId) other);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean equals(KeyboardId other) {
|
|
||||||
return other.mLocale.equals(this.mLocale)
|
|
||||||
&& other.mOrientation == this.mOrientation
|
|
||||||
&& other.mMode == this.mMode
|
|
||||||
&& other.mXmlId == this.mXmlId
|
|
||||||
&& other.mColorScheme == this.mColorScheme
|
|
||||||
&& other.mHasSettingsKey == this.mHasSettingsKey
|
|
||||||
&& other.mVoiceKeyEnabled == this.mVoiceKeyEnabled
|
|
||||||
&& other.mHasVoiceKey == this.mHasVoiceKey
|
|
||||||
&& other.mImeOptions == this.mImeOptions
|
|
||||||
&& other.mEnableShiftLock == this.mEnableShiftLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return mHashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("[%s %s %5s imeOptions=0x%08x xml=0x%08x %s%s%s%s%s]",
|
|
||||||
mLocale,
|
|
||||||
(mOrientation == 1 ? "port" : "land"),
|
|
||||||
modeName(mMode),
|
|
||||||
mImeOptions,
|
|
||||||
mXmlId,
|
|
||||||
colorSchemeName(mColorScheme),
|
|
||||||
(mHasSettingsKey ? " hasSettingsKey" : ""),
|
|
||||||
(mVoiceKeyEnabled ? " voiceKeyEnabled" : ""),
|
|
||||||
(mHasVoiceKey ? " hasVoiceKey" : ""),
|
|
||||||
(mEnableShiftLock ? " enableShiftLock" : ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String modeName(int mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case MODE_TEXT: return "text";
|
|
||||||
case MODE_URL: return "url";
|
|
||||||
case MODE_EMAIL: return "email";
|
|
||||||
case MODE_IM: return "im";
|
|
||||||
case MODE_WEB: return "web";
|
|
||||||
case MODE_PHONE: return "phone";
|
|
||||||
case MODE_NUMBER: return "number";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String colorSchemeName(int colorScheme) {
|
|
||||||
switch (colorScheme) {
|
|
||||||
case BaseKeyboardView.COLOR_SCHEME_WHITE: return "white";
|
|
||||||
case BaseKeyboardView.COLOR_SCHEME_BLACK: return "black";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasVoiceKey(boolean isSymbols) {
|
private boolean hasVoiceKey(boolean isSymbols) {
|
||||||
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
|
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
|
||||||
}
|
}
|
||||||
|
@ -327,9 +206,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
final boolean enableShiftLock;
|
final boolean enableShiftLock;
|
||||||
|
|
||||||
if (isSymbols) {
|
if (isSymbols) {
|
||||||
if (mode == MODE_PHONE) {
|
if (mode == KeyboardId.MODE_PHONE) {
|
||||||
xmlId = R.xml.kbd_phone_symbols;
|
xmlId = R.xml.kbd_phone_symbols;
|
||||||
} else if (mode == MODE_NUMBER) {
|
} else if (mode == KeyboardId.MODE_NUMBER) {
|
||||||
// Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key.
|
// Note: MODE_NUMBER keyboard layout has no "switch alpha symbol" key.
|
||||||
xmlId = R.xml.kbd_number;
|
xmlId = R.xml.kbd_number;
|
||||||
} else {
|
} else {
|
||||||
|
@ -337,10 +216,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
}
|
}
|
||||||
enableShiftLock = false;
|
enableShiftLock = false;
|
||||||
} else {
|
} else {
|
||||||
if (mode == MODE_PHONE) {
|
if (mode == KeyboardId.MODE_PHONE) {
|
||||||
xmlId = R.xml.kbd_phone;
|
xmlId = R.xml.kbd_phone;
|
||||||
enableShiftLock = false;
|
enableShiftLock = false;
|
||||||
} else if (mode == MODE_NUMBER) {
|
} else if (mode == KeyboardId.MODE_NUMBER) {
|
||||||
xmlId = R.xml.kbd_number;
|
xmlId = R.xml.kbd_number;
|
||||||
enableShiftLock = false;
|
enableShiftLock = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -731,7 +610,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
||||||
|
|
||||||
private int getColorScheme() {
|
private int getColorScheme() {
|
||||||
return (mInputView != null)
|
return (mInputView != null)
|
||||||
? mInputView.getColorScheme() : BaseKeyboardView.COLOR_SCHEME_WHITE;
|
? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
|
public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
|
import com.android.inputmethod.keyboard.KeyboardActionListener;
|
||||||
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
|
import com.android.inputmethod.keyboard.KeyboardView;
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboard;
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboardView;
|
||||||
import com.android.inputmethod.latin.LatinIMEUtil.RingCharBuffer;
|
import com.android.inputmethod.latin.LatinIMEUtil.RingCharBuffer;
|
||||||
import com.android.inputmethod.voice.VoiceIMEConnector;
|
import com.android.inputmethod.voice.VoiceIMEConnector;
|
||||||
|
|
||||||
|
@ -73,7 +79,7 @@ import java.util.Locale;
|
||||||
* Input method implementation for Qwerty'ish keyboard.
|
* Input method implementation for Qwerty'ish keyboard.
|
||||||
*/
|
*/
|
||||||
public class LatinIME extends InputMethodService
|
public class LatinIME extends InputMethodService
|
||||||
implements BaseKeyboardView.OnKeyboardActionListener,
|
implements KeyboardActionListener,
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener,
|
SharedPreferences.OnSharedPreferenceChangeListener,
|
||||||
Tutorial.TutorialListener {
|
Tutorial.TutorialListener {
|
||||||
private static final String TAG = "LatinIME";
|
private static final String TAG = "LatinIME";
|
||||||
|
@ -548,10 +554,10 @@ public class LatinIME extends InputMethodService
|
||||||
switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
|
switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
|
||||||
case EditorInfo.TYPE_CLASS_NUMBER:
|
case EditorInfo.TYPE_CLASS_NUMBER:
|
||||||
case EditorInfo.TYPE_CLASS_DATETIME:
|
case EditorInfo.TYPE_CLASS_DATETIME:
|
||||||
mode = KeyboardSwitcher.MODE_NUMBER;
|
mode = KeyboardId.MODE_NUMBER;
|
||||||
break;
|
break;
|
||||||
case EditorInfo.TYPE_CLASS_PHONE:
|
case EditorInfo.TYPE_CLASS_PHONE:
|
||||||
mode = KeyboardSwitcher.MODE_PHONE;
|
mode = KeyboardId.MODE_PHONE;
|
||||||
break;
|
break;
|
||||||
case EditorInfo.TYPE_CLASS_TEXT:
|
case EditorInfo.TYPE_CLASS_TEXT:
|
||||||
//startPrediction();
|
//startPrediction();
|
||||||
|
@ -568,24 +574,24 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
if (isEmailVariation(variation)) {
|
if (isEmailVariation(variation)) {
|
||||||
mPredictionOn = false;
|
mPredictionOn = false;
|
||||||
mode = KeyboardSwitcher.MODE_EMAIL;
|
mode = KeyboardId.MODE_EMAIL;
|
||||||
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
|
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
|
||||||
mPredictionOn = false;
|
mPredictionOn = false;
|
||||||
mode = KeyboardSwitcher.MODE_URL;
|
mode = KeyboardId.MODE_URL;
|
||||||
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
|
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
|
||||||
mode = KeyboardSwitcher.MODE_IM;
|
mode = KeyboardId.MODE_IM;
|
||||||
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
|
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) {
|
||||||
mPredictionOn = false;
|
mPredictionOn = false;
|
||||||
mode = KeyboardSwitcher.MODE_TEXT;
|
mode = KeyboardId.MODE_TEXT;
|
||||||
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
|
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) {
|
||||||
mode = KeyboardSwitcher.MODE_WEB;
|
mode = KeyboardId.MODE_WEB;
|
||||||
// If it's a browser edit field and auto correct is not ON explicitly, then
|
// If it's a browser edit field and auto correct is not ON explicitly, then
|
||||||
// disable auto correction, but keep suggestions on.
|
// disable auto correction, but keep suggestions on.
|
||||||
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
|
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
|
||||||
mInputTypeNoAutoCorrect = true;
|
mInputTypeNoAutoCorrect = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mode = KeyboardSwitcher.MODE_TEXT;
|
mode = KeyboardId.MODE_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If NO_SUGGESTIONS is set, don't do prediction.
|
// If NO_SUGGESTIONS is set, don't do prediction.
|
||||||
|
@ -604,7 +610,7 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mode = KeyboardSwitcher.MODE_TEXT;
|
mode = KeyboardId.MODE_TEXT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
inputView.closing();
|
inputView.closing();
|
||||||
|
@ -675,7 +681,7 @@ public class LatinIME extends InputMethodService
|
||||||
|
|
||||||
mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging);
|
mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging);
|
||||||
|
|
||||||
BaseKeyboardView inputView = mKeyboardSwitcher.getInputView();
|
KeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||||
if (inputView != null)
|
if (inputView != null)
|
||||||
inputView.closing();
|
inputView.closing();
|
||||||
if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
|
if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
|
||||||
|
@ -685,7 +691,7 @@ public class LatinIME extends InputMethodService
|
||||||
@Override
|
@Override
|
||||||
public void onFinishInputView(boolean finishingInput) {
|
public void onFinishInputView(boolean finishingInput) {
|
||||||
super.onFinishInputView(finishingInput);
|
super.onFinishInputView(finishingInput);
|
||||||
BaseKeyboardView inputView = mKeyboardSwitcher.getInputView();
|
KeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||||
if (inputView != null)
|
if (inputView != null)
|
||||||
inputView.setForeground(false);
|
inputView.setForeground(false);
|
||||||
// Remove pending messages related to update suggestions
|
// Remove pending messages related to update suggestions
|
||||||
|
@ -1073,51 +1079,52 @@ public class LatinIME extends InputMethodService
|
||||||
|
|
||||||
// Implementation of KeyboardViewListener
|
// Implementation of KeyboardViewListener
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
||||||
long when = SystemClock.uptimeMillis();
|
long when = SystemClock.uptimeMillis();
|
||||||
if (primaryCode != BaseKeyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
|
if (primaryCode != Keyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
|
||||||
mDeleteCount = 0;
|
mDeleteCount = 0;
|
||||||
}
|
}
|
||||||
mLastKeyTime = when;
|
mLastKeyTime = when;
|
||||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||||
switch (primaryCode) {
|
switch (primaryCode) {
|
||||||
case BaseKeyboard.KEYCODE_DELETE:
|
case Keyboard.KEYCODE_DELETE:
|
||||||
handleBackspace();
|
handleBackspace();
|
||||||
mDeleteCount++;
|
mDeleteCount++;
|
||||||
LatinImeLogger.logOnDelete();
|
LatinImeLogger.logOnDelete();
|
||||||
break;
|
break;
|
||||||
case BaseKeyboard.KEYCODE_SHIFT:
|
case Keyboard.KEYCODE_SHIFT:
|
||||||
// Shift key is handled in onPress() when device has distinct multi-touch panel.
|
// Shift key is handled in onPress() when device has distinct multi-touch panel.
|
||||||
if (!distinctMultiTouch)
|
if (!distinctMultiTouch)
|
||||||
switcher.toggleShift();
|
switcher.toggleShift();
|
||||||
break;
|
break;
|
||||||
case BaseKeyboard.KEYCODE_MODE_CHANGE:
|
case Keyboard.KEYCODE_MODE_CHANGE:
|
||||||
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
|
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
|
||||||
if (!distinctMultiTouch)
|
if (!distinctMultiTouch)
|
||||||
switcher.changeKeyboardMode();
|
switcher.changeKeyboardMode();
|
||||||
break;
|
break;
|
||||||
case BaseKeyboard.KEYCODE_CANCEL:
|
case Keyboard.KEYCODE_CANCEL:
|
||||||
if (!isShowingOptionDialog()) {
|
if (!isShowingOptionDialog()) {
|
||||||
handleClose();
|
handleClose();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LatinKeyboardView.KEYCODE_OPTIONS:
|
case LatinKeyboard.KEYCODE_OPTIONS:
|
||||||
onOptionKeyPressed();
|
onOptionKeyPressed();
|
||||||
break;
|
break;
|
||||||
case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS:
|
case LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS:
|
||||||
onOptionKeyLongPressed();
|
onOptionKeyLongPressed();
|
||||||
break;
|
break;
|
||||||
case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
|
case LatinKeyboard.KEYCODE_NEXT_LANGUAGE:
|
||||||
toggleLanguage(false, true);
|
toggleLanguage(false, true);
|
||||||
break;
|
break;
|
||||||
case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
|
case LatinKeyboard.KEYCODE_PREV_LANGUAGE:
|
||||||
toggleLanguage(false, false);
|
toggleLanguage(false, false);
|
||||||
break;
|
break;
|
||||||
case LatinKeyboardView.KEYCODE_CAPSLOCK:
|
case LatinKeyboard.KEYCODE_CAPSLOCK:
|
||||||
switcher.toggleCapsLock();
|
switcher.toggleCapsLock();
|
||||||
break;
|
break;
|
||||||
case LatinKeyboardView.KEYCODE_VOICE: /* was a button press, was not a swipe */
|
case LatinKeyboard.KEYCODE_VOICE: /* was a button press, was not a swipe */
|
||||||
mVoiceConnector.startListening(false,
|
mVoiceConnector.startListening(false,
|
||||||
mKeyboardSwitcher.getInputView().getWindowToken(), mConfigurationChanging);
|
mKeyboardSwitcher.getInputView().getWindowToken(), mConfigurationChanging);
|
||||||
break;
|
break;
|
||||||
|
@ -1143,6 +1150,7 @@ public class LatinIME extends InputMethodService
|
||||||
mEnteredText = null;
|
mEnteredText = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onText(CharSequence text) {
|
public void onText(CharSequence text) {
|
||||||
mVoiceConnector.commitVoiceInput();
|
mVoiceConnector.commitVoiceInput();
|
||||||
InputConnection ic = getCurrentInputConnection();
|
InputConnection ic = getCurrentInputConnection();
|
||||||
|
@ -1161,6 +1169,7 @@ public class LatinIME extends InputMethodService
|
||||||
mEnteredText = text;
|
mEnteredText = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onCancel() {
|
public void onCancel() {
|
||||||
// User released a finger outside any key
|
// User released a finger outside any key
|
||||||
}
|
}
|
||||||
|
@ -1420,24 +1429,26 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
|
|
||||||
public void switchToKeyboardView() {
|
public void switchToKeyboardView() {
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
if (DEBUG) {
|
public void run() {
|
||||||
Log.d(TAG, "Switch to keyboard view.");
|
if (DEBUG) {
|
||||||
}
|
Log.d(TAG, "Switch to keyboard view.");
|
||||||
View v = mKeyboardSwitcher.getInputView();
|
}
|
||||||
if (v != null) {
|
View v = mKeyboardSwitcher.getInputView();
|
||||||
// Confirms that the keyboard view doesn't have parent view.
|
if (v != null) {
|
||||||
ViewParent p = v.getParent();
|
// Confirms that the keyboard view doesn't have parent view.
|
||||||
if (p != null && p instanceof ViewGroup) {
|
ViewParent p = v.getParent();
|
||||||
((ViewGroup)p).removeView(v);
|
if (p != null && p instanceof ViewGroup) {
|
||||||
}
|
((ViewGroup) p).removeView(v);
|
||||||
setInputView(v);
|
}
|
||||||
}
|
setInputView(v);
|
||||||
setCandidatesViewShown(isCandidateStripVisible());
|
}
|
||||||
updateInputViewShown();
|
setCandidatesViewShown(isCandidateStripVisible());
|
||||||
mHandler.postUpdateSuggestions();
|
updateInputViewShown();
|
||||||
}});
|
mHandler.postUpdateSuggestions();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearSuggestions() {
|
public void clearSuggestions() {
|
||||||
|
@ -1586,8 +1597,8 @@ public class LatinIME extends InputMethodService
|
||||||
LatinImeLogger.logOnManualSuggestion(
|
LatinImeLogger.logOnManualSuggestion(
|
||||||
"", suggestion.toString(), index, suggestions);
|
"", suggestion.toString(), index, suggestions);
|
||||||
final char primaryCode = suggestion.charAt(0);
|
final char primaryCode = suggestion.charAt(0);
|
||||||
onKey(primaryCode, new int[]{primaryCode}, BaseKeyboardView.NOT_A_TOUCH_COORDINATE,
|
onKey(primaryCode, new int[]{primaryCode}, KeyboardView.NOT_A_TOUCH_COORDINATE,
|
||||||
BaseKeyboardView.NOT_A_TOUCH_COORDINATE);
|
KeyboardView.NOT_A_TOUCH_COORDINATE);
|
||||||
if (ic != null) {
|
if (ic != null) {
|
||||||
ic.endBatchEdit();
|
ic.endBatchEdit();
|
||||||
}
|
}
|
||||||
|
@ -1877,6 +1888,7 @@ public class LatinIME extends InputMethodService
|
||||||
switcher.updateShiftState();
|
switcher.updateShiftState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||||
String key) {
|
String key) {
|
||||||
mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key);
|
mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key);
|
||||||
|
@ -1888,6 +1900,7 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void swipeRight() {
|
public void swipeRight() {
|
||||||
if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
|
if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
|
||||||
CharSequence text = ((android.text.ClipboardManager)getSystemService(
|
CharSequence text = ((android.text.ClipboardManager)getSystemService(
|
||||||
|
@ -1898,38 +1911,43 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void swipeLeft() {
|
public void swipeLeft() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void swipeDown() {
|
public void swipeDown() {
|
||||||
handleClose();
|
handleClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void swipeUp() {
|
public void swipeUp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onPress(int primaryCode) {
|
public void onPress(int primaryCode) {
|
||||||
vibrate();
|
vibrate();
|
||||||
playKeyClick(primaryCode);
|
playKeyClick(primaryCode);
|
||||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||||
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
|
if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||||
switcher.onPressShift();
|
switcher.onPressShift();
|
||||||
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
|
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||||
switcher.onPressSymbol();
|
switcher.onPressSymbol();
|
||||||
} else {
|
} else {
|
||||||
switcher.onOtherKeyPressed();
|
switcher.onOtherKeyPressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onRelease(int primaryCode) {
|
public void onRelease(int primaryCode) {
|
||||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||||
// Reset any drag flags in the keyboard
|
// Reset any drag flags in the keyboard
|
||||||
switcher.keyReleased();
|
switcher.keyReleased();
|
||||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||||
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
|
if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||||
switcher.onReleaseShift();
|
switcher.onReleaseShift();
|
||||||
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
|
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||||
switcher.onReleaseSymbol();
|
switcher.onReleaseSymbol();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1966,7 +1984,7 @@ public class LatinIME extends InputMethodService
|
||||||
// FIXME: These should be triggered after auto-repeat logic
|
// FIXME: These should be triggered after auto-repeat logic
|
||||||
int sound = AudioManager.FX_KEYPRESS_STANDARD;
|
int sound = AudioManager.FX_KEYPRESS_STANDARD;
|
||||||
switch (primaryCode) {
|
switch (primaryCode) {
|
||||||
case BaseKeyboard.KEYCODE_DELETE:
|
case Keyboard.KEYCODE_DELETE:
|
||||||
sound = AudioManager.FX_KEYPRESS_DELETE;
|
sound = AudioManager.FX_KEYPRESS_DELETE;
|
||||||
break;
|
break;
|
||||||
case KEYCODE_ENTER:
|
case KEYCODE_ENTER:
|
||||||
|
@ -2006,6 +2024,7 @@ public class LatinIME extends InputMethodService
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tutorial.TutorialListener
|
// Tutorial.TutorialListener
|
||||||
|
@Override
|
||||||
public void onTutorialDone() {
|
public void onTutorialDone() {
|
||||||
sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
|
sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
|
||||||
mTutorial = null;
|
mTutorial = null;
|
||||||
|
@ -2171,6 +2190,7 @@ public class LatinIME extends InputMethodService
|
||||||
itemInputMethod, itemSettings},
|
itemInputMethod, itemSettings},
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onClick(DialogInterface di, int position) {
|
public void onClick(DialogInterface di, int position) {
|
||||||
di.dismiss();
|
di.dismiss();
|
||||||
switch (position) {
|
switch (position) {
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class LatinIMEDebugSettings extends PreferenceActivity
|
||||||
updateDebugMode();
|
updateDebugMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||||
if (key.equals(DEBUG_MODE_KEY)) {
|
if (key.equals(DEBUG_MODE_KEY)) {
|
||||||
if (mDebugMode != null) {
|
if (mDebugMode != null) {
|
||||||
|
|
|
@ -137,6 +137,7 @@ public class LatinIMESettings extends PreferenceActivity
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||||
(new BackupManager(this)).dataChanged();
|
(new BackupManager(this)).dataChanged();
|
||||||
// If turning on voice input, show dialog
|
// If turning on voice input, show dialog
|
||||||
|
@ -181,6 +182,7 @@ public class LatinIMESettings extends PreferenceActivity
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case VOICE_INPUT_CONFIRM_DIALOG:
|
case VOICE_INPUT_CONFIRM_DIALOG:
|
||||||
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
|
if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
|
||||||
mVoicePreference.setValue(mVoiceModeOff);
|
mVoicePreference.setValue(mVoiceModeOff);
|
||||||
|
@ -226,6 +228,7 @@ public class LatinIMESettings extends PreferenceActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onDismiss(DialogInterface dialog) {
|
public void onDismiss(DialogInterface dialog) {
|
||||||
mLogger.settingsWarningDialogDismissed();
|
mLogger.settingsWarningDialogDismissed();
|
||||||
if (!mOkClicked) {
|
if (!mOkClicked) {
|
||||||
|
|
|
@ -310,6 +310,7 @@ public class LatinIMEUtil {
|
||||||
|
|
||||||
public void write(final String log) {
|
public void write(final String log) {
|
||||||
mLoggingHandler.post(new Runnable() {
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
createLogFileIfNotExist();
|
createLogFileIfNotExist();
|
||||||
final long currentTime = System.currentTimeMillis();
|
final long currentTime = System.currentTimeMillis();
|
||||||
|
@ -327,6 +328,7 @@ public class LatinIMEUtil {
|
||||||
|
|
||||||
public void printAll() {
|
public void printAll() {
|
||||||
mLoggingHandler.post(new Runnable() {
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mWriter.flush();
|
mWriter.flush();
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
@ -355,6 +357,7 @@ public class LatinIMEUtil {
|
||||||
|
|
||||||
public void clearAll() {
|
public void clearAll() {
|
||||||
mLoggingHandler.post(new Runnable() {
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mFile != null && mFile.exists()) {
|
if (mFile != null && mFile.exists()) {
|
||||||
if (LatinImeLogger.sDBG) {
|
if (LatinImeLogger.sDBG) {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.latin.Dictionary.DataType;
|
import com.android.inputmethod.latin.Dictionary.DataType;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -27,6 +28,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
|
|
||||||
public static boolean sDBG = false;
|
public static boolean sDBG = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +69,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static void onAddSuggestedWord(String word, int typeId, DataType dataType) {
|
public static void onAddSuggestedWord(String word, int typeId, DataType dataType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onSetKeyboard(BaseKeyboard kb) {
|
public static void onSetKeyboard(Keyboard kb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onPrintAllUsabilityStudtyLogs() {
|
public static void onPrintAllUsabilityStudtyLogs() {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboard;
|
||||||
import com.android.inputmethod.voice.SettingsUtil;
|
import com.android.inputmethod.voice.SettingsUtil;
|
||||||
import com.android.inputmethod.voice.VoiceIMEConnector;
|
import com.android.inputmethod.voice.VoiceIMEConnector;
|
||||||
import com.android.inputmethod.voice.VoiceInput;
|
import com.android.inputmethod.voice.VoiceInput;
|
||||||
|
@ -197,7 +198,7 @@ public class SubtypeSwitcher {
|
||||||
|| VoiceIMEConnector.getInstance().needsToShowWarningDialog()) {
|
|| VoiceIMEConnector.getInstance().needsToShowWarningDialog()) {
|
||||||
if (mVoiceInput != null) {
|
if (mVoiceInput != null) {
|
||||||
// TODO: Call proper function to trigger VoiceIME
|
// TODO: Call proper function to trigger VoiceIME
|
||||||
mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
|
mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -350,7 +351,7 @@ public class SubtypeSwitcher {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Log.d(TAG, "Set and call voice input.");
|
Log.d(TAG, "Set and call voice input.");
|
||||||
}
|
}
|
||||||
mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
|
mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,6 +423,7 @@ public class Suggest implements Dictionary.WordCallback {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean addWord(final char[] word, final int offset, final int length, int freq,
|
public boolean addWord(final char[] word, final int offset, final int length, int freq,
|
||||||
final int dicTypeId, final Dictionary.DataType dataType) {
|
final int dicTypeId, final Dictionary.DataType dataType) {
|
||||||
Dictionary.DataType dataTypeForLog = dataType;
|
Dictionary.DataType dataTypeForLog = dataType;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
import com.android.inputmethod.keyboard.Key;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboardView;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
@ -133,6 +135,7 @@ public class Tutorial implements OnTouchListener {
|
||||||
if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight();
|
if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight();
|
||||||
if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
|
if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
|
||||||
textView.setOnTouchListener(new View.OnTouchListener() {
|
textView.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
@Override
|
||||||
public boolean onTouch(View view, MotionEvent me) {
|
public boolean onTouch(View view, MotionEvent me) {
|
||||||
Tutorial.this.next();
|
Tutorial.this.next();
|
||||||
return true;
|
return true;
|
||||||
|
@ -237,6 +240,7 @@ public class Tutorial implements OnTouchListener {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -97,6 +97,7 @@ public class UserDictionary extends ExpandableDictionary {
|
||||||
|
|
||||||
final ContentResolver contentResolver = getContext().getContentResolver();
|
final ContentResolver contentResolver = getContext().getContentResolver();
|
||||||
new Thread("addWord") {
|
new Thread("addWord") {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
contentResolver.insert(Words.CONTENT_URI, values);
|
contentResolver.insert(Words.CONTENT_URI, values);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ public class FieldContext {
|
||||||
bundle.putInt(IME_OPTIONS, info.imeOptions);
|
bundle.putInt(IME_OPTIONS, info.imeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("static-access")
|
||||||
private static void addInputConnectionToBundle(
|
private static void addInputConnectionToBundle(
|
||||||
InputConnection conn, Bundle bundle) {
|
InputConnection conn, Bundle bundle) {
|
||||||
if (conn == null) {
|
if (conn == null) {
|
||||||
|
@ -96,6 +97,7 @@ public class FieldContext {
|
||||||
return mFieldInfo;
|
return mFieldInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return mFieldInfo.toString();
|
return mFieldInfo.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ import java.util.List;
|
||||||
* plays beeps, shows errors, etc.
|
* plays beeps, shows errors, etc.
|
||||||
*/
|
*/
|
||||||
public class RecognitionView {
|
public class RecognitionView {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private static final String TAG = "RecognitionView";
|
private static final String TAG = "RecognitionView";
|
||||||
|
|
||||||
private Handler mUiHandler; // Reference to UI thread
|
private Handler mUiHandler; // Reference to UI thread
|
||||||
|
@ -78,6 +79,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
/** Updates the microphone icon to show user their volume.*/
|
/** Updates the microphone icon to show user their volume.*/
|
||||||
private Runnable mUpdateVolumeRunnable = new Runnable() {
|
private Runnable mUpdateVolumeRunnable = new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (mState != State.LISTENING) {
|
if (mState != State.LISTENING) {
|
||||||
return;
|
return;
|
||||||
|
@ -141,6 +143,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
public void restoreState() {
|
public void restoreState() {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// Restart the spinner
|
// Restart the spinner
|
||||||
if (mState == State.WORKING) {
|
if (mState == State.WORKING) {
|
||||||
|
@ -153,6 +156,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
public void showInitializing() {
|
public void showInitializing() {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
prepareDialog(false, mContext.getText(R.string.voice_initializing), mInitializing,
|
prepareDialog(false, mContext.getText(R.string.voice_initializing), mInitializing,
|
||||||
mContext.getText(R.string.cancel));
|
mContext.getText(R.string.cancel));
|
||||||
|
@ -162,6 +166,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
public void showListening() {
|
public void showListening() {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.LISTENING;
|
mState = State.LISTENING;
|
||||||
prepareDialog(false, mContext.getText(R.string.voice_listening), mSpeakNow.get(0),
|
prepareDialog(false, mContext.getText(R.string.voice_listening), mSpeakNow.get(0),
|
||||||
|
@ -177,6 +182,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
public void showError(final String message) {
|
public void showError(final String message) {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.READY;
|
mState = State.READY;
|
||||||
prepareDialog(false, message, mError, mContext.getText(R.string.ok));
|
prepareDialog(false, message, mError, mContext.getText(R.string.ok));
|
||||||
|
@ -190,6 +196,7 @@ public class RecognitionView {
|
||||||
final int speechEndPosition) {
|
final int speechEndPosition) {
|
||||||
|
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.WORKING;
|
mState = State.WORKING;
|
||||||
prepareDialog(true, mContext.getText(R.string.voice_working), null, mContext
|
prepareDialog(true, mContext.getText(R.string.voice_working), null, mContext
|
||||||
|
@ -309,6 +316,7 @@ public class RecognitionView {
|
||||||
|
|
||||||
public void finish() {
|
public void finish() {
|
||||||
mUiHandler.post(new Runnable() {
|
mUiHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mState = State.READY;
|
mState = State.READY;
|
||||||
exitWorking();
|
exitWorking();
|
||||||
|
|
|
@ -39,7 +39,6 @@ import android.text.Selection;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.text.method.MovementMethod;
|
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -120,6 +119,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
if (VOICE_INSTALLED) {
|
if (VOICE_INSTALLED) {
|
||||||
mVoiceInput = new VoiceInput(context, this);
|
mVoiceInput = new VoiceInput(context, this);
|
||||||
mHints = new Hints(context, prefs, new Hints.Display() {
|
mHints = new Hints(context, prefs, new Hints.Display() {
|
||||||
|
@Override
|
||||||
public void showHint(int viewResource) {
|
public void showHint(int viewResource) {
|
||||||
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
|
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
|
||||||
Context.LAYOUT_INFLATER_SERVICE);
|
Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
@ -519,6 +519,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
||||||
public void switchToRecognitionStatusView(final boolean configurationChanging) {
|
public void switchToRecognitionStatusView(final boolean configurationChanging) {
|
||||||
final boolean configChanged = configurationChanging;
|
final boolean configChanged = configurationChanging;
|
||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mContext.setCandidatesViewShown(false);
|
mContext.setCandidatesViewShown(false);
|
||||||
mRecognizing = true;
|
mRecognizing = true;
|
||||||
|
|
|
@ -86,6 +86,7 @@ public class VoiceInput implements OnClickListener {
|
||||||
private static final String ALTERNATES_BUNDLE = "alternates_bundle";
|
private static final String ALTERNATES_BUNDLE = "alternates_bundle";
|
||||||
|
|
||||||
// This is copied from the VoiceSearch app.
|
// This is copied from the VoiceSearch app.
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private static final class AlternatesBundleKeys {
|
private static final class AlternatesBundleKeys {
|
||||||
public static final String ALTERNATES = "alternates";
|
public static final String ALTERNATES = "alternates";
|
||||||
public static final String CONFIDENCE = "confidence";
|
public static final String CONFIDENCE = "confidence";
|
||||||
|
@ -405,6 +406,7 @@ public class VoiceInput implements OnClickListener {
|
||||||
/**
|
/**
|
||||||
* Handle the cancel button.
|
* Handle the cancel button.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
switch(view.getId()) {
|
switch(view.getId()) {
|
||||||
case R.id.button:
|
case R.id.button:
|
||||||
|
@ -556,36 +558,43 @@ public class VoiceInput implements OnClickListener {
|
||||||
int mSpeechStart;
|
int mSpeechStart;
|
||||||
private boolean mEndpointed = false;
|
private boolean mEndpointed = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onReadyForSpeech(Bundle noiseParams) {
|
public void onReadyForSpeech(Bundle noiseParams) {
|
||||||
mRecognitionView.showListening();
|
mRecognitionView.showListening();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onBeginningOfSpeech() {
|
public void onBeginningOfSpeech() {
|
||||||
mEndpointed = false;
|
mEndpointed = false;
|
||||||
mSpeechStart = mWaveBuffer.size();
|
mSpeechStart = mWaveBuffer.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onRmsChanged(float rmsdB) {
|
public void onRmsChanged(float rmsdB) {
|
||||||
mRecognitionView.updateVoiceMeter(rmsdB);
|
mRecognitionView.updateVoiceMeter(rmsdB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onBufferReceived(byte[] buf) {
|
public void onBufferReceived(byte[] buf) {
|
||||||
try {
|
try {
|
||||||
mWaveBuffer.write(buf);
|
mWaveBuffer.write(buf);
|
||||||
} catch (IOException e) {}
|
} catch (IOException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onEndOfSpeech() {
|
public void onEndOfSpeech() {
|
||||||
mEndpointed = true;
|
mEndpointed = true;
|
||||||
mState = WORKING;
|
mState = WORKING;
|
||||||
mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
|
mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onError(int errorType) {
|
public void onError(int errorType) {
|
||||||
mState = ERROR;
|
mState = ERROR;
|
||||||
VoiceInput.this.onError(errorType, mEndpointed);
|
VoiceInput.this.onError(errorType, mEndpointed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onResults(Bundle resultsBundle) {
|
public void onResults(Bundle resultsBundle) {
|
||||||
List<String> results = resultsBundle
|
List<String> results = resultsBundle
|
||||||
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
|
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
|
||||||
|
@ -638,10 +647,12 @@ public class VoiceInput implements OnClickListener {
|
||||||
mRecognitionView.finish();
|
mRecognitionView.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onPartialResults(final Bundle partialResults) {
|
public void onPartialResults(final Bundle partialResults) {
|
||||||
// currently - do nothing
|
// currently - do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onEvent(int eventType, Bundle params) {
|
public void onEvent(int eventType, Bundle params) {
|
||||||
// do nothing - reserved for events that might be added in the future
|
// do nothing - reserved for events that might be added in the future
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import android.content.Intent;
|
||||||
* on on the VoiceSearch side.
|
* on on the VoiceSearch side.
|
||||||
*/
|
*/
|
||||||
public class VoiceInputLogger {
|
public class VoiceInputLogger {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private static final String TAG = VoiceInputLogger.class.getSimpleName();
|
private static final String TAG = VoiceInputLogger.class.getSimpleName();
|
||||||
|
|
||||||
private static VoiceInputLogger sVoiceInputLogger;
|
private static VoiceInputLogger sVoiceInputLogger;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin;
|
package com.android.inputmethod.latin;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.SwipeTracker.EventRingBuffer;
|
import com.android.inputmethod.keyboard.SwipeTracker.EventRingBuffer;
|
||||||
|
|
||||||
import android.test.AndroidTestCase;
|
import android.test.AndroidTestCase;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue