/*
* Copyright (C) 2008 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 net.toload.main.hd;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.toload.main.hd.R;
import net.toload.main.hd.global.ImObj;
import net.toload.main.hd.global.KeyboardObj;
import net.toload.main.hd.global.LIMEPreferenceManager;
import net.toload.main.hd.keyboard.LIMEKeyboard;
import net.toload.main.hd.keyboard.LIMEKeyboardView;
import android.util.Log;
public class LIMEKeyboardSwitcher {
static final boolean DEBUG = false;
static final String TAG = "LIMEKeyboardSwitcher";
public static final int MODE_TEXT = 1;
public static final int MODE_SYMBOLS = 2;
public static final int MODE_PHONE = 3;
public static final int MODE_URL = 4;
public static final int MODE_EMAIL = 5;
public static final int MODE_IM = 6;
public static final int MODE_TEXT_QWERTY = 0;
public static final int MODE_TEXT_ALPHA = 1;
public static final int MODE_TEXT_COUNT = 2;
public static final int KEYBOARDMODE_NORMAL = R.id.mode_normal;
public static final int KEYBOARDMODE_URL = R.id.mode_url;
public static final int KEYBOARDMODE_EMAIL = R.id.mode_email;
public static final int KEYBOARDMODE_IM = R.id.mode_im;
public static final int IM_KEYBOARD = 0;
private static final int SYMBOLS_MODE_STATE_NONE = 0;
private static final int SYMBOLS_MODE_STATE_BEGIN = 1;
private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
LIMEKeyboardView mInputView;
LIMEService mContext;
//private KeyboardId mCurrentId;
private Map<KeyboardId, LIMEKeyboard> mKeyboards;
private int mMode = KEYBOARDMODE_NORMAL;
//private int mChnMode = MODE_TEXT_DEFAULT;
//private int mEngMode = MODE_TEXT;
private int mImeOptions;
private int mTextMode = MODE_TEXT_QWERTY;
private LIMEPreferenceManager mLIMEPref;
private boolean mIsShifted;
private boolean mIsSymbols;
private boolean mIsChinese=true;
private boolean mIsAlphabet=false;
private boolean mPreferSymbols;
private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
private int mLastDisplayWidth;
private String imtype = null;
private HashMap<String, KeyboardObj> kbHm;
private HashMap<String, String> imHm;
private static List<String> mActivatedIMList;
//private static List<String> mActiveKeyboardNames;
private static List<String> mActivatedIMShortnameList;
private float mKeySizeScale=1;
public LIMEKeyboardSwitcher(LIMEService context) {
mContext = context;
mLIMEPref = new LIMEPreferenceManager(context);
mKeyboards = new HashMap<KeyboardId, LIMEKeyboard>();
mKeySizeScale = mLIMEPref.getFontSize();
}
public int getKeyboardSize(){
if(kbHm != null){
return kbHm.size();
}
return 0;
}
public void setKeyboardList(List<KeyboardObj> list){
if(list==null || (list!=null&& list.size()==0)) return; //Jeremy '12,4,10 avoid fc when database is locked.
kbHm = new HashMap<String, KeyboardObj>();
for(KeyboardObj o : list){
kbHm.put(o.getCode(), o);
}
}
public String getImKeyboard(String code){
if(imHm != null && imHm.get(code) != null){
return imHm.get(code);
}
return "";
}
public void setImList(List<ImObj> list){
if(list==null || (list!=null&& list.size()==0)) return; //Jeremy '12,4,10 avoid fc when database is locked.
imHm = new HashMap<String, String>();
for(ImObj o : list){
imHm.put(o.getCode(), o.getKeyboard());
}
}
public void setActivatedIMList(List<String> codes, List<String> names, List<String> shortnames){
if(DEBUG) Log.i(TAG,"setActiveKeyboardList()");
if(codes.equals(mActivatedIMList) && shortnames.equals(mActivatedIMShortnameList)) return;
mActivatedIMList = codes;
//mActiveKeyboardNames = names;
mActivatedIMShortnameList = shortnames;
}
public List<String> getActivatedIMShortnameList(){
return mActivatedIMShortnameList;
}
public String getActiveIMShortname(){
if(DEBUG) Log.i(TAG,"getCurrentActiveKeyboardShortName() current IM:"+ imtype);
for (int i = 0; i < mActivatedIMList.size(); i++) {
if (imtype.equals(mActivatedIMList.get(i))) {
if(DEBUG)Log.i(TAG,"getCurrentActiveKeyboardShortName()="+ mActivatedIMShortnameList.get(i));
return mActivatedIMShortnameList.get(i);
}
}
return "";
}
public String getNextActivatedIMShortname(){
for (int i = 0; i < mActivatedIMList.size(); i++) {
if (imtype.equals(mActivatedIMList.get(i))) {
if(i==mActivatedIMList.size()-1)
return mActivatedIMShortnameList.get(0);
else return mActivatedIMShortnameList.get(i+1);
}
}
return "";
}
public String getPrevActivatedIMShortname(){
for (int i = 0; i < mActivatedIMList.size(); i++) {
if (imtype.equals(mActivatedIMList.get(i))) {
if(i==0) return mActivatedIMShortnameList.get(mActivatedIMList.size()-1);
else return mActivatedIMShortnameList.get(i-1);
}
}
return "";
}
public void setInputView(LIMEKeyboardView inputView) {
mInputView = inputView;
}
public void clearKeyboards(){
if(DEBUG) Log.i(TAG, "clearkeyboards()");
if(mKeyboards != null){
mKeyboards.clear();
}
}
public void makeKeyboards(boolean forceCreate) {
if(DEBUG)
Log.i(TAG, "makekeyboards(): forcereCreate:" + forceCreate);
if (forceCreate) mKeyboards.clear();
// Configuration change is coming after the keyboard gets recreated. So don't rely on that.
// If keyboards have already been made, check if we have a screen width change and
// create the keyboard layouts again at the correct orientation
int displayWidth = mContext.getMaxWidth();
if (displayWidth != mLastDisplayWidth) {
mLastDisplayWidth = displayWidth;
mKeyboards.clear();
}
}
/**
* Represents the parameters necessary to construct a new LatinKeyboard,
* which also serve as a unique identifier for each keyboard type.
*/
private static class KeyboardId {
public int mXml;
public int mMode;
public boolean mEnableShiftLock;
public KeyboardId(int xml, int mode, boolean enableShiftLock) {
this.mXml = xml;
this.mMode = mode;
this.mEnableShiftLock = enableShiftLock;
}
public KeyboardId(int xml) {
this(xml, 0, false);
}
public boolean equals(Object other) {
return other instanceof KeyboardId && equals((KeyboardId) other);
}
public boolean equals(KeyboardId other) {
return other.mXml == this.mXml && other.mMode == this.mMode;
}
public int hashCode() {
return (mXml + 1) * (mMode + 1) * (mEnableShiftLock ? 2 : 1);
}
}
private LIMEKeyboard getKeyboard(KeyboardId id) {
if(DEBUG)
Log.i(TAG,"getKeyboard()");
//Jeremy '11,9,3
if(mLIMEPref.getKeyboardSize()!=mKeySizeScale){
clearKeyboards();
mKeySizeScale = mLIMEPref.getKeyboardSize();
}
if(id != null){
if (!mKeyboards.containsKey(id)) {
LIMEKeyboard keyboard = new LIMEKeyboard(
mContext, id.mXml, id.mMode, mKeySizeScale,
mLIMEPref.getShowArrowKeys(), //Jeremy '12,5,21 add the show arrow keys option
mLIMEPref.getSplitKeyboard() //Jeremy '12,5,27 add the split keyboard option
);
keyboard.setKeyboardSwitcher(this);
if (id.mEnableShiftLock) {
keyboard.enableShiftLock();
}
mKeyboards.put(id, keyboard);
}
return mKeyboards.get(id);
}
return null;
}
private int getKeyboardXMLID(String value){
int result = mContext.getResources().getIdentifier(value, "xml", mContext.getPackageName());
return result;
}
public void setKeyboardMode(String code, int mode, int imeOptions, boolean isIm, boolean isSymbol, boolean isShift) {
if(DEBUG){
Log.i(TAG,"KBMODE code:"+code);
Log.i(TAG,"KBMODE mode:"+mode);
Log.i(TAG,"KBMODE imOphtions:"+imeOptions);
Log.i(TAG,"KBMODE isIM:"+isIm);
Log.i(TAG,"KBMODE isSymbol:"+isSymbol);
Log.i(TAG,"KBMODE isShift:"+isShift);
}
imtype = code;
// Jeremy '11,6,2. Has to preserve these options for toggle keyboard controls.
mImeOptions = imeOptions;
mIsSymbols = isSymbol;
mIsShifted = isShift;
if(mode!=0) mMode = mode;
String imcode = "";
if(!code.equals("wb") && !code.equals("hs") ){
if(imHm != null) imcode = imHm.get(code);
}else{
imcode = code;
}
KeyboardObj kobj=null;
if(imcode == null || imcode.equals("")|| imcode.equals("custom")){
imcode = "lime";
if(kbHm!=null) kobj=kbHm.get(imcode);
}else if(imcode.equals("wb")){
// Art 28/Sep/2011 Force WB to use it special design keyboard layout
kobj = new KeyboardObj();
kobj.setCode("wb");
kobj.setName("筆順五碼");
kobj.setDescription("筆順五碼");
kobj.setType("phone");
kobj.setImage("wb_keyboard_preview");
kobj.setImkb("lime_wb");
kobj.setImshiftkb("lime_wb");
kobj.setEngkb("lime_abc");
kobj.setEngshiftkb("lime_abc_shift");
kobj.setSymbolkb("symbols");
kobj.setSymbolshiftkb("symbols_shift");
}else if(imcode.equals("hs")){
// Art 7/Feb/2012 HS Input Method
kobj = new KeyboardObj();
kobj.setCode("hs");
kobj.setName("華象直覺");
kobj.setDescription("華象直覺");
kobj.setType("phone");
kobj.setImage("hs_keyboard_preview");
kobj.setImkb("lime_hs");
kobj.setImshiftkb("lime_hs_shift");
kobj.setEngkb("lime_abc");
kobj.setEngshiftkb("lime_abc_shift");
kobj.setSymbolkb("symbols");
kobj.setSymbolshiftkb("symbols_shift");
}else{
if(kbHm!=null) kobj=kbHm.get(imcode);
}
KeyboardId kid = null;
if(kobj != null){
mIsChinese = false;
if(isSymbol){
if(isShift){
//Log.i("ART","KBMODE ->: " + kobj.getExtendedshiftkb());
kid = new KeyboardId(getKeyboardXMLID(kobj.getSymbolshiftkb()), 0, true );
}else{
//Log.i("ART","KBMODE ->: " + kobj.getExtendedkb());
kid = new KeyboardId(getKeyboardXMLID(kobj.getSymbolkb()), 0, true );
}
}else{
switch (mode) {
case MODE_PHONE:
//Log.i("ART","KBMODE ->: phone");
kid = new KeyboardId(getKeyboardXMLID("phone_number"));
break;
case MODE_URL:
//Log.i("ART","KBMODE ->: url");
if(!imcode.equals("wb")){
if(mLIMEPref.getShowNumberRowInEnglish()){
if(isShift)
kid = new KeyboardId(getKeyboardXMLID("lime_english_number_shift"), KEYBOARDMODE_URL, true);
else
kid = new KeyboardId(getKeyboardXMLID("lime_english_number"), KEYBOARDMODE_URL, true);
}else{
if(isShift)
kid = new KeyboardId(getKeyboardXMLID("lime_english_shift"), KEYBOARDMODE_URL, true);
else
kid = new KeyboardId(getKeyboardXMLID("lime_english"), KEYBOARDMODE_URL, true);
}
}else{
if(isShift)
kid = new KeyboardId(getKeyboardXMLID("lime_abc_shift"), KEYBOARDMODE_URL, true);
else
kid = new KeyboardId(getKeyboardXMLID("lime_abc"), KEYBOARDMODE_URL, true);
}
break;
case MODE_EMAIL:
//Log.i("ART","KBMODE ->: email");
if(!imcode.equals("wb")){
if(mLIMEPref.getShowNumberRowInEnglish()){
if(isShift)
kid = new KeyboardId(getKeyboardXMLID("lime_english_number_shift"), KEYBOARDMODE_EMAIL, true);
else
kid = new KeyboardId(getKeyboardXMLID("lime_english_number"), KEYBOARDMODE_EMAIL, true);
}else{
if(isShift)
kid = new KeyboardId(getKeyboardXMLID("lime_english_shift"), KEYBOARDMODE_EMAIL, true);
else
kid = new KeyboardId(getKeyboardXMLID("lime_english"), KEYBOARDMODE_EMAIL, true);
}
}else{
if(isShift)
kid = new KeyboardId(getKeyboardXMLID("lime_abc_shift"), KEYBOARDMODE_URL, true);
else
kid = new KeyboardId(getKeyboardXMLID("lime_abc"), KEYBOARDMODE_URL, true);
}
break;
default:
if(isIm){ // Chinese IM keyboards
if(isShift){
//Log.i("ART","KBMODE ->: " + kobj.getImshiftkb());
kid = new KeyboardId(getKeyboardXMLID(kobj.getImshiftkb()), KEYBOARDMODE_NORMAL, true );
}else{
//Log.i("ART","KBMODE ->: " + kobj.getImkb());
kid = new KeyboardId(getKeyboardXMLID(kobj.getImkb()), KEYBOARDMODE_NORMAL, true );
}
mIsChinese = true;
}else {//if(!isIm){ //English normal keyboard
if(!imcode.equals("wb")){
if(isShift){
//Log.i("ART","KBMODE ->: " + kobj.getEngshiftkb());
kid = new KeyboardId(
getKeyboardXMLID(kobj.getEngshiftkb(mLIMEPref.getShowNumberRowInEnglish())),
KEYBOARDMODE_NORMAL, true );
}else{
//Log.i("ART","KBMODE ->: " + kobj.getEngkb());
kid = new KeyboardId(
getKeyboardXMLID(kobj.getEngkb(mLIMEPref.getShowNumberRowInEnglish())),
KEYBOARDMODE_NORMAL, true );
}
}else{
if(isShift){
//Log.i("ART","KBMODE ->: " + kobj.getEngshiftkb());
kid = new KeyboardId(
getKeyboardXMLID(kobj.getEngshiftkb()),
KEYBOARDMODE_NORMAL, true );
}else{
//Log.i("ART","KBMODE ->: " + kobj.getEngkb());
kid = new KeyboardId(
getKeyboardXMLID(kobj.getEngkb()),
KEYBOARDMODE_NORMAL, true );
}
}
}
}
}
if(mInputView == null) return;
LIMEKeyboard keyboard = getKeyboard(kid);
// mCurrentId = kid;
mInputView.setKeyboard(keyboard);
keyboard.setShiftLocked(keyboard.isShiftLocked());
keyboard.setShifted(mIsShifted);
mInputView.setKeyboard(mInputView.getKeyboard()); //instead of invalidateAllKeys();
keyboard.setImeOptions(mContext.getResources(), mMode, imeOptions);
}
}
public int getKeyboardMode() {
return mMode;
}
public boolean isTextMode() {
return mMode == MODE_TEXT;
}
public int getTextMode() {
return mTextMode;
}
public int getTextModeCount() {
return MODE_TEXT_COUNT;
}
public boolean isAlphabetMode() {
return mIsAlphabet;
}
public void toggleShift() {
if(DEBUG) Log.i("LIMEKeyboardSwicher:toggeleshift()","KBMODE mode:"+mMode);
mIsShifted= !mIsShifted;
if(mIsChinese)
this.setKeyboardMode(imtype, 0, mImeOptions, true, mIsSymbols, mIsShifted);
else{
this.setKeyboardMode(imtype, mMode, mImeOptions, false, mIsSymbols, mIsShifted);
}
}
public void setIsChinese(boolean value){
mIsChinese = value;
}
public void setIsSymbols(boolean value){
mIsSymbols = value;
}
public void toggleChinese() {
mIsChinese = !mIsChinese;
if(mIsChinese){
this.setKeyboardMode(imtype, 0, mImeOptions, true, mIsSymbols, mIsShifted);
}else{
this.setKeyboardMode(imtype, mMode, mImeOptions, false, mIsSymbols, mIsShifted);
}
}
public void toggleSymbols() {
mIsSymbols = !mIsSymbols;
mIsShifted = false;
if(mIsChinese)
this.setKeyboardMode(imtype, 0, mImeOptions, true, mIsSymbols, mIsShifted);
else
this.setKeyboardMode(imtype, mMode, mImeOptions, false, mIsSymbols, mIsShifted);
if (mIsSymbols && !mPreferSymbols) {
mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN;
} else {
mSymbolsModeState = SYMBOLS_MODE_STATE_NONE;
}
}
public boolean isChinese(){
return mIsChinese;
}
public boolean isSymbols(){
return mIsSymbols;
}
public boolean isShifted(){
return mIsShifted;
}
/**
* Updates state machine to figure out when to automatically switch back to alpha mode.
* Returns true if the keyboard needs to switch back
*/
public boolean onKey(int key) {
// Switch back to alpha mode if user types one or more non-space/enter characters
// followed by a space/enter
switch (mSymbolsModeState) {
case SYMBOLS_MODE_STATE_BEGIN:
if (key != LIMEService.MY_KEYCODE_SPACE && key != LIMEService.MY_KEYCODE_ENTER && key > 0) {
mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL;
}
break;
case SYMBOLS_MODE_STATE_SYMBOL:
if (key == LIMEService.MY_KEYCODE_ENTER || key == LIMEService.MY_KEYCODE_SPACE) return true;
break;
}
return false;
}
public static LIMEKeyboardSwitcher getInstance() {
// TODO Auto-generated method stub
return null;
}
}