/*
* Copyright (c) 2013 Menny Even-Danan
*
* 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.anysoftkeyboard.keyboards;
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.SparseIntArray;
import android.util.Xml;
import android.view.inputmethod.EditorInfo;
import com.anysoftkeyboard.AnySoftKeyboard;
import com.anysoftkeyboard.api.KeyCodes;
import com.anysoftkeyboard.keyboardextensions.KeyboardExtension;
import com.anysoftkeyboard.keyboardextensions.KeyboardExtensionFactory;
import com.anysoftkeyboard.keyboards.views.KeyDrawableStateProvider;
import com.anysoftkeyboard.quicktextkeys.QuickTextKey;
import com.anysoftkeyboard.quicktextkeys.QuickTextKeyFactory;
import com.anysoftkeyboard.utils.Log;
import com.anysoftkeyboard.utils.Workarounds;
import com.menny.android.anysoftkeyboard.AnyApplication;
import com.menny.android.anysoftkeyboard.R;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
public abstract class AnyKeyboard extends Keyboard {
private final static String TAG = "ASK - AK";
public interface HardKeyboardAction {
int getKeyCode();
boolean isAltActive();
boolean isShiftActive();
void setNewKeyCode(int keyCode);
}
public interface HardKeyboardTranslator {
/*
* Gets the current state of the hard keyboard, and may change the
* output key-code.
*/
void translatePhysicalCharacter(HardKeyboardAction action,
AnySoftKeyboard ime);
}
private static final String TAG_ROW = "Row";
private static final String TAG_KEY = "Key";
private static class KeyboardMetadata {
public int keysCount = 0;
public int rowHeight = 0;
public int rowWidth = 0;
public int verticalGap = 0;
public boolean isTopRow = false;
}
private static final int STICKY_KEY_OFF = 0;
private static final int STICKY_KEY_ON = 1;
private static final int STICKY_KEY_LOCKED = 2;
private int mShiftState = STICKY_KEY_OFF;
private int mControlState = STICKY_KEY_OFF;
// private final boolean mDebug;
// private final Drawable mShiftIcon;
// private final Drawable mShiftOnIcon;
// private final Drawable mShiftLockedIcon;
// private final Drawable mShiftFeedbackIcon;
// private final Drawable mShiftOnFeedbackIcon;
// private final Drawable mShiftLockedFeedbackIcon;
private Key mShiftKey;
private Key mControlKey;
private EnterKey mEnterKey;
// public Key langSwitch;
private boolean mRightToLeftLayout = false;// the "super" ctor will create
// keys, and we'll set the
// correct value there.
private boolean mTopRowWasCreated;
private boolean mBottomRowWasCreated;
private int mGenericRowsHeight = 0;
private int mTopRowKeysCount = 0;
// max(generic row widths)
private int mMaxGenericRowsWidth = 0;
private KeyboardCondenser mKeyboardCondenser;
// private int mKeyboardActionType = EditorInfo.IME_ACTION_NONE;
// for popup keyboard
// note: the context can be from a different package!
protected AnyKeyboard(Context askContext, Context context,
int xmlLayoutResId) {
// should use the package context for creating the layout
super(askContext, context, xmlLayoutResId, -1);
// no generic rows in popup
}
// for the External
// note: the context can be from a different package!
protected AnyKeyboard(Context askContext, Context context,
int xmlLayoutResId, int mode) {
// should use the package context for creating the layout
super(askContext, context, xmlLayoutResId, mode);
}
public void loadKeyboard(final KeyboardDimens keyboardDimens) {
super.loadKeyboard(keyboardDimens);
addGenericRows(mKeyboardMode, keyboardDimens);
initKeysMembers(mASKContext);
//releasing memory
attributeIdMap = null;
remoteKeyboardLayoutStyleable = null;
remoteKeyboardRowLayoutStyleable = null;
remoteKeyboardKeyLayoutStyleable = null;
}
;
private void initKeysMembers(Context askContext) {
for (final Key key : getKeys()) {
if (key.y == 0)
key.edgeFlags |= Keyboard.EDGE_TOP;
// Log.d(TAG,
// "Key x:"+key.x+" y:"+key.y+" width:"+key.width+" height:"+key.height);
if ((key.codes != null) && (key.codes.length > 0)) {
final int primaryCode = key.codes[0];
if (key instanceof AnyKey) {
switch (primaryCode) {
case KeyCodes.DELETE:
case KeyCodes.MODE_ALPHABET:
case KeyCodes.KEYBOARD_MODE_CHANGE:
case KeyCodes.KEYBOARD_CYCLE:
case KeyCodes.KEYBOARD_CYCLE_INSIDE_MODE:
case KeyCodes.KEYBOARD_REVERSE_CYCLE:
case KeyCodes.ALT:
case KeyCodes.MODE_SYMOBLS:
case KeyCodes.QUICK_TEXT:
case KeyCodes.DOMAIN:
case KeyCodes.CANCEL:
case KeyCodes.CTRL:
((AnyKey) key).setAsFunctional();
break;
}
}
// detecting LTR languages
if (Workarounds.isRightToLeftCharacter((char) primaryCode))
mRightToLeftLayout = true;// one is enough
switch (primaryCode) {
case KeyCodes.QUICK_TEXT:
QuickTextKey quickKey = QuickTextKeyFactory
.getCurrentQuickTextKey(askContext);
if (quickKey == null) { // No plugins. Weird, but we
// can't do anything
Log.w(TAG,
"Could not locate any quick key plugins! Hopefully nothing will crash...");
break;
}
Resources quickTextKeyResources = quickKey
.getPackageContext().getResources();
key.label = quickKey.getKeyLabel();
int iconResId = quickKey.getKeyIconResId();
int previewResId = quickKey.getIconPreviewResId();
if (iconResId > 0) {
setKeyIcons(key, quickTextKeyResources, iconResId,
previewResId);
}
/*
* Popup resource may be from another context, requires
* special handling when the key is long-pressed!
*/
key.popupResId = quickKey.getPopupKeyboardResId();
key.externalResourcePopupLayout = key.popupResId != 0;
break;
case KeyCodes.DOMAIN:
// fixing icons
key.label = AnyApplication.getConfig().getDomainText()
.trim();
key.popupResId = R.xml.popup_domains;
break;
default:
// setting the character label
if (isAlphabetKey(key) && (key.icon == null)) {
final boolean labelIsOriginallyEmpty = TextUtils
.isEmpty(key.label);
if (labelIsOriginallyEmpty) {
final char code = (char) key.codes[0];
// check the ASCII table, everything below 32,
// is not printable
if (code > 31 && !Character.isWhitespace(code))
key.label = "" + code;
}
}
}
}
}
mKeyboardCondenser = new KeyboardCondenser(askContext, this);
}
protected void addGenericRows(int mode, final KeyboardDimens keyboardDimens) {
final KeyboardMetadata topMd;
if (!mTopRowWasCreated) {
final KeyboardExtension topRowPlugin =
KeyboardExtensionFactory.getCurrentKeyboardExtension(mASKContext, KeyboardExtension.TYPE_TOP);
if (topRowPlugin == null || // no plugin found
// plugin specified to be empty
topRowPlugin.getKeyboardResId() == 0 ||
// could not parse layout res id
topRowPlugin.getKeyboardResId() == -2) {
Log.d(TAG, "No top row layout");
topMd = null;
// adding EDGE_TOP to top keys. See issue 775
List<Key> keys = getKeys();
for (int keyIndex = 0; keyIndex < keys.size(); keyIndex++) {
final Key key = keys.get(keyIndex);
if (key.y == 0)
key.edgeFlags = key.edgeFlags | Keyboard.EDGE_TOP;
}
} else {
//replacing the styleables
attributeIdMap.clear();
remoteKeyboardLayoutStyleable = KeyboardSupport.createBackwardCompatibleStyleable(
R.styleable.KeyboardLayout, mASKContext, topRowPlugin.getPackageContext(), attributeIdMap);
remoteKeyboardKeyLayoutStyleable = KeyboardSupport.createBackwardCompatibleStyleable(
R.styleable.KeyboardLayout_Key, mASKContext, topRowPlugin.getPackageContext(), attributeIdMap);
remoteKeyboardRowLayoutStyleable = KeyboardSupport.createBackwardCompatibleStyleable(
R.styleable.KeyboardLayout_Row, mASKContext, topRowPlugin.getPackageContext(), attributeIdMap);
Log.d(TAG, "Top row layout id " + topRowPlugin.getId());
topMd = addKeyboardRow(topRowPlugin.getPackageContext(),
topRowPlugin.getKeyboardResId(), mode, keyboardDimens);
}
if (topMd != null)
fixKeyboardDueToGenericRow(topMd,
(int) keyboardDimens.getRowVerticalGap());
}
if (!mBottomRowWasCreated) {
final KeyboardExtension bottomRowPlugin =
KeyboardExtensionFactory.getCurrentKeyboardExtension(mASKContext, KeyboardExtension.TYPE_BOTTOM);
Log.d(TAG, "Bottom row layout id " + bottomRowPlugin.getId());
attributeIdMap.clear();
remoteKeyboardLayoutStyleable = KeyboardSupport.createBackwardCompatibleStyleable(
R.styleable.KeyboardLayout, mASKContext, bottomRowPlugin.getPackageContext(), attributeIdMap);
remoteKeyboardKeyLayoutStyleable = KeyboardSupport.createBackwardCompatibleStyleable(
R.styleable.KeyboardLayout_Key, mASKContext, bottomRowPlugin.getPackageContext(), attributeIdMap);
remoteKeyboardRowLayoutStyleable = KeyboardSupport.createBackwardCompatibleStyleable(
R.styleable.KeyboardLayout_Row, mASKContext, bottomRowPlugin.getPackageContext(), attributeIdMap);
KeyboardMetadata bottomMd = addKeyboardRow(
bottomRowPlugin.getPackageContext(),
bottomRowPlugin.getKeyboardResId(), mode, keyboardDimens);
fixKeyboardDueToGenericRow(bottomMd,
(int) keyboardDimens.getRowVerticalGap());
}
}
private void fixKeyboardDueToGenericRow(KeyboardMetadata md,
int rowVerticalGap) {
final int additionalPixels = (md.rowHeight + md.verticalGap + rowVerticalGap);
mGenericRowsHeight += additionalPixels;
if (md.isTopRow) {
mTopRowKeysCount += md.keysCount;
List<Key> keys = getKeys();
for (int keyIndex = md.keysCount; keyIndex < keys.size(); keyIndex++) {
final Key key = keys.get(keyIndex);
key.y += additionalPixels;
// if (key instanceof LessSensitiveAnyKey)
// ((LessSensitiveAnyKey)key).resetSenitivity();//reseting cause
// the key may be offseted now (generic rows)
}
}/*
* else { // The height should not include any gap below that last row
* // this corresponds to // mTotalHeight = y - mDefaultVerticalGap; //
* in the Keyboard class from Android sources // Note that we are using
* keyboard default vertical gap (instead of row vertical gap) // as
* this is done also in Android sources. mGenericRowsHeight -=
* getVerticalGap(); }
*/
}
private KeyboardMetadata addKeyboardRow(Context context, int rowResId,
int mode, final KeyboardDimens keyboardDimens) {
XmlResourceParser parser = context.getResources().getXml(rowResId);
List<Key> keys = getKeys();
boolean inKey = false;
boolean inRow = false;
// boolean leftMostKey = false;
boolean skipRow = false;
final float keyHorizontalGap = keyboardDimens.getKeyHorizontalGap();
final float rowVerticalGap = keyboardDimens.getRowVerticalGap();
int row = 0;
float x = 0;
float y = rowVerticalGap;
Key key = null;
Row currentRow = null;
Resources res = context.getResources();
KeyboardMetadata m = new KeyboardMetadata();
try {
int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) {
String tag = parser.getName();
if (TAG_ROW.equals(tag)) {
inRow = true;
x = 0;
currentRow = createRowFromXml(mASKContext, res, parser);
skipRow = currentRow.mode != 0
&& currentRow.mode != mode;
if (skipRow) {
currentRow = null;
skipToEndOfRow(parser);
inRow = false;
} else {
m.isTopRow = currentRow.rowEdgeFlags == Keyboard.EDGE_TOP;
if (!m.isTopRow) {
// the bottom row Y should be last
// The last coordinate is height + keyboard's
// default vertical gap
// since mTotalHeight = y - mDefaultVerticalGap;
// (see loadKeyboard
// in the android sources)
// We use our overriden getHeight method which
// is just fixed so that it includes the first
// generic row.
y = getHeight() + getVerticalGap();
}
m.rowHeight = 0;
m.verticalGap = currentRow.verticalGap;
}
} else if (TAG_KEY.equals(tag)) {
inKey = true;
x += (keyHorizontalGap / 2);
key = createKeyFromXml(mASKContext, context, currentRow,
keyboardDimens, (int) x, (int) y, parser);
key.width -= keyHorizontalGap;// the gap is on both
// sides
if (m.isTopRow)
keys.add(m.keysCount, key);
else
keys.add(key);
m.keysCount++;
m.rowHeight = Math.max(key.height, m.rowHeight);
}
} else if (event == XmlResourceParser.END_TAG) {
if (inKey) {
inKey = false;
x += (key.gap + key.width);
x += (keyHorizontalGap / 2);
if (x > m.rowWidth) {
m.rowWidth = (int) x;
// We keep generic row max width updated
mMaxGenericRowsWidth = Math.max(
mMaxGenericRowsWidth, m.rowWidth);
}
} else if (inRow) {
inRow = false;
y += currentRow.verticalGap;
y += m.rowHeight;
y += rowVerticalGap;
row++;
} else {
// TODO: error or extend?
}
}
}
} catch (Exception e) {
Log.e(TAG, "Parse error:" + e);
e.printStackTrace();
}
// mTotalHeight = y - mDefaultVerticalGap;
return m;
}
private void skipToEndOfRow(XmlResourceParser parser)
throws XmlPullParserException, IOException {
int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
if (event == XmlResourceParser.END_TAG
&& parser.getName().equals(TAG_ROW)) {
break;
}
}
}
/* required overrides */
@Override
public int getHeight() {
return super.getHeight() + mGenericRowsHeight;
}
// minWidth is actually 'total width', see android framework source code
@Override
public int getMinWidth() {
return Math.max(mMaxGenericRowsWidth, super.getMinWidth());
}
@Override
public int getShiftKeyIndex() {
return super.getShiftKeyIndex() + mTopRowKeysCount;
}
private void setKeyIcons(Key key, Resources localResources, int iconId,
int iconFeedbackId) {
try {
key.icon = localResources.getDrawable(iconId);
if (iconFeedbackId > 0) {
Drawable preview = localResources.getDrawable(iconFeedbackId);
KeyboardSupport.updateDrawableBounds(preview);
key.iconPreview = preview;
}
} catch (OutOfMemoryError m) {
Log.w(TAG,
"Low memory when trying to load key icon. I'll leave it empty.");
}
if (key.icon != null)
key.label = null;
}
public Context getKeyboardContext() {
return mKeyboardContext;
}
public abstract String getDefaultDictionaryLocale();
// this function is called from within the super constructor.
@Override
protected Key createKeyFromXml(Context askContext, Context keyboardContext,
Row parent, KeyboardDimens keyboardDimens, int x, int y,
XmlResourceParser parser) {
AnyKey key = new AnyKey(askContext, keyboardContext, parent, keyboardDimens, x, y,
parser);
if ((key.codes != null) && (key.codes.length > 0)) {
final int primaryCode = key.codes[0];
// creating less sensitive keys if required
switch (primaryCode) {
case KeyCodes.DISABLED:// disabled
key.disable();
break;
case KeyCodes.ENTER:// enter
key = mEnterKey = new EnterKey(mASKContext, keyboardContext, parent,
keyboardDimens, x, y, parser);
break;
case KeyCodes.SHIFT:
mShiftKey = key;// I want the reference used by the super.
break;
case KeyCodes.CTRL:
mControlKey = key;
break;
// case KeyCodes.DELETE://delete
// key = new LessSensitiveAnyKey(mASKContext, res, parent, x, y,
// parser);
// break;
}
}
setPopupKeyChars(key);
return key;
}
@Override
protected Row createRowFromXml(Context askContext, Resources res,
XmlResourceParser parser) {
Row aRow = super.createRowFromXml(askContext, res, parser);
if (aRow.mode > 0)
aRow.mode = res.getInteger(aRow.mode);// switching to the mode!
if ((aRow.rowEdgeFlags & Keyboard.EDGE_TOP) != 0)
mTopRowWasCreated = true;
if ((aRow.rowEdgeFlags & Keyboard.EDGE_BOTTOM) != 0)
mBottomRowWasCreated = true;
return aRow;
}
private boolean isAlphabetKey(Key key) {
return (!key.modifier) && (!key.sticky) && (!key.repeatable) &&
/* (key.icon == null) && */
(key.codes[0] > 0);
}
public boolean isStartOfWordLetter(char keyValue) {
return Character.isLetter(keyValue)/* || (keyValue == '\'') */;
}
public boolean isInnerWordLetter(char keyValue) {
return Character.isLetter(keyValue) || (keyValue == '\'');
}
public abstract HashSet<Character> getSentenceSeparators();
/**
* This looks at the ime options given by the current editor, to set the
* appropriate label on the keyboard's enter key (if it has one).
*/
public void setImeOptions(Resources res, EditorInfo editor) {
if (mEnterKey == null) {
return;
}
// Issue 254: we know of a known Android Messaging bug
// http://code.google.com/p/android/issues/detail?id=2739
if (Workarounds.doubleActionKeyDisableWorkAround(editor)) {// package:
// com.android.mms,
// id:2131361817
mEnterKey.disable();
return;
}
// int options = (editor == null)? 0 : editor.imeOptions;
// CharSequence imeLabel = (editor == null)? null :editor.actionLabel;
// int imeActionId = (editor == null)? -1 :editor.actionId;
mEnterKey.enable();
}
public abstract String getKeyboardName();
public boolean isLeftToRightLanguage() {
return !mRightToLeftLayout;
}
public abstract int getKeyboardIconResId();
public boolean setShiftLocked(boolean shiftLocked) {
if (keyboardSupportShift()) {
final int initialState = mShiftState;
if (shiftLocked) {
mShiftState = STICKY_KEY_LOCKED;
} else if (mShiftState == STICKY_KEY_LOCKED) {
mShiftState = STICKY_KEY_ON;
}
setShiftViewAsState();
return initialState != mShiftState;
}
return false;
}
@Override
public boolean isShifted() {
if (keyboardSupportShift()) {
return mShiftState != STICKY_KEY_OFF;
} else {
return false;
}
}
@Override
public boolean setShifted(boolean shiftState) {
if (keyboardSupportShift()) {
final int initialState = mShiftState;
if (shiftState) {
if (mShiftState == STICKY_KEY_OFF) {// so it is not LOCKED
mShiftState = STICKY_KEY_ON;
}
// else this is already ON, or at caps lock.
} else {
mShiftState = STICKY_KEY_OFF;
}
setShiftViewAsState();
return mShiftState != initialState;
} else {
super.setShifted(shiftState);
return false;
}
}
protected boolean keyboardSupportShift() {
return mShiftKey != null;
}
private void setShiftViewAsState() {
// the "on" led is just like the caps-lock led
if (mShiftKey != null)
mShiftKey.on = (mShiftState == STICKY_KEY_LOCKED);
}
public boolean isShiftLocked() {
return mShiftState == STICKY_KEY_LOCKED;
}
public boolean isControl() {
if (mControlKey != null) {
return mControlState != STICKY_KEY_OFF;
} else {
return false;
}
}
public boolean setControl(boolean control) {
if (mControlKey != null) {
final int initialState = mControlState;
if (control) {
if (mControlState == STICKY_KEY_OFF) {// so it is not LOCKED
mControlState = STICKY_KEY_ON;
}
// else this is already ON, or at caps lock.
} else {
mControlState = STICKY_KEY_OFF;
}
setControlViewAsState();
return mControlState != initialState;
} else {
return false;
}
}
private void setControlViewAsState() {
// the "on" led is just like the caps-lock led
mControlKey.on = (mControlState == STICKY_KEY_LOCKED);
}
/*
* public boolean isControlLocked() { return mControlState ==
* STICKY_KEY_LOCKED; }
*/
protected void setPopupKeyChars(Key aKey) {
}
public static class AnyKey extends Keyboard.Key {
public int[] shiftedCodes;
public CharSequence shiftedKeyLabel;
public CharSequence hintLabel;
public int longPressCode;
private boolean mFunctionalKey;
private boolean mEnabled;
public AnyKey(Row row, KeyboardDimens keyboardDimens) {
super(row, keyboardDimens);
}
public AnyKey(Context askContext, Context keyboardContext, Keyboard.Row parent,
KeyboardDimens keyboardDimens, int x, int y,
XmlResourceParser parser) {
super(askContext, keyboardContext, parent, keyboardDimens, x, y, parser);
//setting up some defaults
mEnabled = true;
mFunctionalKey = false;
shiftedCodes = null;
longPressCode = 0;
shiftedKeyLabel = null;
hintLabel = null;
Keyboard parentKeyboard = parent.parent;
SparseIntArray attributeIdMap = parentKeyboard.attributeIdMap;
int[] remoteKeyboardKeyLayoutStyleable = parentKeyboard.remoteKeyboardKeyLayoutStyleable;
TypedArray a = keyboardContext.obtainStyledAttributes(Xml.asAttributeSet(parser), remoteKeyboardKeyLayoutStyleable);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
final int remoteIndex = a.getIndex(i);
final int localAttrId = attributeIdMap.get(remoteKeyboardKeyLayoutStyleable[remoteIndex]);
try {
switch (localAttrId) {
case R.attr.shiftedCodes:
shiftedCodes = KeyboardSupport.getKeyCodesFromTypedArray(a, remoteIndex);
break;
case R.attr.longPressCode:
longPressCode = a.getInt(remoteIndex, 0);
break;
case R.attr.isFunctional:
mFunctionalKey = a.getBoolean(remoteIndex, false);
break;
case R.attr.shiftedKeyLabel:
shiftedKeyLabel = a.getString(remoteIndex);
break;
case R.attr.hintLabel:
hintLabel = a.getString(remoteIndex);
break;
}
} catch (Exception e) {
Log.w(TAG, "Failed to set data from XML!", e);
}
}
a.recycle();
// ensuring codes and shiftedCodes are the same size
if (shiftedCodes != null && shiftedCodes.length != codes.length) {
int[] wrongSizedShiftCodes = shiftedCodes;
shiftedCodes = new int[codes.length];
int i = 0;
for (i = 0; i < wrongSizedShiftCodes.length && i < codes.length; i++)
shiftedCodes[i] = wrongSizedShiftCodes[i];
for (/* starting from where i finished above */; i < codes.length; i++) {
final int code = codes[i];
if (Character.isLetter(code))
shiftedCodes[i] = Character.toUpperCase(code);
else
shiftedCodes[i] = code;
}
}
if (popupCharacters != null && popupCharacters.length() == 0) {
// If there is a keyboard with no keys specified in
// popupCharacters
popupResId = 0;
}
}
public void enable() {
mEnabled = true;
}
public void disable() {
iconPreview = null;
icon = null;
label = " ";// can not use NULL.
mEnabled = false;
}
public boolean isInside(int clickedX, int clickedY) {
if (mEnabled)
return super.isInside(clickedX, clickedY);
else
return false;// disabled.
}
public void setAsFunctional() {
mFunctionalKey = true;
}
@Override
public int[] getCurrentDrawableState(KeyDrawableStateProvider provider) {
if (mFunctionalKey) {
if (pressed) {
return provider.KEY_STATE_FUNCTIONAL_PRESSED;
} else {
return provider.KEY_STATE_FUNCTIONAL_NORMAL;
}
}
return super.getCurrentDrawableState(provider);
}
}
private static class EnterKey extends AnyKey {
private final int mOriginalHeight;
public EnterKey(Context askContext, Context keyboardContext, Row parent,
KeyboardDimens keyboardDimens, int x, int y,
XmlResourceParser parser) {
super(askContext, keyboardContext, parent, keyboardDimens, x, y, parser);
mOriginalHeight = this.height;
}
@Override
public void disable() {
if (AnyApplication.getConfig().getActionKeyInvisibleWhenRequested())
this.height = 0;
super.disable();
}
@Override
public void enable() {
this.height = mOriginalHeight;
super.enable();
}
@Override
public int[] getCurrentDrawableState(KeyDrawableStateProvider provider) {
if (pressed) {
return provider.KEY_STATE_ACTION_PRESSED;
} else {
return provider.KEY_STATE_ACTION_NORMAL;
}
}
}
public abstract String getKeyboardPrefId();
public boolean requiresProximityCorrection() {
return getKeys().size() > 20;
}
public int getKeyboardMode() {
return mKeyboardMode;
}
public void setCondensedKeys(CondenseType condenseType) {
if (mKeyboardCondenser.setCondensedKeys(condenseType))
computeNearestNeighbors();//keyboard has changed, so we need to recompute the neighbors.
}
}