/tags/20090919/src/com/menny/android/anysoftkeyboard/keyboards/HardKeyboardSequenceHandler.java

http://softkeyboard.googlecode.com/ · Java · 209 lines · 169 code · 32 blank · 8 comment · 21 complexity · a3558dfe3d61fa6c57535327da515ad2 MD5 · raw file

  1. package com.menny.android.anysoftkeyboard.keyboards;
  2. import java.security.InvalidParameterException;
  3. import java.util.HashMap;
  4. import android.view.KeyEvent;
  5. import com.menny.android.anysoftkeyboard.AnyKeyboardContextProvider;
  6. class HardKeyboardSequenceHandler
  7. {
  8. private static final int[] msQwerty = new int[]{
  9. KeyEvent.KEYCODE_Q, KeyEvent.KEYCODE_W, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_R, KeyEvent.KEYCODE_T, KeyEvent.KEYCODE_Y,KeyEvent.KEYCODE_U,KeyEvent.KEYCODE_I,KeyEvent.KEYCODE_O,KeyEvent.KEYCODE_P,
  10. KeyEvent.KEYCODE_A,KeyEvent.KEYCODE_S,KeyEvent.KEYCODE_D,KeyEvent.KEYCODE_F,KeyEvent.KEYCODE_G,KeyEvent.KEYCODE_H,KeyEvent.KEYCODE_J,KeyEvent.KEYCODE_K,KeyEvent.KEYCODE_L,
  11. KeyEvent.KEYCODE_Z,KeyEvent.KEYCODE_X,KeyEvent.KEYCODE_C,KeyEvent.KEYCODE_V,KeyEvent.KEYCODE_B,KeyEvent.KEYCODE_N,KeyEvent.KEYCODE_M
  12. };
  13. private abstract class KeyEventSequenceBase
  14. {
  15. protected KeyEventSequenceBase()
  16. {
  17. }
  18. public abstract int getSequenceLength();
  19. protected abstract int getIntAt(int i);
  20. @Override
  21. public boolean equals(Object o)
  22. {
  23. if (o instanceof KeyEventSequenceBase)
  24. {
  25. KeyEventSequenceBase other = (KeyEventSequenceBase)o;
  26. if (other.hashCode() != hashCode())
  27. return false;
  28. if (other.getSequenceLength() != getSequenceLength())
  29. return false;
  30. for(int i=0;i<getSequenceLength();i++)
  31. {
  32. if (other.getIntAt(i) != getIntAt(i))
  33. return false;
  34. }
  35. //if I reached here... the it is equal.
  36. return true;
  37. }
  38. return super.equals(o);
  39. }
  40. }
  41. private class KeyEventSequence extends KeyEventSequenceBase
  42. {
  43. private final int[] mSequence;
  44. private final int mHashCode;
  45. private final char mTarget;
  46. public KeyEventSequence(int[] keyEventSequence, char target)
  47. {
  48. super();
  49. mTarget = target;
  50. mSequence = keyEventSequence;
  51. int hashCode = 0;
  52. for(int i=0;i<mSequence.length;i++)
  53. hashCode+=mSequence[i];
  54. mHashCode = hashCode;
  55. }
  56. public char getTarget() {return mTarget;}
  57. @Override
  58. public int getSequenceLength() {return mSequence.length;}
  59. @Override
  60. public int hashCode() {
  61. return mHashCode;
  62. }
  63. @Override
  64. protected int getIntAt(int i)
  65. {
  66. return mSequence[i];
  67. }
  68. }
  69. private class KeyEventSequenceHolder extends KeyEventSequenceBase
  70. {
  71. private final int[] mSequence;
  72. private int mHashCode;
  73. private int mCurrentSequenceLength;
  74. public KeyEventSequenceHolder()
  75. {
  76. super();
  77. mSequence = new int[10];//like there is going to be such a long sequence...
  78. mHashCode = 0;
  79. mCurrentSequenceLength = 0;
  80. }
  81. public void appendKeyEvent(int keyEvent)
  82. {
  83. mSequence[mCurrentSequenceLength % mSequence.length] = keyEvent;
  84. mCurrentSequenceLength++;
  85. mHashCode+=keyEvent;
  86. }
  87. public void reset()
  88. {
  89. mCurrentSequenceLength = 0;
  90. mHashCode = 0;
  91. }
  92. @Override
  93. public int getSequenceLength() {return mCurrentSequenceLength;}
  94. @Override
  95. public int hashCode() {
  96. return mHashCode;
  97. }
  98. @Override
  99. protected int getIntAt(int i)
  100. {
  101. return mSequence[i % mSequence.length];
  102. }
  103. }
  104. //See 'getSequenceCharacter' function for usage for msSequenceLivingTime and mLastTypedKeyEventTime.
  105. private static final long msSequenceLivingTime = 600;
  106. private long mLastTypedKeyEventTime;
  107. private final KeyEventSequenceHolder mCurrentTypedSequence;
  108. private final HashMap<KeyEventSequence, KeyEventSequence> mSequences;
  109. public HardKeyboardSequenceHandler()
  110. {
  111. mSequences = new HashMap<KeyEventSequence, KeyEventSequence>();
  112. mCurrentTypedSequence = new KeyEventSequenceHolder();
  113. mLastTypedKeyEventTime = System.currentTimeMillis();
  114. }
  115. public void addQwertyTranslation(String targetCharacters)
  116. {
  117. if (msQwerty.length != targetCharacters.length())
  118. throw new InvalidParameterException("'targetCharacters' should be the same lenght as the latin QWERTY keys strings: "+msQwerty);
  119. for(int qwertyIndex=0; qwertyIndex<msQwerty.length; qwertyIndex++)
  120. {
  121. char latinCharacter = (char)msQwerty[qwertyIndex];
  122. char otherCharacter = targetCharacters.charAt(qwertyIndex);
  123. if (otherCharacter > 0)
  124. addSequence(new int[]{latinCharacter}, otherCharacter);
  125. }
  126. }
  127. public void addSequence(int[] sequence, char result)
  128. {
  129. //creating sub sequences
  130. for(int sequenceLength = 1; sequenceLength < sequence.length; sequenceLength++)
  131. {
  132. int[] subSequence = new int[sequenceLength];
  133. for(int i=0;i<sequenceLength;i++)
  134. subSequence[i] = sequence[i];
  135. KeyEventSequence keysSequence = new KeyEventSequence(subSequence, (char)0);
  136. if (!mSequences.containsKey(keysSequence))
  137. mSequences.put(keysSequence,keysSequence);
  138. }
  139. //add the real sequence mapping
  140. KeyEventSequence actualSequence = new KeyEventSequence(sequence, result);
  141. mSequences.put(actualSequence, actualSequence);
  142. }
  143. public char getSequenceCharacter(int currentKeyEvent, AnyKeyboardContextProvider inputHandler)
  144. {
  145. //sequence does not live forever!
  146. //I say, let it live for msSequenceLivingTime milliseconds.
  147. long currentTime = System.currentTimeMillis();
  148. if ((currentTime - mLastTypedKeyEventTime) >= msSequenceLivingTime)
  149. mCurrentTypedSequence.reset();
  150. mLastTypedKeyEventTime = currentTime;
  151. mCurrentTypedSequence.appendKeyEvent(currentKeyEvent);
  152. if (mSequences.containsKey(mCurrentTypedSequence))
  153. {
  154. KeyEventSequence mappedSequence = mSequences.get(mCurrentTypedSequence);
  155. char mappedChar = mappedSequence.getTarget();
  156. if (mappedChar == 0)
  157. return 0;
  158. else
  159. {
  160. //need to delete the already typed characters
  161. inputHandler.deleteLastCharactersFromInput(mappedSequence.getSequenceLength() - 1);
  162. return mappedChar;
  163. }
  164. }
  165. else
  166. {
  167. int lastSequenceLength = mCurrentTypedSequence.getSequenceLength();
  168. //the previous state is not valid
  169. mCurrentTypedSequence.reset();
  170. if (lastSequenceLength > 1)//the sequence is not there...
  171. {//maybe just this key event.
  172. return getSequenceCharacter(currentKeyEvent, inputHandler);
  173. }
  174. return 0;
  175. }
  176. }
  177. }