Merge "Move some inner static class to top class in new package"
commit
26dae3f4e8
|
@ -26,9 +26,9 @@
|
|||
android:paddingLeft="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"
|
||||
android:id="@+id/BaseKeyboardView"
|
||||
android:id="@+id/KeyboardView"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_width="match_parent"
|
||||
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:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||
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: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:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||
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:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||
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:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||
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:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
|
||||
android:id="@+id/LatinkeyboardBaseView"
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
android:orientation="horizontal"
|
||||
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"
|
||||
android:id="@+id/BaseKeyboardView"
|
||||
android:id="@+id/KeyboardView"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
android:paddingLeft="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"
|
||||
android:id="@+id/BaseKeyboardView"
|
||||
android:id="@+id/KeyboardView"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -26,9 +26,9 @@
|
|||
android:paddingLeft="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"
|
||||
android:id="@+id/BaseKeyboardView"
|
||||
android:id="@+id/KeyboardView"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<resources>
|
||||
|
||||
<declare-styleable name="BaseKeyboardView">
|
||||
<declare-styleable name="KeyboardView">
|
||||
<!-- Default KeyboardView style. -->
|
||||
<attr name="keyboardViewStyle" format="reference" />
|
||||
|
||||
|
@ -68,14 +68,14 @@
|
|||
</attr>
|
||||
|
||||
<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="black" value="1" />
|
||||
</attr>
|
||||
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BaseKeyboard">
|
||||
<declare-styleable name="Keyboard">
|
||||
<!-- Default width of a key, in pixels or percentage of display width. -->
|
||||
<attr name="keyWidth" format="dimension|fraction" />
|
||||
<!-- Default height of a key, in pixels or percentage of display width. -->
|
||||
|
@ -86,7 +86,7 @@
|
|||
<attr name="verticalGap" format="dimension|fraction" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BaseKeyboard_Key">
|
||||
<declare-styleable name="Keyboard_Key">
|
||||
<!-- The unicode value or comma-separated values that this key outputs. -->
|
||||
<attr name="codes" format="integer|string" />
|
||||
<!-- The XML keyboard layout of any popup keyboard. -->
|
||||
|
@ -114,7 +114,7 @@
|
|||
<attr name="keyLabel" format="string" />
|
||||
<!-- The key label option -->
|
||||
<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="alignRight" value="2" />
|
||||
<flag name="alignBottom" value="8" />
|
||||
|
@ -135,7 +135,7 @@
|
|||
<attr name="shiftedIcon" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BaseKeyboard_Row">
|
||||
<declare-styleable name="Keyboard_Row">
|
||||
<!-- Row edge flags. -->
|
||||
<attr name="rowEdgeFlags">
|
||||
<!-- Row is anchored to the top of the keyboard. -->
|
||||
|
@ -145,12 +145,12 @@
|
|||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BaseKeyboard_Include">
|
||||
<declare-styleable name="Keyboard_Include">
|
||||
<attr name="keyboardLayout" format="reference" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BaseKeyboard_Case">
|
||||
<!-- This should be aligned with KeyboardSwitcher.MODE_* -->
|
||||
<declare-styleable name="Keyboard_Case">
|
||||
<!-- This should be aligned with KeyboardId.MODE_* -->
|
||||
<attr name="mode">
|
||||
<enum name="text" value="0" />
|
||||
<enum name="url" value="1" />
|
||||
|
@ -175,7 +175,7 @@
|
|||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BaseKeyboard_KeyStyle">
|
||||
<declare-styleable name="Keyboard_KeyStyle">
|
||||
<attr name="styleName" format="string" />
|
||||
<attr name="parentStyle" format="string" />
|
||||
</declare-styleable>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
-->
|
||||
|
||||
<resources>
|
||||
<style name="BaseKeyboardView">
|
||||
<style name="KeyboardView">
|
||||
<item name="android:background">@drawable/keyboard_background</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.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
abstract class KeyDetector {
|
||||
protected BaseKeyboard mKeyboard;
|
||||
public abstract class KeyDetector {
|
||||
public static final int NOT_A_KEY = -1;
|
||||
|
||||
protected Keyboard mKeyboard;
|
||||
|
||||
private Key[] mKeys;
|
||||
|
||||
|
@ -34,7 +34,7 @@ abstract class KeyDetector {
|
|||
|
||||
protected int mProximityThresholdSquare;
|
||||
|
||||
public Key[] setKeyboard(BaseKeyboard keyboard, float correctionX, float correctionY) {
|
||||
public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
|
||||
if (keyboard == null)
|
||||
throw new NullPointerException();
|
||||
mCorrectionX = (int)correctionX;
|
||||
|
@ -84,7 +84,7 @@ abstract class KeyDetector {
|
|||
*/
|
||||
public int[] newCodeArray() {
|
||||
int[] codes = new int[getMaxNearbyKeys()];
|
||||
Arrays.fill(codes, BaseKeyboardView.NOT_A_KEY);
|
||||
Arrays.fill(codes, NOT_A_KEY);
|
||||
return codes;
|
||||
}
|
||||
|
|
@ -14,9 +14,10 @@
|
|||
* 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.XmlResourceParser;
|
||||
|
@ -48,30 +49,37 @@ public class KeyStyles {
|
|||
private EmptyKeyStyle() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIntArray(TypedArray a, int index) {
|
||||
return parseIntArray(a, index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getDrawable(TypedArray a, int index) {
|
||||
return a.getDrawable(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getText(TypedArray a, int index) {
|
||||
return a.getText(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResourceId(TypedArray a, int index, int defaultValue) {
|
||||
return a.getResourceId(index, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(TypedArray a, int index, int defaultValue) {
|
||||
return a.getInt(index, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFlag(TypedArray a, int index, int defaultValue) {
|
||||
return a.getInt(index, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(TypedArray a, int index, boolean defaultValue) {
|
||||
return a.getBoolean(index, defaultValue);
|
||||
}
|
||||
|
@ -156,18 +164,18 @@ public class KeyStyles {
|
|||
|
||||
private void parseKeyStyleAttributes(TypedArray a) {
|
||||
// TODO: Currently not all Key attributes can be declared as style.
|
||||
readIntArray(a, R.styleable.BaseKeyboard_Key_codes);
|
||||
readText(a, R.styleable.BaseKeyboard_Key_keyLabel);
|
||||
readFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption);
|
||||
readText(a, R.styleable.BaseKeyboard_Key_keyOutputText);
|
||||
readDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon);
|
||||
readDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview);
|
||||
readDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon);
|
||||
readDrawable(a, R.styleable.BaseKeyboard_Key_shiftedIcon);
|
||||
readResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard);
|
||||
readBoolean(a, R.styleable.BaseKeyboard_Key_isModifier);
|
||||
readBoolean(a, R.styleable.BaseKeyboard_Key_isSticky);
|
||||
readBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable);
|
||||
readIntArray(a, R.styleable.Keyboard_Key_codes);
|
||||
readText(a, R.styleable.Keyboard_Key_keyLabel);
|
||||
readFlag(a, R.styleable.Keyboard_Key_keyLabelOption);
|
||||
readText(a, R.styleable.Keyboard_Key_keyOutputText);
|
||||
readDrawable(a, R.styleable.Keyboard_Key_keyIcon);
|
||||
readDrawable(a, R.styleable.Keyboard_Key_iconPreview);
|
||||
readDrawable(a, R.styleable.Keyboard_Key_keyHintIcon);
|
||||
readDrawable(a, R.styleable.Keyboard_Key_shiftedIcon);
|
||||
readResourceId(a, R.styleable.Keyboard_Key_popupKeyboard);
|
||||
readBoolean(a, R.styleable.Keyboard_Key_isModifier);
|
||||
readBoolean(a, R.styleable.Keyboard_Key_isSticky);
|
||||
readBoolean(a, R.styleable.Keyboard_Key_isRepeatable);
|
||||
}
|
||||
|
||||
private void readDrawable(TypedArray a, int index) {
|
||||
|
@ -211,14 +219,14 @@ public class KeyStyles {
|
|||
|
||||
public void parseKeyStyleAttributes(TypedArray a, TypedArray keyAttrs,
|
||||
XmlResourceParser parser) {
|
||||
String styleName = a.getString(R.styleable.BaseKeyboard_KeyStyle_styleName);
|
||||
String styleName = a.getString(R.styleable.Keyboard_KeyStyle_styleName);
|
||||
if (mStyles.containsKey(styleName))
|
||||
throw new ParseException("duplicate key style declared: " + styleName, parser);
|
||||
|
||||
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(
|
||||
R.styleable.BaseKeyboard_KeyStyle_parentStyle);
|
||||
R.styleable.Keyboard_KeyStyle_parentStyle);
|
||||
final DeclaredKeyStyle parent = mStyles.get(parentStyle);
|
||||
if (parent == null)
|
||||
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.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Row;
|
||||
import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
|
@ -36,7 +34,7 @@ import java.util.List;
|
|||
/**
|
||||
* 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:
|
||||
* <pre>
|
||||
* >!-- xml/keyboard.xml --<
|
||||
|
@ -102,8 +100,8 @@ import java.util.List;
|
|||
* </pre>
|
||||
*/
|
||||
|
||||
public class BaseKeyboardParser {
|
||||
private static final String TAG = "BaseKeyboardParser";
|
||||
public class KeyboardParser {
|
||||
private static final String TAG = "KeyboardParser";
|
||||
private static final boolean DEBUG_TAG = false;
|
||||
|
||||
// Keyboard XML Tags
|
||||
|
@ -118,7 +116,7 @@ public class BaseKeyboardParser {
|
|||
private static final String TAG_DEFAULT = "default";
|
||||
private static final String TAG_KEY_STYLE = "key-style";
|
||||
|
||||
private final BaseKeyboard mKeyboard;
|
||||
private final Keyboard mKeyboard;
|
||||
private final Resources mResources;
|
||||
|
||||
private int mCurrentX = 0;
|
||||
|
@ -128,7 +126,7 @@ public class BaseKeyboardParser {
|
|||
private Row mCurrentRow = null;
|
||||
private final KeyStyles mKeyStyles = new KeyStyles();
|
||||
|
||||
public BaseKeyboardParser(BaseKeyboard keyboard, Resources res) {
|
||||
public KeyboardParser(Keyboard keyboard, Resources res) {
|
||||
mKeyboard = keyboard;
|
||||
mResources = res;
|
||||
}
|
||||
|
@ -160,19 +158,19 @@ public class BaseKeyboardParser {
|
|||
}
|
||||
|
||||
private void parseKeyboardAttributes(XmlResourceParser parser) {
|
||||
final BaseKeyboard keyboard = mKeyboard;
|
||||
final Keyboard keyboard = mKeyboard;
|
||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboard);
|
||||
R.styleable.Keyboard);
|
||||
final int width = keyboard.getKeyboardWidth();
|
||||
final int height = keyboard.getKeyboardHeight();
|
||||
keyboard.setKeyWidth(getDimensionOrFraction(a,
|
||||
R.styleable.BaseKeyboard_keyWidth, width, width / 10));
|
||||
R.styleable.Keyboard_keyWidth, width, width / 10));
|
||||
keyboard.setKeyHeight(getDimensionOrFraction(a,
|
||||
R.styleable.BaseKeyboard_keyHeight, height, 50));
|
||||
R.styleable.Keyboard_keyHeight, height, 50));
|
||||
keyboard.setHorizontalGap(getDimensionOrFraction(a,
|
||||
R.styleable.BaseKeyboard_horizontalGap, width, 0));
|
||||
R.styleable.Keyboard_horizontalGap, width, 0));
|
||||
keyboard.setVerticalGap(getDimensionOrFraction(a,
|
||||
R.styleable.BaseKeyboard_verticalGap, height, 0));
|
||||
R.styleable.Keyboard_verticalGap, height, 0));
|
||||
a.recycle();
|
||||
if (DEBUG_TAG) Log.d(TAG, "id=" + keyboard.mId);
|
||||
}
|
||||
|
@ -266,7 +264,7 @@ public class BaseKeyboardParser {
|
|||
mKeyStyles);
|
||||
checkEndTag(TAG_KEY, parser);
|
||||
keys.add(key);
|
||||
if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT)
|
||||
if (key.codes[0] == Keyboard.KEYCODE_SHIFT)
|
||||
mKeyboard.getShiftKeys().add(key);
|
||||
endKey(key);
|
||||
}
|
||||
|
@ -278,8 +276,8 @@ public class BaseKeyboardParser {
|
|||
checkEndTag(TAG_SPACER, parser);
|
||||
} else {
|
||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboard);
|
||||
final int gap = getDimensionOrFraction(a, R.styleable.BaseKeyboard_horizontalGap,
|
||||
R.styleable.Keyboard);
|
||||
final int gap = getDimensionOrFraction(a, R.styleable.Keyboard_horizontalGap,
|
||||
mKeyboard.getKeyboardWidth(), 0);
|
||||
a.recycle();
|
||||
checkEndTag(TAG_SPACER, parser);
|
||||
|
@ -303,9 +301,9 @@ public class BaseKeyboardParser {
|
|||
checkEndTag(TAG_INCLUDE, parser);
|
||||
} else {
|
||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboard_Include);
|
||||
R.styleable.Keyboard_Include);
|
||||
final int keyboardLayout = a.getResourceId(
|
||||
R.styleable.BaseKeyboard_Include_keyboardLayout, 0);
|
||||
R.styleable.Keyboard_Include_keyboardLayout, 0);
|
||||
a.recycle();
|
||||
|
||||
checkEndTag(TAG_INCLUDE, parser);
|
||||
|
@ -395,25 +393,25 @@ public class BaseKeyboardParser {
|
|||
return true;
|
||||
|
||||
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboard_Case);
|
||||
R.styleable.Keyboard_Case);
|
||||
final TypedArray viewAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboardView);
|
||||
R.styleable.KeyboardView);
|
||||
try {
|
||||
final boolean modeMatched = matchInteger(a,
|
||||
R.styleable.BaseKeyboard_Case_mode, id.mMode);
|
||||
R.styleable.Keyboard_Case_mode, id.mMode);
|
||||
final boolean settingsKeyMatched = matchBoolean(a,
|
||||
R.styleable.BaseKeyboard_Case_hasSettingsKey, id.mHasSettingsKey);
|
||||
R.styleable.Keyboard_Case_hasSettingsKey, id.mHasSettingsKey);
|
||||
final boolean voiceEnabledMatched = matchBoolean(a,
|
||||
R.styleable.BaseKeyboard_Case_voiceKeyEnabled, id.mVoiceKeyEnabled);
|
||||
R.styleable.Keyboard_Case_voiceKeyEnabled, id.mVoiceKeyEnabled);
|
||||
final boolean voiceKeyMatched = matchBoolean(a,
|
||||
R.styleable.BaseKeyboard_Case_hasVoiceKey, id.mHasVoiceKey);
|
||||
R.styleable.Keyboard_Case_hasVoiceKey, id.mHasVoiceKey);
|
||||
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
|
||||
// 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.
|
||||
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
|
||||
&& voiceKeyMatched && colorSchemeMatched && imeOptionsMatched;
|
||||
|
||||
|
@ -421,15 +419,15 @@ public class BaseKeyboardParser {
|
|||
Log.d(TAG, String.format(
|
||||
"parseCaseCondition: %s%s%s%s%s%s%s",
|
||||
Boolean.toString(selected).toUpperCase(),
|
||||
debugInteger(a, R.styleable.BaseKeyboard_Case_mode, "mode"),
|
||||
debugBoolean(a, R.styleable.BaseKeyboard_Case_hasSettingsKey,
|
||||
debugInteger(a, R.styleable.Keyboard_Case_mode, "mode"),
|
||||
debugBoolean(a, R.styleable.Keyboard_Case_hasSettingsKey,
|
||||
"hasSettingsKey"),
|
||||
debugBoolean(a, R.styleable.BaseKeyboard_Case_voiceKeyEnabled,
|
||||
debugBoolean(a, R.styleable.Keyboard_Case_voiceKeyEnabled,
|
||||
"voiceKeyEnabled"),
|
||||
debugBoolean(a, R.styleable.BaseKeyboard_Case_hasVoiceKey, "hasVoiceKey"),
|
||||
debugInteger(viewAttr, R.styleable.BaseKeyboardView_colorScheme,
|
||||
debugBoolean(a, R.styleable.Keyboard_Case_hasVoiceKey, "hasVoiceKey"),
|
||||
debugInteger(viewAttr, R.styleable.KeyboardView_colorScheme,
|
||||
"colorScheme"),
|
||||
debugInteger(a, R.styleable.BaseKeyboard_Case_imeOptions, "imeOptions")));
|
||||
debugInteger(a, R.styleable.Keyboard_Case_imeOptions, "imeOptions")));
|
||||
}
|
||||
|
||||
return selected;
|
||||
|
@ -464,11 +462,11 @@ public class BaseKeyboardParser {
|
|||
private void parseKeyStyle(XmlResourceParser parser, List<Key> keys)
|
||||
throws XmlPullParserException, IOException {
|
||||
TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboard_KeyStyle);
|
||||
R.styleable.Keyboard_KeyStyle);
|
||||
TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||
R.styleable.BaseKeyboard_Key);
|
||||
R.styleable.Keyboard_Key);
|
||||
try {
|
||||
if (!a.hasValue(R.styleable.BaseKeyboard_KeyStyle_styleName))
|
||||
if (!a.hasValue(R.styleable.Keyboard_KeyStyle_styleName))
|
||||
throw new ParseException("<" + TAG_KEY_STYLE
|
||||
+ "/> needs styleName attribute", parser);
|
||||
if (keys != null)
|
|
@ -14,9 +14,11 @@
|
|||
* 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.pm.PackageManager;
|
||||
|
@ -49,27 +51,26 @@ import android.widget.TextView;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* A view that renders a virtual {@link LatinKeyboard}. It handles rendering of keys and
|
||||
* detecting key presses and touch movements.
|
||||
* A view that renders a virtual {@link Keyboard}. It handles rendering of keys and detecting key
|
||||
* presses and touch movements.
|
||||
*
|
||||
* 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#BaseKeyboardView_keyPreviewLayout
|
||||
* @attr ref R.styleable#BaseKeyboardView_keyPreviewOffset
|
||||
* @attr ref R.styleable#BaseKeyboardView_labelTextSize
|
||||
* @attr ref R.styleable#BaseKeyboardView_keyTextSize
|
||||
* @attr ref R.styleable#BaseKeyboardView_keyTextColor
|
||||
* @attr ref R.styleable#BaseKeyboardView_verticalCorrection
|
||||
* @attr ref R.styleable#BaseKeyboardView_popupLayout
|
||||
* @attr ref R.styleable#KeyboardView_keyBackground
|
||||
* @attr ref R.styleable#KeyboardView_keyPreviewLayout
|
||||
* @attr ref R.styleable#KeyboardView_keyPreviewOffset
|
||||
* @attr ref R.styleable#KeyboardView_labelTextSize
|
||||
* @attr ref R.styleable#KeyboardView_keyTextSize
|
||||
* @attr ref R.styleable#KeyboardView_keyTextColor
|
||||
* @attr ref R.styleable#KeyboardView_verticalCorrection
|
||||
* @attr ref R.styleable#KeyboardView_popupLayout
|
||||
*/
|
||||
public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
||||
private static final String TAG = "BaseKeyboardView";
|
||||
public class KeyboardView extends View implements PointerTracker.UIProxy {
|
||||
private static final String TAG = "KeyboardView";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG_SHOW_ALIGN = 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 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
|
||||
private final int mKeyRepeatInterval;
|
||||
|
||||
// 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 HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL = -1;
|
||||
|
||||
|
@ -187,7 +105,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private int mPopupLayout;
|
||||
|
||||
// Main keyboard
|
||||
private BaseKeyboard mKeyboard;
|
||||
private Keyboard mKeyboard;
|
||||
private Key[] mKeys;
|
||||
|
||||
// Key preview popup
|
||||
|
@ -196,7 +114,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private PopupWindow mPreviewPopup;
|
||||
private int mPreviewTextSizeLarge;
|
||||
private int[] mOffsetInWindow;
|
||||
private int mOldPreviewKeyIndex = NOT_A_KEY;
|
||||
private int mOldPreviewKeyIndex = KeyDetector.NOT_A_KEY;
|
||||
private boolean mShowPreview = true;
|
||||
private boolean mShowTouchPoints = true;
|
||||
private int mPopupPreviewOffsetX;
|
||||
|
@ -208,7 +126,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
|
||||
// Popup mini keyboard
|
||||
private PopupWindow mMiniKeyboardPopup;
|
||||
private BaseKeyboardView mMiniKeyboard;
|
||||
private KeyboardView mMiniKeyboard;
|
||||
private View mMiniKeyboardParent;
|
||||
private final WeakHashMap<Key, View> mMiniKeyboardCache = new WeakHashMap<Key, View>();
|
||||
private int mMiniKeyboardOriginX;
|
||||
|
@ -218,13 +136,13 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private final float mMiniKeyboardSlideAllowance;
|
||||
private int mMiniKeyboardTrackerId;
|
||||
|
||||
/** Listener for {@link OnKeyboardActionListener}. */
|
||||
private OnKeyboardActionListener mKeyboardActionListener;
|
||||
/** Listener for {@link KeyboardActionListener}. */
|
||||
private KeyboardActionListener mKeyboardActionListener;
|
||||
|
||||
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
|
||||
|
||||
// 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 int mOldPointerCount = 1;
|
||||
|
@ -370,63 +288,15 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
}
|
||||
};
|
||||
|
||||
static class PointerQueue {
|
||||
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) {
|
||||
public KeyboardView(Context context, AttributeSet attrs) {
|
||||
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);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.BaseKeyboardView, defStyle, R.style.BaseKeyboardView);
|
||||
attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
||||
LayoutInflater inflate =
|
||||
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
int previewLayout = 0;
|
||||
|
@ -438,53 +308,53 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
int attr = a.getIndex(i);
|
||||
|
||||
switch (attr) {
|
||||
case R.styleable.BaseKeyboardView_keyBackground:
|
||||
case R.styleable.KeyboardView_keyBackground:
|
||||
mKeyBackground = a.getDrawable(attr);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyHysteresisDistance:
|
||||
case R.styleable.KeyboardView_keyHysteresisDistance:
|
||||
mKeyHysteresisDistance = a.getDimensionPixelOffset(attr, 0);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_verticalCorrection:
|
||||
case R.styleable.KeyboardView_verticalCorrection:
|
||||
mVerticalCorrection = a.getDimensionPixelOffset(attr, 0);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyPreviewLayout:
|
||||
case R.styleable.KeyboardView_keyPreviewLayout:
|
||||
previewLayout = a.getResourceId(attr, 0);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyPreviewOffset:
|
||||
case R.styleable.KeyboardView_keyPreviewOffset:
|
||||
mPreviewOffset = a.getDimensionPixelOffset(attr, 0);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyPreviewHeight:
|
||||
case R.styleable.KeyboardView_keyPreviewHeight:
|
||||
mPreviewHeight = a.getDimensionPixelSize(attr, 80);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyLetterSize:
|
||||
case R.styleable.KeyboardView_keyLetterSize:
|
||||
mKeyLetterSize = a.getDimensionPixelSize(attr, 18);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyTextColor:
|
||||
case R.styleable.KeyboardView_keyTextColor:
|
||||
mKeyTextColor = a.getColor(attr, 0xFF000000);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyTextColorDisabled:
|
||||
case R.styleable.KeyboardView_keyTextColorDisabled:
|
||||
mKeyTextColorDisabled = a.getColor(attr, 0xFF000000);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_labelTextSize:
|
||||
case R.styleable.KeyboardView_labelTextSize:
|
||||
mLabelTextSize = a.getDimensionPixelSize(attr, 14);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_popupLayout:
|
||||
case R.styleable.KeyboardView_popupLayout:
|
||||
mPopupLayout = a.getResourceId(attr, 0);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_shadowColor:
|
||||
case R.styleable.KeyboardView_shadowColor:
|
||||
mShadowColor = a.getColor(attr, 0);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_shadowRadius:
|
||||
case R.styleable.KeyboardView_shadowRadius:
|
||||
mShadowRadius = a.getFloat(attr, 0f);
|
||||
break;
|
||||
// TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
|
||||
case R.styleable.BaseKeyboardView_backgroundDimAmount:
|
||||
case R.styleable.KeyboardView_backgroundDimAmount:
|
||||
mBackgroundDimAmount = a.getFloat(attr, 0.5f);
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_keyLetterStyle:
|
||||
case R.styleable.KeyboardView_keyLetterStyle:
|
||||
mKeyLetterStyle = Typeface.defaultFromStyle(a.getInt(attr, Typeface.NORMAL));
|
||||
break;
|
||||
case R.styleable.BaseKeyboardView_colorScheme:
|
||||
case R.styleable.KeyboardView_colorScheme:
|
||||
mColorScheme = a.getInt(attr, COLOR_SCHEME_WHITE);
|
||||
break;
|
||||
}
|
||||
|
@ -575,7 +445,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
|
||||
}
|
||||
|
||||
public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
|
||||
public void setOnKeyboardActionListener(KeyboardActionListener listener) {
|
||||
mKeyboardActionListener = listener;
|
||||
for (PointerTracker tracker : mPointerTrackers) {
|
||||
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
|
||||
*/
|
||||
protected OnKeyboardActionListener getOnKeyboardActionListener() {
|
||||
protected KeyboardActionListener getOnKeyboardActionListener() {
|
||||
return mKeyboardActionListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @see BaseKeyboard
|
||||
* @see Keyboard
|
||||
* @see #getKeyboard()
|
||||
* @param keyboard the keyboard to display in this view
|
||||
*/
|
||||
protected void setKeyboard(BaseKeyboard keyboard) {
|
||||
public void setKeyboard(Keyboard keyboard) {
|
||||
if (mKeyboard != null) {
|
||||
dismissKeyPreview();
|
||||
}
|
||||
|
@ -622,9 +492,9 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
/**
|
||||
* Returns the current keyboard being displayed by this view.
|
||||
* @return the currently attached keyboard
|
||||
* @see #setKeyboard(BaseKeyboard)
|
||||
* @see #setKeyboard(Keyboard)
|
||||
*/
|
||||
protected BaseKeyboard getKeyboard() {
|
||||
public Keyboard getKeyboard() {
|
||||
return mKeyboard;
|
||||
}
|
||||
|
||||
|
@ -632,6 +502,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
* Return whether the device has distinct multi-touch panel.
|
||||
* @return true if the device has distinct multi-touch panel.
|
||||
*/
|
||||
@Override
|
||||
public boolean hasDistinctMultitouch() {
|
||||
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
|
||||
* reported.
|
||||
* @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 keys
|
||||
*/
|
||||
private void computeProximityThreshold(BaseKeyboard keyboard, Key[] keys) {
|
||||
private void computeProximityThreshold(Keyboard keyboard, Key[] keys) {
|
||||
if (keyboard == null || keys == null || keys.length == 0) return;
|
||||
final HashMap<Integer, Integer> histogram = new HashMap<Integer, Integer>();
|
||||
int maxCount = 0;
|
||||
|
@ -750,6 +621,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
canvas.drawBitmap(mBuffer, 0, 0, null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void onBufferDraw() {
|
||||
if (mBuffer == null || mKeyboardChanged) {
|
||||
if (mBuffer == null || mKeyboardChanged &&
|
||||
|
@ -1020,22 +892,24 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private void dismissKeyPreview() {
|
||||
for (PointerTracker tracker : mPointerTrackers)
|
||||
tracker.releaseKey();
|
||||
showPreview(NOT_A_KEY, null);
|
||||
showPreview(KeyDetector.NOT_A_KEY, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPreview(int keyIndex, PointerTracker tracker) {
|
||||
int oldKeyIndex = mOldPreviewKeyIndex;
|
||||
mOldPreviewKeyIndex = keyIndex;
|
||||
// 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
|
||||
// should hide the preview of the previous key.
|
||||
@SuppressWarnings("unused")
|
||||
final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
|
||||
|| (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER
|
||||
&& SubtypeSwitcher.getInstance().needsToDisplayLanguage()
|
||||
&& (tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex)));
|
||||
// If key changed and preview is on or the key is space (language switch is enabled)
|
||||
if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview))) {
|
||||
if (keyIndex == NOT_A_KEY) {
|
||||
if (keyIndex == KeyDetector.NOT_A_KEY) {
|
||||
mHandler.cancelPopupPreview();
|
||||
mHandler.dismissPreview(mDelayAfterPreview);
|
||||
} 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
|
||||
* one key is changing it's content. Any changes that affect the position or size of the key
|
||||
* may not be honored.
|
||||
* @param key key in the attached {@link BaseKeyboard}.
|
||||
* @param key key in the attached {@link Keyboard}.
|
||||
* @see #invalidateAllKeys
|
||||
*/
|
||||
@Override
|
||||
public void invalidateKey(Key key) {
|
||||
if (key == null)
|
||||
return;
|
||||
|
@ -1183,7 +1058,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private void onLongPressShiftKey(PointerTracker tracker) {
|
||||
tracker.setAlreadyProcessed();
|
||||
mPointerQueue.remove(tracker);
|
||||
mKeyboardActionListener.onKey(LatinKeyboardView.KEYCODE_CAPSLOCK, null, 0, 0);
|
||||
mKeyboardActionListener.onKey(LatinKeyboard.KEYCODE_CAPSLOCK, null, 0, 0);
|
||||
}
|
||||
|
||||
private View inflateMiniKeyboardContainer(Key popupKey) {
|
||||
|
@ -1194,34 +1069,43 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
if (container == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
BaseKeyboardView miniKeyboard =
|
||||
(BaseKeyboardView)container.findViewById(R.id.BaseKeyboardView);
|
||||
miniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() {
|
||||
KeyboardView miniKeyboard =
|
||||
(KeyboardView)container.findViewById(R.id.KeyboardView);
|
||||
miniKeyboard.setOnKeyboardActionListener(new KeyboardActionListener() {
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
||||
mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y);
|
||||
dismissPopupKeyboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onText(CharSequence text) {
|
||||
mKeyboardActionListener.onText(text);
|
||||
dismissPopupKeyboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
dismissPopupKeyboard();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeLeft() {
|
||||
}
|
||||
@Override
|
||||
public void swipeRight() {
|
||||
}
|
||||
@Override
|
||||
public void swipeUp() {
|
||||
}
|
||||
@Override
|
||||
public void swipeDown() {
|
||||
}
|
||||
@Override
|
||||
public void onPress(int primaryCode) {
|
||||
mKeyboardActionListener.onPress(primaryCode);
|
||||
}
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {
|
||||
mKeyboardActionListener.onRelease(primaryCode);
|
||||
}
|
||||
|
@ -1231,12 +1115,12 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
// Remove gesture detector on mini-keyboard
|
||||
miniKeyboard.mGestureDetector = null;
|
||||
|
||||
BaseKeyboard keyboard;
|
||||
Keyboard keyboard;
|
||||
if (popupKey.popupCharacters != null) {
|
||||
keyboard = new BaseKeyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
|
||||
keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
|
||||
-1, getPaddingLeft() + getPaddingRight());
|
||||
} else {
|
||||
keyboard = new BaseKeyboard(getContext(), popupKeyboardId);
|
||||
keyboard = new Keyboard(getContext(), popupKeyboardId);
|
||||
}
|
||||
miniKeyboard.setKeyboard(keyboard);
|
||||
miniKeyboard.setPopupParent(this);
|
||||
|
@ -1256,8 +1140,8 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
// and bottom edge flags on.
|
||||
// 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.
|
||||
return (edgeFlags & BaseKeyboard.EDGE_TOP) != 0
|
||||
&& (edgeFlags & BaseKeyboard.EDGE_BOTTOM) != 0;
|
||||
return (edgeFlags & Keyboard.EDGE_TOP) != 0
|
||||
&& (edgeFlags & Keyboard.EDGE_BOTTOM) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1279,7 +1163,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
container = inflateMiniKeyboardContainer(popupKey);
|
||||
mMiniKeyboardCache.put(popupKey, container);
|
||||
}
|
||||
mMiniKeyboard = (BaseKeyboardView)container.findViewById(R.id.BaseKeyboardView);
|
||||
mMiniKeyboard = (KeyboardView)container.findViewById(R.id.KeyboardView);
|
||||
if (mWindowOffset == null) {
|
||||
mWindowOffset = new int[2];
|
||||
getLocationInWindow(mWindowOffset);
|
||||
|
@ -1325,7 +1209,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1];
|
||||
mMiniKeyboard.setPopupOffset(adjustedX, y);
|
||||
// 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
|
||||
? false : mKeyboard.isShiftedOrShiftLocked())) {
|
||||
mMiniKeyboard.invalidateAllKeys();
|
||||
|
@ -1376,7 +1260,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private PointerTracker getPointerTracker(final int id) {
|
||||
final ArrayList<PointerTracker> pointers = mPointerTrackers;
|
||||
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.
|
||||
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.
|
||||
*/
|
||||
|
||||
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.res.Resources;
|
||||
|
@ -22,28 +26,33 @@ import android.content.res.TypedArray;
|
|||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextPaint;
|
||||
import android.util.Log;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
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 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 Drawable mShiftLockPreviewIcon;
|
||||
|
@ -76,22 +85,22 @@ public class LatinKeyboard extends BaseKeyboard {
|
|||
// Minimum width of space key preview (proportional to keyboard width)
|
||||
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)
|
||||
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,
|
||||
// its short language name will be used instead.
|
||||
private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f;
|
||||
|
||||
private static int sSpacebarVerticalCorrection;
|
||||
|
||||
public LatinKeyboard(Context context, KeyboardSwitcher.KeyboardId id) {
|
||||
public LatinKeyboard(Context context, KeyboardId id) {
|
||||
super(context, id);
|
||||
final Resources res = context.getResources();
|
||||
mContext = context;
|
||||
mRes = res;
|
||||
if (id.mColorScheme == BaseKeyboardView.COLOR_SCHEME_BLACK) {
|
||||
if (id.mColorScheme == KeyboardView.COLOR_SCHEME_BLACK) {
|
||||
mSpaceBarTextShadowColor = res.getColor(
|
||||
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(
|
||||
R.color.latinkeyboard_bar_language_shadow_white);
|
||||
}
|
||||
|
@ -181,7 +190,7 @@ public class LatinKeyboard extends BaseKeyboard {
|
|||
return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
|
||||
}
|
||||
|
||||
/* package */ LatinKeyboardShiftState getKeyboardShiftState() {
|
||||
public LatinKeyboardShiftState getKeyboardShiftState() {
|
||||
return mShiftState;
|
||||
}
|
||||
|
||||
|
@ -190,11 +199,11 @@ public class LatinKeyboard extends BaseKeyboard {
|
|||
}
|
||||
|
||||
public boolean isPhoneKeyboard() {
|
||||
return mId.mMode == KeyboardSwitcher.MODE_PHONE;
|
||||
return mId.mMode == KeyboardId.MODE_PHONE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion) {
|
||||
final int width = mSpaceKey.width;
|
||||
final int height = mSpaceIcon.getIntrinsicHeight();
|
||||
|
@ -334,7 +344,8 @@ public class LatinKeyboard extends BaseKeyboard {
|
|||
final int width = Math.max(mSpaceKey.width,
|
||||
(int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
|
||||
final int height = mSpacePreviewIcon.getIntrinsicHeight();
|
||||
mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, width, height);
|
||||
mSlidingLocaleIcon =
|
||||
new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height);
|
||||
mSlidingLocaleIcon.setBounds(0, 0, width, height);
|
||||
mSpaceKey.iconPreview = mSlidingLocaleIcon;
|
||||
}
|
||||
|
@ -380,6 +391,7 @@ public class LatinKeyboard extends BaseKeyboard {
|
|||
* Does the magic of locking the touch gesture into the spacebar when
|
||||
* switching input languages.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isInside(LatinKey key, int x, int y) {
|
||||
final int code = key.codes[0];
|
||||
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);
|
||||
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;
|
||||
|
|
@ -14,9 +14,9 @@
|
|||
* 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 android.content.Context;
|
||||
|
@ -31,15 +31,7 @@ import android.view.MotionEvent;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class LatinKeyboardView extends BaseKeyboardView {
|
||||
|
||||
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;
|
||||
public class LatinKeyboardView extends KeyboardView {
|
||||
|
||||
/** Whether we've started dropping move events because we found a big jump */
|
||||
private boolean mDroppingEvents;
|
||||
|
@ -84,7 +76,7 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
|||
}
|
||||
|
||||
public LatinKeyboard getLatinKeyboard() {
|
||||
BaseKeyboard keyboard = getKeyboard();
|
||||
Keyboard keyboard = getKeyboard();
|
||||
if (keyboard instanceof LatinKeyboard) {
|
||||
return (LatinKeyboard)keyboard;
|
||||
} else {
|
||||
|
@ -95,8 +87,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
|||
@Override
|
||||
protected boolean onLongPress(Key key) {
|
||||
int primaryCode = key.codes[0];
|
||||
if (primaryCode == KEYCODE_OPTIONS) {
|
||||
return invokeOnKey(KEYCODE_OPTIONS_LONGPRESS);
|
||||
if (primaryCode == LatinKeyboard.KEYCODE_OPTIONS) {
|
||||
return invokeOnKey(LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS);
|
||||
} else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
|
||||
// Long pressing on 0 in phone number keypad gives you a '+'.
|
||||
return invokeOnKey('+');
|
||||
|
@ -107,8 +99,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
|||
|
||||
private boolean invokeOnKey(int primaryCode) {
|
||||
getOnKeyboardActionListener().onKey(primaryCode, null,
|
||||
BaseKeyboardView.NOT_A_TOUCH_COORDINATE,
|
||||
BaseKeyboardView.NOT_A_TOUCH_COORDINATE);
|
||||
KeyboardView.NOT_A_TOUCH_COORDINATE,
|
||||
KeyboardView.NOT_A_TOUCH_COORDINATE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -223,7 +215,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
|||
int languageDirection = keyboard.getLanguageChangeDirection();
|
||||
if (languageDirection != 0) {
|
||||
getOnKeyboardActionListener().onKey(
|
||||
languageDirection == 1 ? KEYCODE_NEXT_LANGUAGE : KEYCODE_PREV_LANGUAGE,
|
||||
languageDirection == 1
|
||||
? LatinKeyboard.KEYCODE_NEXT_LANGUAGE : LatinKeyboard.KEYCODE_PREV_LANGUAGE,
|
||||
null, mLastX, mLastY);
|
||||
me.setAction(MotionEvent.ACTION_CANCEL);
|
||||
keyboard.keyReleased();
|
||||
|
@ -236,8 +229,8 @@ public class LatinKeyboardView extends BaseKeyboardView {
|
|||
|
||||
/**************************** INSTRUMENTATION *******************************/
|
||||
|
||||
static final boolean DEBUG_AUTO_PLAY = false;
|
||||
static final boolean DEBUG_LINE = false;
|
||||
public static final boolean DEBUG_AUTO_PLAY = false;
|
||||
public static final boolean DEBUG_LINE = false;
|
||||
private static final int MSG_TOUCH_DOWN = 1;
|
||||
private static final int MSG_TOUCH_UP = 2;
|
||||
|
|
@ -14,11 +14,9 @@
|
|||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
||||
|
||||
class MiniKeyboardKeyDetector extends KeyDetector {
|
||||
public class MiniKeyboardKeyDetector extends KeyDetector {
|
||||
private static final int MAX_NEARBY_KEYS = 1;
|
||||
|
||||
private final int mSlideAllowanceSquare;
|
||||
|
@ -42,7 +40,7 @@ class MiniKeyboardKeyDetector extends KeyDetector {
|
|||
final int touchX = getTouchX(x);
|
||||
final int touchY = getTouchY(y);
|
||||
|
||||
int closestKeyIndex = BaseKeyboardView.NOT_A_KEY;
|
||||
int closestKeyIndex = NOT_A_KEY;
|
||||
int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
|
||||
final int keyCount = keys.length;
|
||||
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];
|
||||
return closestKeyIndex;
|
||||
}
|
|
@ -14,11 +14,11 @@
|
|||
* the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
||||
import com.android.inputmethod.latin.BaseKeyboardView.OnKeyboardActionListener;
|
||||
import com.android.inputmethod.latin.BaseKeyboardView.UIHandler;
|
||||
import com.android.inputmethod.keyboard.KeyboardView.UIHandler;
|
||||
import com.android.inputmethod.latin.LatinIME;
|
||||
import com.android.inputmethod.latin.R;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
|
@ -44,16 +44,16 @@ public class PointerTracker {
|
|||
private final int mMultiTapKeyTimeout;
|
||||
|
||||
// Miscellaneous constants
|
||||
private static final int NOT_A_KEY = BaseKeyboardView.NOT_A_KEY;
|
||||
private static final int[] KEY_DELETE = { BaseKeyboard.KEYCODE_DELETE };
|
||||
private static final int NOT_A_KEY = KeyDetector.NOT_A_KEY;
|
||||
private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE };
|
||||
|
||||
private final UIProxy mProxy;
|
||||
private final UIHandler mHandler;
|
||||
private final KeyDetector mKeyDetector;
|
||||
private OnKeyboardActionListener mListener;
|
||||
private KeyboardActionListener mListener;
|
||||
private final boolean mHasDistinctMultitouch;
|
||||
|
||||
private BaseKeyboard mKeyboard;
|
||||
private Keyboard mKeyboard;
|
||||
private Key[] mKeys;
|
||||
private int mKeyHysteresisDistanceSquared = -1;
|
||||
|
||||
|
@ -181,11 +181,11 @@ public class PointerTracker {
|
|||
resetMultiTap();
|
||||
}
|
||||
|
||||
public void setOnKeyboardActionListener(OnKeyboardActionListener listener) {
|
||||
public void setOnKeyboardActionListener(KeyboardActionListener 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)
|
||||
throw new IllegalArgumentException();
|
||||
mKeyboard = keyboard;
|
||||
|
@ -208,8 +208,8 @@ public class PointerTracker {
|
|||
if (key == null)
|
||||
return false;
|
||||
int primaryCode = key.codes[0];
|
||||
return primaryCode == BaseKeyboard.KEYCODE_SHIFT
|
||||
|| primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE;
|
||||
return primaryCode == Keyboard.KEYCODE_SHIFT
|
||||
|| primaryCode == Keyboard.KEYCODE_MODE_CHANGE;
|
||||
}
|
||||
|
||||
public boolean isModifier() {
|
||||
|
@ -420,7 +420,7 @@ public class PointerTracker {
|
|||
|
||||
private void startLongPressTimer(int keyIndex) {
|
||||
Key key = getKey(keyIndex);
|
||||
if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT) {
|
||||
if (key.codes[0] == Keyboard.KEYCODE_SHIFT) {
|
||||
mHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
|
||||
} else {
|
||||
mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
|
||||
|
@ -433,7 +433,7 @@ public class PointerTracker {
|
|||
}
|
||||
|
||||
private void detectAndSendKey(int index, int x, int y, long eventTime) {
|
||||
final OnKeyboardActionListener listener = mListener;
|
||||
final KeyboardActionListener listener = mListener;
|
||||
final Key key = getKey(index);
|
||||
|
||||
if (key == null) {
|
||||
|
@ -453,7 +453,7 @@ public class PointerTracker {
|
|||
// Multi-tap
|
||||
if (mInMultiTap) {
|
||||
if (mTapCount != -1) {
|
||||
mListener.onKey(BaseKeyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
|
||||
mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
|
||||
} else {
|
||||
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.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
class ProximityKeyDetector extends KeyDetector {
|
||||
public class ProximityKeyDetector extends KeyDetector {
|
||||
private static final int MAX_NEARBY_KEYS = 12;
|
||||
|
||||
// working area
|
||||
|
@ -37,8 +35,8 @@ class ProximityKeyDetector extends KeyDetector {
|
|||
final int touchX = getTouchX(x);
|
||||
final int touchY = getTouchY(y);
|
||||
|
||||
int primaryIndex = BaseKeyboardView.NOT_A_KEY;
|
||||
int closestKeyIndex = BaseKeyboardView.NOT_A_KEY;
|
||||
int primaryIndex = NOT_A_KEY;
|
||||
int closestKeyIndex = NOT_A_KEY;
|
||||
int closestKeyDist = mProximityThresholdSquare + 1;
|
||||
final int[] distances = mDistances;
|
||||
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.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
package com.android.inputmethod.keyboard;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
class SwipeTracker {
|
||||
public class SwipeTracker {
|
||||
private static final int NUM_PAST = 4;
|
||||
private static final int LONGEST_PAST_TIME = 200;
|
||||
|
||||
|
@ -91,7 +91,7 @@ class SwipeTracker {
|
|||
return mYVelocity;
|
||||
}
|
||||
|
||||
static class EventRingBuffer {
|
||||
public static class EventRingBuffer {
|
||||
private final int bufSize;
|
||||
private final float xBuf[];
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
return sCollator.compare(this.label, ((Loc) o).label);
|
||||
}
|
||||
|
|
|
@ -16,16 +16,19 @@
|
|||
|
||||
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.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
import android.view.InflateException;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -34,14 +37,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
private static final boolean DEBUG = 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.
|
||||
public static final String DEFAULT_LAYOUT_ID = "5";
|
||||
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 =
|
||||
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
|
||||
|
||||
private int mMode = MODE_TEXT; /* default value */
|
||||
private int mMode = KeyboardId.MODE_TEXT; /* default value */
|
||||
private int mImeOptions;
|
||||
private boolean mIsSymbols;
|
||||
/** 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"
|
||||
// respectively here for xlarge device's layout switching.
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return mVoiceKeyEnabled && (isSymbols != mVoiceButtonOnPrimary);
|
||||
}
|
||||
|
@ -327,9 +206,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
final boolean enableShiftLock;
|
||||
|
||||
if (isSymbols) {
|
||||
if (mode == MODE_PHONE) {
|
||||
if (mode == KeyboardId.MODE_PHONE) {
|
||||
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.
|
||||
xmlId = R.xml.kbd_number;
|
||||
} else {
|
||||
|
@ -337,10 +216,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
}
|
||||
enableShiftLock = false;
|
||||
} else {
|
||||
if (mode == MODE_PHONE) {
|
||||
if (mode == KeyboardId.MODE_PHONE) {
|
||||
xmlId = R.xml.kbd_phone;
|
||||
enableShiftLock = false;
|
||||
} else if (mode == MODE_NUMBER) {
|
||||
} else if (mode == KeyboardId.MODE_NUMBER) {
|
||||
xmlId = R.xml.kbd_number;
|
||||
enableShiftLock = false;
|
||||
} else {
|
||||
|
@ -731,7 +610,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
|
|||
|
||||
private int getColorScheme() {
|
||||
return (mInputView != null)
|
||||
? mInputView.getColorScheme() : BaseKeyboardView.COLOR_SCHEME_WHITE;
|
||||
? mInputView.getColorScheme() : KeyboardView.COLOR_SCHEME_WHITE;
|
||||
}
|
||||
|
||||
public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
|
||||
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.voice.VoiceIMEConnector;
|
||||
|
||||
|
@ -73,7 +79,7 @@ import java.util.Locale;
|
|||
* Input method implementation for Qwerty'ish keyboard.
|
||||
*/
|
||||
public class LatinIME extends InputMethodService
|
||||
implements BaseKeyboardView.OnKeyboardActionListener,
|
||||
implements KeyboardActionListener,
|
||||
SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
Tutorial.TutorialListener {
|
||||
private static final String TAG = "LatinIME";
|
||||
|
@ -548,10 +554,10 @@ public class LatinIME extends InputMethodService
|
|||
switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) {
|
||||
case EditorInfo.TYPE_CLASS_NUMBER:
|
||||
case EditorInfo.TYPE_CLASS_DATETIME:
|
||||
mode = KeyboardSwitcher.MODE_NUMBER;
|
||||
mode = KeyboardId.MODE_NUMBER;
|
||||
break;
|
||||
case EditorInfo.TYPE_CLASS_PHONE:
|
||||
mode = KeyboardSwitcher.MODE_PHONE;
|
||||
mode = KeyboardId.MODE_PHONE;
|
||||
break;
|
||||
case EditorInfo.TYPE_CLASS_TEXT:
|
||||
//startPrediction();
|
||||
|
@ -568,24 +574,24 @@ public class LatinIME extends InputMethodService
|
|||
}
|
||||
if (isEmailVariation(variation)) {
|
||||
mPredictionOn = false;
|
||||
mode = KeyboardSwitcher.MODE_EMAIL;
|
||||
mode = KeyboardId.MODE_EMAIL;
|
||||
} else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
|
||||
mPredictionOn = false;
|
||||
mode = KeyboardSwitcher.MODE_URL;
|
||||
mode = KeyboardId.MODE_URL;
|
||||
} 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) {
|
||||
mPredictionOn = false;
|
||||
mode = KeyboardSwitcher.MODE_TEXT;
|
||||
mode = KeyboardId.MODE_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
|
||||
// disable auto correction, but keep suggestions on.
|
||||
if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) {
|
||||
mInputTypeNoAutoCorrect = true;
|
||||
}
|
||||
} else {
|
||||
mode = KeyboardSwitcher.MODE_TEXT;
|
||||
mode = KeyboardId.MODE_TEXT;
|
||||
}
|
||||
|
||||
// If NO_SUGGESTIONS is set, don't do prediction.
|
||||
|
@ -604,7 +610,7 @@ public class LatinIME extends InputMethodService
|
|||
}
|
||||
break;
|
||||
default:
|
||||
mode = KeyboardSwitcher.MODE_TEXT;
|
||||
mode = KeyboardId.MODE_TEXT;
|
||||
break;
|
||||
}
|
||||
inputView.closing();
|
||||
|
@ -675,7 +681,7 @@ public class LatinIME extends InputMethodService
|
|||
|
||||
mVoiceConnector.flushVoiceInputLogs(mConfigurationChanging);
|
||||
|
||||
BaseKeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||
KeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||
if (inputView != null)
|
||||
inputView.closing();
|
||||
if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
|
||||
|
@ -685,7 +691,7 @@ public class LatinIME extends InputMethodService
|
|||
@Override
|
||||
public void onFinishInputView(boolean finishingInput) {
|
||||
super.onFinishInputView(finishingInput);
|
||||
BaseKeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||
KeyboardView inputView = mKeyboardSwitcher.getInputView();
|
||||
if (inputView != null)
|
||||
inputView.setForeground(false);
|
||||
// Remove pending messages related to update suggestions
|
||||
|
@ -1073,51 +1079,52 @@ public class LatinIME extends InputMethodService
|
|||
|
||||
// Implementation of KeyboardViewListener
|
||||
|
||||
@Override
|
||||
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
|
||||
long when = SystemClock.uptimeMillis();
|
||||
if (primaryCode != BaseKeyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
|
||||
if (primaryCode != Keyboard.KEYCODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
|
||||
mDeleteCount = 0;
|
||||
}
|
||||
mLastKeyTime = when;
|
||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||
switch (primaryCode) {
|
||||
case BaseKeyboard.KEYCODE_DELETE:
|
||||
case Keyboard.KEYCODE_DELETE:
|
||||
handleBackspace();
|
||||
mDeleteCount++;
|
||||
LatinImeLogger.logOnDelete();
|
||||
break;
|
||||
case BaseKeyboard.KEYCODE_SHIFT:
|
||||
case Keyboard.KEYCODE_SHIFT:
|
||||
// Shift key is handled in onPress() when device has distinct multi-touch panel.
|
||||
if (!distinctMultiTouch)
|
||||
switcher.toggleShift();
|
||||
break;
|
||||
case BaseKeyboard.KEYCODE_MODE_CHANGE:
|
||||
case Keyboard.KEYCODE_MODE_CHANGE:
|
||||
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
|
||||
if (!distinctMultiTouch)
|
||||
switcher.changeKeyboardMode();
|
||||
break;
|
||||
case BaseKeyboard.KEYCODE_CANCEL:
|
||||
case Keyboard.KEYCODE_CANCEL:
|
||||
if (!isShowingOptionDialog()) {
|
||||
handleClose();
|
||||
}
|
||||
break;
|
||||
case LatinKeyboardView.KEYCODE_OPTIONS:
|
||||
case LatinKeyboard.KEYCODE_OPTIONS:
|
||||
onOptionKeyPressed();
|
||||
break;
|
||||
case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS:
|
||||
case LatinKeyboard.KEYCODE_OPTIONS_LONGPRESS:
|
||||
onOptionKeyLongPressed();
|
||||
break;
|
||||
case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE:
|
||||
case LatinKeyboard.KEYCODE_NEXT_LANGUAGE:
|
||||
toggleLanguage(false, true);
|
||||
break;
|
||||
case LatinKeyboardView.KEYCODE_PREV_LANGUAGE:
|
||||
case LatinKeyboard.KEYCODE_PREV_LANGUAGE:
|
||||
toggleLanguage(false, false);
|
||||
break;
|
||||
case LatinKeyboardView.KEYCODE_CAPSLOCK:
|
||||
case LatinKeyboard.KEYCODE_CAPSLOCK:
|
||||
switcher.toggleCapsLock();
|
||||
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,
|
||||
mKeyboardSwitcher.getInputView().getWindowToken(), mConfigurationChanging);
|
||||
break;
|
||||
|
@ -1143,6 +1150,7 @@ public class LatinIME extends InputMethodService
|
|||
mEnteredText = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onText(CharSequence text) {
|
||||
mVoiceConnector.commitVoiceInput();
|
||||
InputConnection ic = getCurrentInputConnection();
|
||||
|
@ -1161,6 +1169,7 @@ public class LatinIME extends InputMethodService
|
|||
mEnteredText = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// User released a finger outside any key
|
||||
}
|
||||
|
@ -1421,6 +1430,7 @@ public class LatinIME extends InputMethodService
|
|||
|
||||
public void switchToKeyboardView() {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Switch to keyboard view.");
|
||||
|
@ -1437,7 +1447,8 @@ public class LatinIME extends InputMethodService
|
|||
setCandidatesViewShown(isCandidateStripVisible());
|
||||
updateInputViewShown();
|
||||
mHandler.postUpdateSuggestions();
|
||||
}});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void clearSuggestions() {
|
||||
|
@ -1586,8 +1597,8 @@ public class LatinIME extends InputMethodService
|
|||
LatinImeLogger.logOnManualSuggestion(
|
||||
"", suggestion.toString(), index, suggestions);
|
||||
final char primaryCode = suggestion.charAt(0);
|
||||
onKey(primaryCode, new int[]{primaryCode}, BaseKeyboardView.NOT_A_TOUCH_COORDINATE,
|
||||
BaseKeyboardView.NOT_A_TOUCH_COORDINATE);
|
||||
onKey(primaryCode, new int[]{primaryCode}, KeyboardView.NOT_A_TOUCH_COORDINATE,
|
||||
KeyboardView.NOT_A_TOUCH_COORDINATE);
|
||||
if (ic != null) {
|
||||
ic.endBatchEdit();
|
||||
}
|
||||
|
@ -1877,6 +1888,7 @@ public class LatinIME extends InputMethodService
|
|||
switcher.updateShiftState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
|
||||
String key) {
|
||||
mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key);
|
||||
|
@ -1888,6 +1900,7 @@ public class LatinIME extends InputMethodService
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeRight() {
|
||||
if (LatinKeyboardView.DEBUG_AUTO_PLAY) {
|
||||
CharSequence text = ((android.text.ClipboardManager)getSystemService(
|
||||
|
@ -1898,38 +1911,43 @@ public class LatinIME extends InputMethodService
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeLeft() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeDown() {
|
||||
handleClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipeUp() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPress(int primaryCode) {
|
||||
vibrate();
|
||||
playKeyClick(primaryCode);
|
||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
|
||||
if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||
switcher.onPressShift();
|
||||
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
|
||||
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||
switcher.onPressSymbol();
|
||||
} else {
|
||||
switcher.onOtherKeyPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRelease(int primaryCode) {
|
||||
KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||
// Reset any drag flags in the keyboard
|
||||
switcher.keyReleased();
|
||||
final boolean distinctMultiTouch = switcher.hasDistinctMultitouch();
|
||||
if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
|
||||
if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
|
||||
switcher.onReleaseShift();
|
||||
} else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
|
||||
} else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
|
||||
switcher.onReleaseSymbol();
|
||||
}
|
||||
}
|
||||
|
@ -1966,7 +1984,7 @@ public class LatinIME extends InputMethodService
|
|||
// FIXME: These should be triggered after auto-repeat logic
|
||||
int sound = AudioManager.FX_KEYPRESS_STANDARD;
|
||||
switch (primaryCode) {
|
||||
case BaseKeyboard.KEYCODE_DELETE:
|
||||
case Keyboard.KEYCODE_DELETE:
|
||||
sound = AudioManager.FX_KEYPRESS_DELETE;
|
||||
break;
|
||||
case KEYCODE_ENTER:
|
||||
|
@ -2006,6 +2024,7 @@ public class LatinIME extends InputMethodService
|
|||
}
|
||||
|
||||
// Tutorial.TutorialListener
|
||||
@Override
|
||||
public void onTutorialDone() {
|
||||
sendDownUpKeyEvents(-1); // Inform the setupwizard that tutorial is in last bubble
|
||||
mTutorial = null;
|
||||
|
@ -2171,6 +2190,7 @@ public class LatinIME extends InputMethodService
|
|||
itemInputMethod, itemSettings},
|
||||
new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface di, int position) {
|
||||
di.dismiss();
|
||||
switch (position) {
|
||||
|
|
|
@ -43,6 +43,7 @@ public class LatinIMEDebugSettings extends PreferenceActivity
|
|||
updateDebugMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||
if (key.equals(DEBUG_MODE_KEY)) {
|
||||
if (mDebugMode != null) {
|
||||
|
|
|
@ -137,6 +137,7 @@ public class LatinIMESettings extends PreferenceActivity
|
|||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||
(new BackupManager(this)).dataChanged();
|
||||
// If turning on voice input, show dialog
|
||||
|
@ -181,6 +182,7 @@ public class LatinIMESettings extends PreferenceActivity
|
|||
switch (id) {
|
||||
case VOICE_INPUT_CONFIRM_DIALOG:
|
||||
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
|
||||
mVoicePreference.setValue(mVoiceModeOff);
|
||||
|
@ -226,6 +228,7 @@ public class LatinIMESettings extends PreferenceActivity
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
mLogger.settingsWarningDialogDismissed();
|
||||
if (!mOkClicked) {
|
||||
|
|
|
@ -310,6 +310,7 @@ public class LatinIMEUtil {
|
|||
|
||||
public void write(final String log) {
|
||||
mLoggingHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
createLogFileIfNotExist();
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
|
@ -327,6 +328,7 @@ public class LatinIMEUtil {
|
|||
|
||||
public void printAll() {
|
||||
mLoggingHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mWriter.flush();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
@ -355,6 +357,7 @@ public class LatinIMEUtil {
|
|||
|
||||
public void clearAll() {
|
||||
mLoggingHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mFile != null && mFile.exists()) {
|
||||
if (LatinImeLogger.sDBG) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.keyboard.Keyboard;
|
||||
import com.android.inputmethod.latin.Dictionary.DataType;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -27,6 +28,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
|
|||
|
||||
public static boolean sDBG = false;
|
||||
|
||||
@Override
|
||||
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 onSetKeyboard(BaseKeyboard kb) {
|
||||
public static void onSetKeyboard(Keyboard kb) {
|
||||
}
|
||||
|
||||
public static void onPrintAllUsabilityStudtyLogs() {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.keyboard.LatinKeyboard;
|
||||
import com.android.inputmethod.voice.SettingsUtil;
|
||||
import com.android.inputmethod.voice.VoiceIMEConnector;
|
||||
import com.android.inputmethod.voice.VoiceInput;
|
||||
|
@ -197,7 +198,7 @@ public class SubtypeSwitcher {
|
|||
|| VoiceIMEConnector.getInstance().needsToShowWarningDialog()) {
|
||||
if (mVoiceInput != null) {
|
||||
// TODO: Call proper function to trigger VoiceIME
|
||||
mService.onKey(LatinKeyboardView.KEYCODE_VOICE, null, 0, 0);
|
||||
mService.onKey(LatinKeyboard.KEYCODE_VOICE, null, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -350,7 +351,7 @@ public class SubtypeSwitcher {
|
|||
if (DBG) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -423,6 +423,7 @@ public class Suggest implements Dictionary.WordCallback {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addWord(final char[] word, final int offset, final int length, int freq,
|
||||
final int dicTypeId, final Dictionary.DataType dataType) {
|
||||
Dictionary.DataType dataTypeForLog = dataType;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.latin.BaseKeyboard.Key;
|
||||
import com.android.inputmethod.keyboard.Key;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.format.DateFormat;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.keyboard.LatinKeyboardView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
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.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
|
||||
textView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent me) {
|
||||
Tutorial.this.next();
|
||||
return true;
|
||||
|
@ -237,6 +240,7 @@ public class Tutorial implements OnTouchListener {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
next();
|
||||
|
|
|
@ -97,6 +97,7 @@ public class UserDictionary extends ExpandableDictionary {
|
|||
|
||||
final ContentResolver contentResolver = getContext().getContentResolver();
|
||||
new Thread("addWord") {
|
||||
@Override
|
||||
public void run() {
|
||||
contentResolver.insert(Words.CONTENT_URI, values);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ public class FieldContext {
|
|||
bundle.putInt(IME_OPTIONS, info.imeOptions);
|
||||
}
|
||||
|
||||
@SuppressWarnings("static-access")
|
||||
private static void addInputConnectionToBundle(
|
||||
InputConnection conn, Bundle bundle) {
|
||||
if (conn == null) {
|
||||
|
@ -96,6 +97,7 @@ public class FieldContext {
|
|||
return mFieldInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mFieldInfo.toString();
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import java.util.List;
|
|||
* plays beeps, shows errors, etc.
|
||||
*/
|
||||
public class RecognitionView {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "RecognitionView";
|
||||
|
||||
private Handler mUiHandler; // Reference to UI thread
|
||||
|
@ -78,6 +79,7 @@ public class RecognitionView {
|
|||
|
||||
/** Updates the microphone icon to show user their volume.*/
|
||||
private Runnable mUpdateVolumeRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (mState != State.LISTENING) {
|
||||
return;
|
||||
|
@ -141,6 +143,7 @@ public class RecognitionView {
|
|||
|
||||
public void restoreState() {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Restart the spinner
|
||||
if (mState == State.WORKING) {
|
||||
|
@ -153,6 +156,7 @@ public class RecognitionView {
|
|||
|
||||
public void showInitializing() {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
prepareDialog(false, mContext.getText(R.string.voice_initializing), mInitializing,
|
||||
mContext.getText(R.string.cancel));
|
||||
|
@ -162,6 +166,7 @@ public class RecognitionView {
|
|||
|
||||
public void showListening() {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mState = State.LISTENING;
|
||||
prepareDialog(false, mContext.getText(R.string.voice_listening), mSpeakNow.get(0),
|
||||
|
@ -177,6 +182,7 @@ public class RecognitionView {
|
|||
|
||||
public void showError(final String message) {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mState = State.READY;
|
||||
prepareDialog(false, message, mError, mContext.getText(R.string.ok));
|
||||
|
@ -190,6 +196,7 @@ public class RecognitionView {
|
|||
final int speechEndPosition) {
|
||||
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mState = State.WORKING;
|
||||
prepareDialog(true, mContext.getText(R.string.voice_working), null, mContext
|
||||
|
@ -309,6 +316,7 @@ public class RecognitionView {
|
|||
|
||||
public void finish() {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mState = State.READY;
|
||||
exitWorking();
|
||||
|
|
|
@ -39,7 +39,6 @@ import android.text.Selection;
|
|||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.method.MovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -120,6 +119,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
|||
if (VOICE_INSTALLED) {
|
||||
mVoiceInput = new VoiceInput(context, this);
|
||||
mHints = new Hints(context, prefs, new Hints.Display() {
|
||||
@Override
|
||||
public void showHint(int viewResource) {
|
||||
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
@ -519,6 +519,7 @@ public class VoiceIMEConnector implements VoiceInput.UiListener {
|
|||
public void switchToRecognitionStatusView(final boolean configurationChanging) {
|
||||
final boolean configChanged = configurationChanging;
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mContext.setCandidatesViewShown(false);
|
||||
mRecognizing = true;
|
||||
|
|
|
@ -86,6 +86,7 @@ public class VoiceInput implements OnClickListener {
|
|||
private static final String ALTERNATES_BUNDLE = "alternates_bundle";
|
||||
|
||||
// This is copied from the VoiceSearch app.
|
||||
@SuppressWarnings("unused")
|
||||
private static final class AlternatesBundleKeys {
|
||||
public static final String ALTERNATES = "alternates";
|
||||
public static final String CONFIDENCE = "confidence";
|
||||
|
@ -405,6 +406,7 @@ public class VoiceInput implements OnClickListener {
|
|||
/**
|
||||
* Handle the cancel button.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch(view.getId()) {
|
||||
case R.id.button:
|
||||
|
@ -556,36 +558,43 @@ public class VoiceInput implements OnClickListener {
|
|||
int mSpeechStart;
|
||||
private boolean mEndpointed = false;
|
||||
|
||||
@Override
|
||||
public void onReadyForSpeech(Bundle noiseParams) {
|
||||
mRecognitionView.showListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeginningOfSpeech() {
|
||||
mEndpointed = false;
|
||||
mSpeechStart = mWaveBuffer.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRmsChanged(float rmsdB) {
|
||||
mRecognitionView.updateVoiceMeter(rmsdB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBufferReceived(byte[] buf) {
|
||||
try {
|
||||
mWaveBuffer.write(buf);
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEndOfSpeech() {
|
||||
mEndpointed = true;
|
||||
mState = WORKING;
|
||||
mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int errorType) {
|
||||
mState = ERROR;
|
||||
VoiceInput.this.onError(errorType, mEndpointed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResults(Bundle resultsBundle) {
|
||||
List<String> results = resultsBundle
|
||||
.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
|
||||
|
@ -638,10 +647,12 @@ public class VoiceInput implements OnClickListener {
|
|||
mRecognitionView.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPartialResults(final Bundle partialResults) {
|
||||
// currently - do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(int eventType, Bundle params) {
|
||||
// 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.
|
||||
*/
|
||||
public class VoiceInputLogger {
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = VoiceInputLogger.class.getSimpleName();
|
||||
|
||||
private static VoiceInputLogger sVoiceInputLogger;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import com.android.inputmethod.latin.SwipeTracker.EventRingBuffer;
|
||||
import com.android.inputmethod.keyboard.SwipeTracker.EventRingBuffer;
|
||||
|
||||
import android.test.AndroidTestCase;
|
||||
|
||||
|
|
Loading…
Reference in New Issue