Java程序  |  427行  |  14.5 KB

/*
 * 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<KeyAction> KeyActionList = new ArrayList<KeyAction>();

    /**
     * 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;
    }
}