Home | History | Annotate | Download | only in openwnn
      1 /*
      2  * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package jp.co.omronsoft.openwnn;
     18 
     19 import jp.co.omronsoft.openwnn.JAJP.*;
     20 import android.inputmethodservice.InputMethodService;
     21 import android.view.WindowManager;
     22 import android.content.Context;
     23 import android.view.View;
     24 import android.view.KeyEvent;
     25 import android.view.MotionEvent;
     26 import android.content.SharedPreferences;
     27 import android.preference.PreferenceManager;
     28 
     29 import android.util.Log;
     30 import android.os.*;
     31 import android.view.inputmethod.*;
     32 import android.content.res.Configuration;
     33 import android.graphics.*;
     34 import android.graphics.drawable.*;
     35 
     36 import java.util.ArrayList;
     37 import java.util.List;
     38 
     39 import jp.co.omronsoft.openwnn.KeyAction;
     40 
     41 /**
     42  * The OpenWnn IME's base class.
     43  *
     44  * @author Copyright (C) 2009-2011 OMRON SOFTWARE CO., LTD.  All Rights Reserved.
     45  */
     46 public class OpenWnn extends InputMethodService {
     47 
     48     /** Candidate view */
     49     protected CandidatesViewManager  mCandidatesViewManager = null;
     50     /** Input view (software keyboard) */
     51     protected InputViewManager  mInputViewManager = null;
     52     /** Conversion engine */
     53     protected WnnEngine  mConverter = null;
     54     /** Pre-converter (for Romaji-to-Kana input, Hangul input, etc.) */
     55     protected LetterConverter  mPreConverter = null;
     56     /** The inputing/editing string */
     57     protected ComposingText  mComposingText = null;
     58     /** The input connection */
     59     protected InputConnection mInputConnection = null;
     60     /** Auto hide candidate view */
     61     protected boolean mAutoHideMode = true;
     62     /** Direct input mode */
     63     protected boolean mDirectInputMode = true;
     64 
     65     /** Flag for checking if the previous down key event is consumed by OpenWnn  */
     66     private boolean mConsumeDownEvent;
     67 
     68     /** for isXLarge */
     69     private static boolean mIsXLarge = false;
     70 
     71     /** TextCandidatesViewManager */
     72     protected TextCandidatesViewManager mTextCandidatesViewManager = null;
     73 
     74     /** TextCandidates1LineViewManager */
     75     protected TextCandidates1LineViewManager mTextCandidates1LineViewManager = null;
     76 
     77     /** The instance of current IME */
     78     private static OpenWnn mCurrentIme;
     79 
     80     /** KeyAction list */
     81     private List<KeyAction> KeyActionList = new ArrayList<KeyAction>();
     82 
     83     /**
     84      * Constructor
     85      */
     86     public OpenWnn() {
     87         super();
     88     }
     89 
     90     /***********************************************************************
     91      * InputMethodService
     92      **********************************************************************/
     93     /** @see android.inputmethodservice.InputMethodService#onCreate */
     94     @Override public void onCreate() {
     95         updateXLargeMode();
     96         super.onCreate();
     97 
     98         SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
     99 
    100         mCurrentIme = this;
    101 
    102 
    103         mTextCandidatesViewManager = new TextCandidatesViewManager(-1);
    104         if (isXLarge()) {
    105             mTextCandidates1LineViewManager =
    106                 new TextCandidates1LineViewManager(OpenWnnEngineJAJP.LIMIT_OF_CANDIDATES_1LINE);
    107             mCandidatesViewManager = mTextCandidates1LineViewManager;
    108         } else {
    109             mCandidatesViewManager = mTextCandidatesViewManager;
    110         }
    111 
    112         if (mConverter != null) { mConverter.init(); }
    113         if (mComposingText != null) { mComposingText.clear(); }
    114     }
    115 
    116     /** @see android.inputmethodservice.InputMethodService#onCreateCandidatesView */
    117     @Override public View onCreateCandidatesView() {
    118         if (mCandidatesViewManager != null) {
    119             WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
    120             if (isXLarge()) {
    121                 mCandidatesViewManager = mTextCandidates1LineViewManager;
    122                 mTextCandidatesViewManager.initView(this,
    123                                                         wm.getDefaultDisplay().getWidth(),
    124                                                         wm.getDefaultDisplay().getHeight());
    125             } else {
    126                 mCandidatesViewManager = mTextCandidatesViewManager;
    127             }
    128             View view = mCandidatesViewManager.initView(this,
    129                                                         wm.getDefaultDisplay().getWidth(),
    130                                                         wm.getDefaultDisplay().getHeight());
    131             mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
    132             return view;
    133         } else {
    134             return super.onCreateCandidatesView();
    135         }
    136     }
    137 
    138     /** @see android.inputmethodservice.InputMethodService#onCreateInputView */
    139     @Override public View onCreateInputView() {
    140         SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
    141 
    142 
    143         if (mInputViewManager != null) {
    144             WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
    145             return mInputViewManager.initView(this,
    146                                               wm.getDefaultDisplay().getWidth(),
    147                                               wm.getDefaultDisplay().getHeight());
    148         } else {
    149             return super.onCreateInputView();
    150         }
    151     }
    152 
    153     /** @see android.inputmethodservice.InputMethodService#onDestroy */
    154     @Override public void onDestroy() {
    155         super.onDestroy();
    156         mCurrentIme = null;
    157         close();
    158     }
    159 
    160     /** @see android.inputmethodservice.InputMethodService#onKeyDown */
    161     @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
    162         mConsumeDownEvent = onEvent(new OpenWnnEvent(event));
    163 
    164         KeyAction Keycodeinfo = new KeyAction();
    165         Keycodeinfo.mConsumeDownEvent = mConsumeDownEvent;
    166         Keycodeinfo.mKeyCode = keyCode;
    167 
    168         int cnt = KeyActionList.size();
    169         if (cnt != 0) {
    170             for (int i = 0; i < cnt; i++) {
    171                 if (KeyActionList.get(i).mKeyCode == keyCode) {
    172                     KeyActionList.remove(i);
    173                     break;
    174                 }
    175             }
    176         }
    177         KeyActionList.add(Keycodeinfo);
    178         if (!mConsumeDownEvent) {
    179             return super.onKeyDown(keyCode, event);
    180         }
    181         return mConsumeDownEvent;
    182     }
    183 
    184     /** @see android.inputmethodservice.InputMethodService#onKeyUp */
    185     @Override public boolean onKeyUp(int keyCode, KeyEvent event) {
    186         boolean ret = mConsumeDownEvent;
    187         int cnt = KeyActionList.size();
    188         for (int i = 0; i < cnt; i++) {
    189             KeyAction Keycodeinfo = KeyActionList.get(i);
    190             if (Keycodeinfo.mKeyCode == keyCode) {
    191                 ret = Keycodeinfo.mConsumeDownEvent;
    192                 KeyActionList.remove(i);
    193                 break;
    194             }
    195         }
    196         if (!ret) {
    197             ret = super.onKeyUp(keyCode, event);
    198         }else{
    199             ret = onEvent(new OpenWnnEvent(event));
    200         }
    201         return ret;
    202     }
    203 
    204     /**
    205      * Called when the key long press event occurred.
    206      *
    207      * @see android.inputmethodservice.InputMethodService#onKeyLongPress
    208      */
    209     @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    210         if (mCurrentIme == null) {
    211             Log.e("iWnn", "OpenWnn::onKeyLongPress()  Unprocessing onCreate() ");
    212             return super.onKeyLongPress(keyCode, event);
    213         }
    214 
    215         OpenWnnEvent wnnEvent = new OpenWnnEvent(event);
    216         wnnEvent.code = OpenWnnEvent.KEYLONGPRESS;
    217         return onEvent(wnnEvent);
    218     }
    219 
    220     /** @see android.inputmethodservice.InputMethodService#onStartInput */
    221     @Override public void onStartInput(EditorInfo attribute, boolean restarting) {
    222         super.onStartInput(attribute, restarting);
    223         mInputConnection = getCurrentInputConnection();
    224         if (!restarting && mComposingText != null) {
    225             mComposingText.clear();
    226         }
    227     }
    228 
    229     /** @see android.inputmethodservice.InputMethodService#onStartInputView */
    230     @Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
    231         super.onStartInputView(attribute, restarting);
    232         mInputConnection = getCurrentInputConnection();
    233 
    234         setCandidatesViewShown(false);
    235         if (mInputConnection != null) {
    236             mDirectInputMode = false;
    237             if (mConverter != null) { mConverter.init(); }
    238         } else {
    239             mDirectInputMode = true;
    240         }
    241         SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
    242         if (mCandidatesViewManager != null) { mCandidatesViewManager.setPreferences(pref);  }
    243         if (mInputViewManager != null) { mInputViewManager.setPreferences(pref, attribute);  }
    244         if (mPreConverter != null) { mPreConverter.setPreferences(pref);  }
    245         if (mConverter != null) { mConverter.setPreferences(pref);  }
    246     }
    247 
    248     /** @see android.inputmethodservice.InputMethodService#requestHideSelf */
    249     @Override public void requestHideSelf(int flag) {
    250         super.requestHideSelf(flag);
    251         if (mInputViewManager == null) {
    252             hideWindow();
    253         }
    254     }
    255 
    256     /** @see android.inputmethodservice.InputMethodService#setCandidatesViewShown */
    257     @Override public void setCandidatesViewShown(boolean shown) {
    258         super.setCandidatesViewShown(shown);
    259         if (shown) {
    260             showWindow(true);
    261         } else {
    262             if (mAutoHideMode && mInputViewManager == null) {
    263                 hideWindow();
    264             }
    265         }
    266     }
    267 
    268     /** @see android.inputmethodservice.InputMethodService#hideWindow */
    269     @Override public void hideWindow() {
    270         super.hideWindow();
    271         mDirectInputMode = true;
    272         hideStatusIcon();
    273     }
    274     /** @see android.inputmethodservice.InputMethodService#onComputeInsets */
    275     @Override public void onComputeInsets(InputMethodService.Insets outInsets) {
    276         super.onComputeInsets(outInsets);
    277         outInsets.contentTopInsets = outInsets.visibleTopInsets;
    278     }
    279 
    280 
    281     /**********************************************************************
    282      * OpenWnn
    283      **********************************************************************/
    284     /**
    285      * Process an event.
    286      *
    287      * @param  ev  An event
    288      * @return  {@code true} if the event is processed in this method; {@code false} if not.
    289      */
    290     public boolean onEvent(OpenWnnEvent ev) {
    291         return false;
    292     }
    293 
    294     /**
    295      * Search a character for toggle input.
    296      *
    297      * @param prevChar     The character input previous
    298      * @param toggleTable  Toggle table
    299      * @param reverse      {@code false} if toggle direction is forward, {@code true} if toggle direction is backward
    300      * @return          A character ({@code null} if no character is found)
    301      */
    302     protected String searchToggleCharacter(String prevChar, String[] toggleTable, boolean reverse) {
    303         for (int i = 0; i < toggleTable.length; i++) {
    304             if (prevChar.equals(toggleTable[i])) {
    305                 if (reverse) {
    306                     i--;
    307                     if (i < 0) {
    308                         return toggleTable[toggleTable.length - 1];
    309                     } else {
    310                         return toggleTable[i];
    311                     }
    312                 } else {
    313                     i++;
    314                     if (i == toggleTable.length) {
    315                         return toggleTable[0];
    316                     } else {
    317                         return toggleTable[i];
    318                     }
    319                 }
    320             }
    321         }
    322         return null;
    323     }
    324 
    325     /**
    326      * Processing of resource open when IME ends.
    327      */
    328     protected void close() {
    329         if (mConverter != null) { mConverter.close(); }
    330     }
    331 
    332     /**
    333      * Whether the x large mode.
    334      *
    335      * @return      {@code true} if x large; {@code false} if not x large.
    336      */
    337     public static boolean isXLarge() {
    338         return mIsXLarge;
    339     }
    340 
    341     /**
    342      * Update the x large mode.
    343      */
    344     public void updateXLargeMode() {
    345         mIsXLarge = ((getResources().getConfiguration().screenLayout &
    346                       Configuration.SCREENLAYOUT_SIZE_MASK)
    347                       == Configuration.SCREENLAYOUT_SIZE_XLARGE);
    348     }
    349 
    350     /**
    351      * Get the instance of current IME.
    352      *
    353      * @return the instance of current IME, See {@link jp.co.omronsoft.openwnn.OpenWnn}
    354      */
    355     public static OpenWnn getCurrentIme() {
    356         return mCurrentIme;
    357     }
    358 
    359     /**
    360      * Check through key code in IME.
    361      *
    362      * @param keyCode  check key code.
    363      * @return {@code true} if through key code; {@code false} otherwise.
    364      */
    365     protected boolean isThroughKeyCode(int keyCode) {
    366         boolean result;
    367         switch (keyCode) {
    368         case KeyEvent.KEYCODE_CALL:
    369         case KeyEvent.KEYCODE_VOLUME_DOWN:
    370         case KeyEvent.KEYCODE_VOLUME_UP:
    371         case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
    372         case KeyEvent.KEYCODE_MEDIA_NEXT:
    373         case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
    374         case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
    375         case KeyEvent.KEYCODE_MEDIA_REWIND:
    376         case KeyEvent.KEYCODE_MEDIA_STOP:
    377         case KeyEvent.KEYCODE_MUTE:
    378         case KeyEvent.KEYCODE_HEADSETHOOK:
    379         case KeyEvent.KEYCODE_VOLUME_MUTE:
    380         case KeyEvent.KEYCODE_MEDIA_CLOSE:
    381         case KeyEvent.KEYCODE_MEDIA_EJECT:
    382         case KeyEvent.KEYCODE_MEDIA_PAUSE:
    383         case KeyEvent.KEYCODE_MEDIA_PLAY:
    384         case KeyEvent.KEYCODE_MEDIA_RECORD:
    385         case KeyEvent.KEYCODE_MANNER_MODE:
    386             result = true;
    387             break;
    388 
    389         default:
    390             result = false;
    391             break;
    392 
    393         }
    394         return result;
    395     }
    396 
    397     /**
    398      * Check ten-key code.
    399      *
    400      * @param keyCode  check key code.
    401      * @return {@code true} if ten-key code; {@code false} not ten-key code.
    402      */
    403     protected boolean isTenKeyCode(int keyCode) {
    404         boolean result = false;
    405         switch (keyCode) {
    406         case KeyEvent.KEYCODE_NUMPAD_0:
    407         case KeyEvent.KEYCODE_NUMPAD_1:
    408         case KeyEvent.KEYCODE_NUMPAD_2:
    409         case KeyEvent.KEYCODE_NUMPAD_3:
    410         case KeyEvent.KEYCODE_NUMPAD_4:
    411         case KeyEvent.KEYCODE_NUMPAD_5:
    412         case KeyEvent.KEYCODE_NUMPAD_6:
    413         case KeyEvent.KEYCODE_NUMPAD_7:
    414         case KeyEvent.KEYCODE_NUMPAD_8:
    415         case KeyEvent.KEYCODE_NUMPAD_9:
    416         case KeyEvent.KEYCODE_NUMPAD_DOT:
    417             result = true;
    418             break;
    419 
    420         default:
    421             break;
    422 
    423         }
    424         return result;
    425     }
    426 }
    427