/* * Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd. * * 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 jp.co.omronsoft.openwnn; import jp.co.omronsoft.openwnn.JAJP.*; import android.inputmethodservice.InputMethodService; import android.view.WindowManager; import android.content.Context; import android.view.View; import android.view.KeyEvent; import android.view.MotionEvent; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; import android.os.*; import android.view.inputmethod.*; import android.content.res.Configuration; import android.graphics.*; import android.graphics.drawable.*; import java.util.ArrayList; import java.util.List; import jp.co.omronsoft.openwnn.KeyAction; /** * The OpenWnn IME's base class. * * @author Copyright (C) 2009-2011 OMRON SOFTWARE CO., LTD. All Rights Reserved. */ public class OpenWnn extends InputMethodService { /** Candidate view */ protected CandidatesViewManager mCandidatesViewManager = null; /** Input view (software keyboard) */ protected InputViewManager mInputViewManager = null; /** Conversion engine */ protected WnnEngine mConverter = null; /** Pre-converter (for Romaji-to-Kana input, Hangul input, etc.) */ protected LetterConverter mPreConverter = null; /** The inputing/editing string */ protected ComposingText mComposingText = null; /** The input connection */ protected InputConnection mInputConnection = null; /** Auto hide candidate view */ protected boolean mAutoHideMode = true; /** Direct input mode */ protected boolean mDirectInputMode = true; /** Flag for checking if the previous down key event is consumed by OpenWnn */ private boolean mConsumeDownEvent; /** for isXLarge */ private static boolean mIsXLarge = false; /** TextCandidatesViewManager */ protected TextCandidatesViewManager mTextCandidatesViewManager = null; /** TextCandidates1LineViewManager */ protected TextCandidates1LineViewManager mTextCandidates1LineViewManager = null; /** The instance of current IME */ private static OpenWnn mCurrentIme; /** KeyAction list */ private List KeyActionList = new ArrayList(); /** * Constructor */ public OpenWnn() { super(); } /*********************************************************************** * InputMethodService **********************************************************************/ /** @see android.inputmethodservice.InputMethodService#onCreate */ @Override public void onCreate() { updateXLargeMode(); super.onCreate(); SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); mCurrentIme = this; mTextCandidatesViewManager = new TextCandidatesViewManager(-1); if (isXLarge()) { mTextCandidates1LineViewManager = new TextCandidates1LineViewManager(OpenWnnEngineJAJP.LIMIT_OF_CANDIDATES_1LINE); mCandidatesViewManager = mTextCandidates1LineViewManager; } else { mCandidatesViewManager = mTextCandidatesViewManager; } if (mConverter != null) { mConverter.init(); } if (mComposingText != null) { mComposingText.clear(); } } /** @see android.inputmethodservice.InputMethodService#onCreateCandidatesView */ @Override public View onCreateCandidatesView() { if (mCandidatesViewManager != null) { WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); if (isXLarge()) { mCandidatesViewManager = mTextCandidates1LineViewManager; mTextCandidatesViewManager.initView(this, wm.getDefaultDisplay().getWidth(), wm.getDefaultDisplay().getHeight()); } else { mCandidatesViewManager = mTextCandidatesViewManager; } View view = mCandidatesViewManager.initView(this, wm.getDefaultDisplay().getWidth(), wm.getDefaultDisplay().getHeight()); mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL); return view; } else { return super.onCreateCandidatesView(); } } /** @see android.inputmethodservice.InputMethodService#onCreateInputView */ @Override public View onCreateInputView() { SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); if (mInputViewManager != null) { WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE); return mInputViewManager.initView(this, wm.getDefaultDisplay().getWidth(), wm.getDefaultDisplay().getHeight()); } else { return super.onCreateInputView(); } } /** @see android.inputmethodservice.InputMethodService#onDestroy */ @Override public void onDestroy() { super.onDestroy(); mCurrentIme = null; close(); } /** @see android.inputmethodservice.InputMethodService#onKeyDown */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { mConsumeDownEvent = onEvent(new OpenWnnEvent(event)); KeyAction Keycodeinfo = new KeyAction(); Keycodeinfo.mConsumeDownEvent = mConsumeDownEvent; Keycodeinfo.mKeyCode = keyCode; int cnt = KeyActionList.size(); if (cnt != 0) { for (int i = 0; i < cnt; i++) { if (KeyActionList.get(i).mKeyCode == keyCode) { KeyActionList.remove(i); break; } } } KeyActionList.add(Keycodeinfo); if (!mConsumeDownEvent) { return super.onKeyDown(keyCode, event); } return mConsumeDownEvent; } /** @see android.inputmethodservice.InputMethodService#onKeyUp */ @Override public boolean onKeyUp(int keyCode, KeyEvent event) { boolean ret = mConsumeDownEvent; int cnt = KeyActionList.size(); for (int i = 0; i < cnt; i++) { KeyAction Keycodeinfo = KeyActionList.get(i); if (Keycodeinfo.mKeyCode == keyCode) { ret = Keycodeinfo.mConsumeDownEvent; KeyActionList.remove(i); break; } } if (!ret) { ret = super.onKeyUp(keyCode, event); }else{ ret = onEvent(new OpenWnnEvent(event)); } return ret; } /** * Called when the key long press event occurred. * * @see android.inputmethodservice.InputMethodService#onKeyLongPress */ @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (mCurrentIme == null) { Log.e("iWnn", "OpenWnn::onKeyLongPress() Unprocessing onCreate() "); return super.onKeyLongPress(keyCode, event); } OpenWnnEvent wnnEvent = new OpenWnnEvent(event); wnnEvent.code = OpenWnnEvent.KEYLONGPRESS; return onEvent(wnnEvent); } /** @see android.inputmethodservice.InputMethodService#onStartInput */ @Override public void onStartInput(EditorInfo attribute, boolean restarting) { super.onStartInput(attribute, restarting); mInputConnection = getCurrentInputConnection(); if (!restarting && mComposingText != null) { mComposingText.clear(); } } /** @see android.inputmethodservice.InputMethodService#onStartInputView */ @Override public void onStartInputView(EditorInfo attribute, boolean restarting) { super.onStartInputView(attribute, restarting); mInputConnection = getCurrentInputConnection(); setCandidatesViewShown(false); if (mInputConnection != null) { mDirectInputMode = false; if (mConverter != null) { mConverter.init(); } } else { mDirectInputMode = true; } SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); if (mCandidatesViewManager != null) { mCandidatesViewManager.setPreferences(pref); } if (mInputViewManager != null) { mInputViewManager.setPreferences(pref, attribute); } if (mPreConverter != null) { mPreConverter.setPreferences(pref); } if (mConverter != null) { mConverter.setPreferences(pref); } } /** @see android.inputmethodservice.InputMethodService#requestHideSelf */ @Override public void requestHideSelf(int flag) { super.requestHideSelf(flag); if (mInputViewManager == null) { hideWindow(); } } /** @see android.inputmethodservice.InputMethodService#setCandidatesViewShown */ @Override public void setCandidatesViewShown(boolean shown) { super.setCandidatesViewShown(shown); if (shown) { showWindow(true); } else { if (mAutoHideMode && mInputViewManager == null) { hideWindow(); } } } /** @see android.inputmethodservice.InputMethodService#hideWindow */ @Override public void hideWindow() { super.hideWindow(); mDirectInputMode = true; hideStatusIcon(); } /** @see android.inputmethodservice.InputMethodService#onComputeInsets */ @Override public void onComputeInsets(InputMethodService.Insets outInsets) { super.onComputeInsets(outInsets); outInsets.contentTopInsets = outInsets.visibleTopInsets; } /********************************************************************** * OpenWnn **********************************************************************/ /** * Process an event. * * @param ev An event * @return {@code true} if the event is processed in this method; {@code false} if not. */ public boolean onEvent(OpenWnnEvent ev) { return false; } /** * Search a character for toggle input. * * @param prevChar The character input previous * @param toggleTable Toggle table * @param reverse {@code false} if toggle direction is forward, {@code true} if toggle direction is backward * @return A character ({@code null} if no character is found) */ protected String searchToggleCharacter(String prevChar, String[] toggleTable, boolean reverse) { for (int i = 0; i < toggleTable.length; i++) { if (prevChar.equals(toggleTable[i])) { if (reverse) { i--; if (i < 0) { return toggleTable[toggleTable.length - 1]; } else { return toggleTable[i]; } } else { i++; if (i == toggleTable.length) { return toggleTable[0]; } else { return toggleTable[i]; } } } } return null; } /** * Processing of resource open when IME ends. */ protected void close() { if (mConverter != null) { mConverter.close(); } } /** * Whether the x large mode. * * @return {@code true} if x large; {@code false} if not x large. */ public static boolean isXLarge() { return mIsXLarge; } /** * Update the x large mode. */ public void updateXLargeMode() { mIsXLarge = ((getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE); } /** * Get the instance of current IME. * * @return the instance of current IME, See {@link jp.co.omronsoft.openwnn.OpenWnn} */ public static OpenWnn getCurrentIme() { return mCurrentIme; } /** * Check through key code in IME. * * @param keyCode check key code. * @return {@code true} if through key code; {@code false} otherwise. */ protected boolean isThroughKeyCode(int keyCode) { boolean result; switch (keyCode) { case KeyEvent.KEYCODE_CALL: case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: case KeyEvent.KEYCODE_MEDIA_NEXT: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: case KeyEvent.KEYCODE_MEDIA_PREVIOUS: case KeyEvent.KEYCODE_MEDIA_REWIND: case KeyEvent.KEYCODE_MEDIA_STOP: case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_VOLUME_MUTE: case KeyEvent.KEYCODE_MEDIA_CLOSE: case KeyEvent.KEYCODE_MEDIA_EJECT: case KeyEvent.KEYCODE_MEDIA_PAUSE: case KeyEvent.KEYCODE_MEDIA_PLAY: case KeyEvent.KEYCODE_MEDIA_RECORD: case KeyEvent.KEYCODE_MANNER_MODE: result = true; break; default: result = false; break; } return result; } /** * Check ten-key code. * * @param keyCode check key code. * @return {@code true} if ten-key code; {@code false} not ten-key code. */ protected boolean isTenKeyCode(int keyCode) { boolean result = false; switch (keyCode) { case KeyEvent.KEYCODE_NUMPAD_0: case KeyEvent.KEYCODE_NUMPAD_1: case KeyEvent.KEYCODE_NUMPAD_2: case KeyEvent.KEYCODE_NUMPAD_3: case KeyEvent.KEYCODE_NUMPAD_4: case KeyEvent.KEYCODE_NUMPAD_5: case KeyEvent.KEYCODE_NUMPAD_6: case KeyEvent.KEYCODE_NUMPAD_7: case KeyEvent.KEYCODE_NUMPAD_8: case KeyEvent.KEYCODE_NUMPAD_9: case KeyEvent.KEYCODE_NUMPAD_DOT: result = true; break; default: break; } return result; } }