package com.himamis.retex.editor.android.event; import android.os.Build; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; import com.himamis.retex.editor.android.FormulaEditor; import com.himamis.retex.editor.share.event.KeyListener; public class KeyListenerAdapter implements View.OnKeyListener { private KeyListener mKeyListener; private FormulaEditor mFormulaEditor; public KeyListenerAdapter(KeyListener keyListener, FormulaEditor formulaEditor) { mKeyListener = keyListener; mFormulaEditor = formulaEditor; } @Override public boolean onKey(View v, int keyCode, KeyEvent event) { switch (event.getAction()) { case KeyEvent.ACTION_DOWN: com.himamis.retex.editor.share.event.KeyEvent wrappedEvent = wrapEvent(event); boolean handled = mKeyListener.onKeyPressed(wrappedEvent); return handled; case KeyEvent.ACTION_UP: case KeyEvent.ACTION_MULTIPLE: if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) { mFormulaEditor.onEnter(); return true; } wrappedEvent = wrapEvent(event); boolean ret = mKeyListener.onKeyReleased(wrappedEvent); char unicodeChar = wrappedEvent.getUnicodeKeyChar(); if (unicodeChar != '\0') { handled = mKeyListener.onKeyTyped(wrappedEvent); ret |= handled; mFormulaEditor.afterKeyTyped(wrappedEvent); } return ret; default: return false; } } private static com.himamis.retex.editor.share.event.KeyEvent wrapEvent(KeyEvent keyEvent) { int keyCode = getKeyCode(keyEvent.getKeyCode()); char charCode = getCharCode(keyEvent); int modifiers = getModifiers(keyEvent); int action = getAction(keyEvent); return new com.himamis.retex.editor.share.event.KeyEvent(keyCode, modifiers, charCode, action); } private static int getKeyCode(int nativeKeyCode) { switch (nativeKeyCode) { case KeyEvent.KEYCODE_DEL: return com.himamis.retex.editor.share.event.KeyEvent.VK_BACK_SPACE; case KeyEvent.KEYCODE_DPAD_LEFT: return com.himamis.retex.editor.share.event.KeyEvent.VK_LEFT; case KeyEvent.KEYCODE_DPAD_RIGHT: return com.himamis.retex.editor.share.event.KeyEvent.VK_RIGHT; case KeyEvent.KEYCODE_DPAD_UP: return com.himamis.retex.editor.share.event.KeyEvent.VK_UP; case KeyEvent.KEYCODE_DPAD_DOWN: return com.himamis.retex.editor.share.event.KeyEvent.VK_DOWN; case KeyEvent.KEYCODE_ENTER: return com.himamis.retex.editor.share.event.KeyEvent.VK_ENTER; } return 0; } private static int getModifiers(KeyEvent keyEvent) { if (Build.VERSION.SDK_INT >= 13) { // TODO use the same modifiers as in natur/cuni... KeyEvent return keyEvent.getModifiers(); } // TODO ? return 0; } private static char getCharCode(KeyEvent keyEvent) { int unicodeChar = keyEvent.getUnicodeChar(); if (keyEvent.getAction() == KeyEvent.ACTION_MULTIPLE && keyEvent.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN) { // return the first character return keyEvent.getCharacters().charAt(0); } else if ((unicodeChar & KeyCharacterMap.COMBINING_ACCENT) != 0 || (unicodeChar == 0)) { return '\0'; } else { return (char) unicodeChar; } } private static int getAction(KeyEvent keyEvent) { switch (keyEvent.getAction()) { case KeyEvent.ACTION_DOWN: return com.himamis.retex.editor.share.event.KeyEvent.ACTION_DOWN; case KeyEvent.ACTION_UP: return com.himamis.retex.editor.share.event.KeyEvent.ACTION_UP; case KeyEvent.ACTION_MULTIPLE: return com.himamis.retex.editor.share.event.KeyEvent.ACTION_MULTIPLE; default: return com.himamis.retex.editor.share.event.KeyEvent.ACTION_UNKNOWN; } } }