Merge "Introduce KeyboardSet to hold related KeyboardIds"

This commit is contained in:
Tadashi G. Takaoka 2011-12-13 01:12:10 -08:00 committed by Android (Google) Code Review
commit cfe264bfee
2 changed files with 144 additions and 80 deletions

View file

@ -0,0 +1,134 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SettingsValues;
import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.Utils;
import java.util.Locale;
/**
* This class has a set of {@link KeyboardId}s. Each of them represents a different keyboard
* specific to a keyboard state, such as alphabet, symbols, and so on. Layouts in the same
* {@link KeyboardSet} are related to each other.
* A {@link KeyboardSet} needs to be created for each {@link android.view.inputmethod.EditorInfo}.
*/
public class KeyboardSet {
// TODO: Make these KeyboardId private.
public final KeyboardId mAlphabetId;
public final KeyboardId mSymbolsId;
public final KeyboardId mSymbolsShiftedId;
KeyboardSet(Builder builder) {
mAlphabetId = builder.getKeyboardId(false, false);
mSymbolsId = builder.getKeyboardId(true, false);
mSymbolsShiftedId = builder.getKeyboardId(true, true);
}
public static class Builder {
private final Resources mResources;
private final EditorInfo mEditorInfo;
private final int mMode;
private final boolean mVoiceKeyEnabled;
private final boolean mNoSettingsKey;
private final boolean mHasSettingsKey;
private final int mF2KeyMode;
private final boolean mVoiceKeyOnMain;
private final Locale mLocale;
private final Configuration mConf;
private final DisplayMetrics mMetrics;
public Builder(Context context, EditorInfo editorInfo, SettingsValues settingsValues) {
mResources = context.getResources();
mEditorInfo = editorInfo;
final SubtypeSwitcher subtypeSwitcher = SubtypeSwitcher.getInstance();
final String packageName = context.getPackageName();
mMode = Utils.getKeyboardMode(mEditorInfo);
final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
@SuppressWarnings("deprecation")
final boolean noMicrophone = Utils.inPrivateImeOptions(
packageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
|| Utils.inPrivateImeOptions(
null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
mVoiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo) && !noMicrophone;
mVoiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
mNoSettingsKey = Utils.inPrivateImeOptions(
packageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
mHasSettingsKey = settingsKeyEnabled && !mNoSettingsKey;
mF2KeyMode = getF2KeyMode(settingsKeyEnabled, mNoSettingsKey);
final boolean forceAscii = Utils.inPrivateImeOptions(
packageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
final boolean asciiCapable = subtypeSwitcher.currentSubtypeContainsExtraValueKey(
LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
mLocale = (forceAscii && !asciiCapable) ? Locale.US : subtypeSwitcher.getInputLocale();
mConf = mResources.getConfiguration();
mMetrics = mResources.getDisplayMetrics();
}
public KeyboardSet build() {
return new KeyboardSet(this);
}
KeyboardId getKeyboardId(boolean isSymbols, boolean isShift) {
final int xmlId = getXmlId(mMode, isSymbols, isShift);
final boolean hasShortCutKey = mVoiceKeyEnabled && (isSymbols != mVoiceKeyOnMain);
return new KeyboardId(mResources.getResourceEntryName(xmlId), xmlId, mLocale,
mConf.orientation, mMetrics.widthPixels, mMode, mEditorInfo, mHasSettingsKey,
mF2KeyMode, mNoSettingsKey, mVoiceKeyEnabled, hasShortCutKey);
}
private static int getXmlId(int mode, boolean isSymbols, boolean isShift) {
switch (mode) {
case KeyboardId.MODE_PHONE:
return (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
case KeyboardId.MODE_NUMBER:
return R.xml.kbd_number;
default:
if (isSymbols) {
return isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
}
return R.xml.kbd_qwerty;
}
}
private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
if (noSettingsKey) {
// Never shows the Settings key
return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
}
if (settingsKeyEnabled) {
return KeyboardId.F2KEY_MODE_SETTINGS;
} else {
// It should be alright to fall back to the Settings key on 7-inch layouts
// even when the Settings key is not explicitly enabled.
return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
}
}
}
}

View file

@ -18,9 +18,7 @@ package com.android.inputmethod.keyboard;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import android.view.InflateException; import android.view.InflateException;
@ -65,14 +63,11 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
private InputView mCurrentInputView; private InputView mCurrentInputView;
private LatinKeyboardView mKeyboardView; private LatinKeyboardView mKeyboardView;
private LatinIME mInputMethodService; private LatinIME mInputMethodService;
private String mPackageName;
private Resources mResources; private Resources mResources;
private KeyboardState mState; private KeyboardState mState;
private KeyboardId mMainKeyboardId; private KeyboardSet mKeyboardSet;
private KeyboardId mSymbolsKeyboardId;
private KeyboardId mSymbolsShiftedKeyboardId;
private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache = private final HashMap<KeyboardId, SoftReference<LatinKeyboard>> mKeyboardCache =
new HashMap<KeyboardId, SoftReference<LatinKeyboard>>(); new HashMap<KeyboardId, SoftReference<LatinKeyboard>>();
@ -100,7 +95,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
private void initInternal(LatinIME ims, SharedPreferences prefs) { private void initInternal(LatinIME ims, SharedPreferences prefs) {
mInputMethodService = ims; mInputMethodService = ims;
mPackageName = ims.getPackageName();
mResources = ims.getResources(); mResources = ims.getResources();
mPrefs = prefs; mPrefs = prefs;
mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mSubtypeSwitcher = SubtypeSwitcher.getInstance();
@ -133,20 +127,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) { public void loadKeyboard(EditorInfo editorInfo, SettingsValues settingsValues) {
try { try {
mMainKeyboardId = getKeyboardId(editorInfo, false, false, settingsValues); mKeyboardSet = new KeyboardSet.Builder(mInputMethodService, editorInfo, settingsValues)
mSymbolsKeyboardId = getKeyboardId(editorInfo, true, false, settingsValues); .build();
mSymbolsShiftedKeyboardId = getKeyboardId(editorInfo, true, true, settingsValues);
mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols), mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols),
hasDistinctMultitouch()); hasDistinctMultitouch());
// TODO: Should get rid of this special case handling for Phone Number layouts once we // TODO: Should get rid of this special case handling for Phone Number layouts once we
// have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted // have separate layouts with unique KeyboardIds for alphabet and alphabet-shifted
// respectively. // respectively.
if (mMainKeyboardId.isPhoneKeyboard()) { if (mKeyboardSet.mAlphabetId.isPhoneKeyboard()) {
mState.onToggleAlphabetAndSymbols(); mState.onToggleAlphabetAndSymbols();
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
Log.w(TAG, "loading keyboard failed: " + mMainKeyboardId, e); Log.w(TAG, "loading keyboard failed: " + mKeyboardSet.mAlphabetId, e);
LatinImeLogger.logOnException(mMainKeyboardId.toString(), e); LatinImeLogger.logOnException(mKeyboardSet.mAlphabetId.toString(), e);
} }
} }
@ -177,6 +170,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
updateShiftState(); updateShiftState();
} }
// TODO: Move this method to KeyboardSet.
private LatinKeyboard getKeyboard(KeyboardId id) { private LatinKeyboard getKeyboard(KeyboardId id) {
final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id); final SoftReference<LatinKeyboard> ref = mKeyboardCache.get(id);
LatinKeyboard keyboard = (ref == null) ? null : ref.get(); LatinKeyboard keyboard = (ref == null) ? null : ref.get();
@ -215,55 +209,6 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
return keyboard; return keyboard;
} }
private KeyboardId getKeyboardId(EditorInfo editorInfo, final boolean isSymbols,
final boolean isShift, SettingsValues settingsValues) {
final int mode = Utils.getKeyboardMode(editorInfo);
final int xmlId;
switch (mode) {
case KeyboardId.MODE_PHONE:
xmlId = (isSymbols && isShift) ? R.xml.kbd_phone_shift : R.xml.kbd_phone;
break;
case KeyboardId.MODE_NUMBER:
xmlId = R.xml.kbd_number;
break;
default:
if (isSymbols) {
xmlId = isShift ? R.xml.kbd_symbols_shift : R.xml.kbd_symbols;
} else {
xmlId = R.xml.kbd_qwerty;
}
break;
}
final boolean settingsKeyEnabled = settingsValues.isSettingsKeyEnabled();
@SuppressWarnings("deprecation")
final boolean noMicrophone = Utils.inPrivateImeOptions(
mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, editorInfo)
|| Utils.inPrivateImeOptions(
null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo);
final boolean voiceKeyEnabled = settingsValues.isVoiceKeyEnabled(editorInfo)
&& !noMicrophone;
final boolean voiceKeyOnMain = settingsValues.isVoiceKeyOnMain();
final boolean noSettingsKey = Utils.inPrivateImeOptions(
mPackageName, LatinIME.IME_OPTION_NO_SETTINGS_KEY, editorInfo);
final boolean hasSettingsKey = settingsKeyEnabled && !noSettingsKey;
final int f2KeyMode = getF2KeyMode(settingsKeyEnabled, noSettingsKey);
final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != voiceKeyOnMain);
final boolean forceAscii = Utils.inPrivateImeOptions(
mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, editorInfo);
final boolean asciiCapable = mSubtypeSwitcher.currentSubtypeContainsExtraValueKey(
LatinIME.SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE);
final Locale locale = (forceAscii && !asciiCapable)
? Locale.US : mSubtypeSwitcher.getInputLocale();
final Configuration conf = mResources.getConfiguration();
final DisplayMetrics dm = mResources.getDisplayMetrics();
return new KeyboardId(
mResources.getResourceEntryName(xmlId), xmlId, locale, conf.orientation,
dm.widthPixels, mode, editorInfo, hasSettingsKey, f2KeyMode, noSettingsKey,
voiceKeyEnabled, hasShortcutKey);
}
public boolean isAlphabetMode() { public boolean isAlphabetMode() {
final Keyboard keyboard = getLatinKeyboard(); final Keyboard keyboard = getLatinKeyboard();
return keyboard != null && keyboard.mId.isAlphabetKeyboard(); return keyboard != null && keyboard.mId.isAlphabetKeyboard();
@ -393,19 +338,19 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
// Implements {@link KeyboardState.SwitchActions}. // Implements {@link KeyboardState.SwitchActions}.
@Override @Override
public void setSymbolsKeyboard() { public void setSymbolsKeyboard() {
setKeyboard(getKeyboard(mSymbolsKeyboardId)); setKeyboard(getKeyboard(mKeyboardSet.mSymbolsId));
} }
// Implements {@link KeyboardState.SwitchActions}. // Implements {@link KeyboardState.SwitchActions}.
@Override @Override
public void setAlphabetKeyboard() { public void setAlphabetKeyboard() {
setKeyboard(getKeyboard(mMainKeyboardId)); setKeyboard(getKeyboard(mKeyboardSet.mAlphabetId));
} }
// Implements {@link KeyboardState.SwitchActions}. // Implements {@link KeyboardState.SwitchActions}.
@Override @Override
public void setSymbolsShiftedKeyboard() { public void setSymbolsShiftedKeyboard() {
final Keyboard keyboard = getKeyboard(mSymbolsShiftedKeyboardId); final Keyboard keyboard = getKeyboard(mKeyboardSet.mSymbolsShiftedId);
setKeyboard(keyboard); setKeyboard(keyboard);
// TODO: Remove this logic once we introduce initial keyboard shift state attribute. // TODO: Remove this logic once we introduce initial keyboard shift state attribute.
// Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a. // Symbol shift keyboard may have a shift key that has a caps lock style indicator (a.k.a.
@ -518,19 +463,4 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions,
} }
} }
} }
private static int getF2KeyMode(boolean settingsKeyEnabled, boolean noSettingsKey) {
if (noSettingsKey) {
// Never shows the Settings key
return KeyboardId.F2KEY_MODE_SHORTCUT_IME;
}
if (settingsKeyEnabled) {
return KeyboardId.F2KEY_MODE_SETTINGS;
} else {
// It should be alright to fall back to the Settings key on 7-inch layouts
// even when the Settings key is not explicitly enabled.
return KeyboardId.F2KEY_MODE_SHORTCUT_IME_OR_SETTINGS;
}
}
} }