/ime/latinime/src/com/googlecode/eyesfree/inputmethod/KeyCodeDescriptionMapper.java

http://eyes-free.googlecode.com/ · Java · 191 lines · 100 code · 26 blank · 65 comment · 22 complexity · d35531a67dc11752484293c072bc890b MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  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. package com.googlecode.eyesfree.inputmethod;
  17. import android.content.Context;
  18. import android.content.res.Resources;
  19. import android.inputmethodservice.Keyboard.Key;
  20. import android.text.TextUtils;
  21. import com.googlecode.eyesfree.inputmethod.latin.KeyboardSwitcher;
  22. import com.googlecode.eyesfree.inputmethod.latin.LatinKeyboardView;
  23. import com.googlecode.eyesfree.inputmethod.latin.R;
  24. import java.util.HashMap;
  25. public class KeyCodeDescriptionMapper {
  26. private static KeyCodeDescriptionMapper sInstance;
  27. public static KeyCodeDescriptionMapper getInstance(Context context) {
  28. if (sInstance == null) {
  29. sInstance = new KeyCodeDescriptionMapper(context);
  30. }
  31. return sInstance;
  32. }
  33. // Map of key labels to spoken description resource IDs
  34. private final HashMap<CharSequence, Integer> mKeyLabelMap;
  35. // Map of key codes to spoken description resource IDs
  36. private final HashMap<Integer, Integer> mKeyCodeMap;
  37. // Map of shifted key codes to spoken description resource IDs
  38. private final HashMap<Integer, Integer> mShiftedKeyCodeMap;
  39. // Map of shift-locked key codes to spoken description resource IDs
  40. private final HashMap<Integer, Integer> mShiftLockedKeyCodeMap;
  41. private KeyCodeDescriptionMapper(Context context) {
  42. final Resources res = context.getResources();
  43. mKeyLabelMap = new HashMap<CharSequence, Integer>();
  44. mKeyCodeMap = new HashMap<Integer, Integer>();
  45. mShiftedKeyCodeMap = new HashMap<Integer, Integer>();
  46. mShiftLockedKeyCodeMap = new HashMap<Integer, Integer>();
  47. // Label substitutions for when the key label should not be spoken
  48. mKeyLabelMap.put(res.getText(R.string.label_alpha_key),
  49. R.string.spoken_description_to_alpha);
  50. mKeyLabelMap.put(res.getText(R.string.label_symbol_key),
  51. R.string.spoken_description_to_symbol);
  52. mKeyLabelMap.put(res.getText(R.string.label_phone_key),
  53. R.string.spoken_description_to_numeric);
  54. // Manual label substitutions for key labels with no string resource
  55. mKeyLabelMap.put(":-)", R.string.spoken_description_smiley);
  56. // Symbols that most TTS engines can't speak
  57. mKeyCodeMap.put((int) '.', R.string.spoken_description_period);
  58. mKeyCodeMap.put((int) ',', R.string.spoken_description_comma);
  59. mKeyCodeMap.put((int) '(', R.string.spoken_description_left_parenthesis);
  60. mKeyCodeMap.put((int) ')', R.string.spoken_description_right_parenthesis);
  61. mKeyCodeMap.put((int) ':', R.string.spoken_description_colon);
  62. mKeyCodeMap.put((int) ';', R.string.spoken_description_semicolon);
  63. mKeyCodeMap.put((int) '!', R.string.spoken_description_exclamation_mark);
  64. mKeyCodeMap.put((int) '?', R.string.spoken_description_question_mark);
  65. mKeyCodeMap.put((int) '\"', R.string.spoken_description_double_quote);
  66. mKeyCodeMap.put((int) '\'', R.string.spoken_description_single_quote);
  67. mKeyCodeMap.put((int) '*', R.string.spoken_description_star);
  68. mKeyCodeMap.put((int) '#', R.string.spoken_description_pound);
  69. mKeyCodeMap.put((int) ' ', R.string.spoken_description_space);
  70. // Non-ASCII symbols (must use escape codes!)
  71. mKeyCodeMap.put((int) '\u2022', R.string.spoken_description_dot);
  72. mKeyCodeMap.put((int) '\u221A', R.string.spoken_description_square_root);
  73. mKeyCodeMap.put((int) '\u03C0', R.string.spoken_description_pi);
  74. mKeyCodeMap.put((int) '\u0394', R.string.spoken_description_delta);
  75. mKeyCodeMap.put((int) '\u2122', R.string.spoken_description_trademark);
  76. mKeyCodeMap.put((int) '\u2105', R.string.spoken_description_care_of);
  77. mKeyCodeMap.put((int) '\u2026', R.string.spoken_description_ellipsis);
  78. mKeyCodeMap.put((int) '\u201E', R.string.spoken_description_low_double_quote);
  79. // Special non-character codes defined in Keyboard
  80. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_DELETE, R.string.spoken_description_delete);
  81. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_RETURN, R.string.spoken_description_return);
  82. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_OPTIONS, R.string.spoken_description_settings);
  83. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_SHIFT, R.string.spoken_description_shift);
  84. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_VOICE, R.string.spoken_description_mic);
  85. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_TAB, R.string.spoken_description_tab);
  86. // Additional TalkBack-specific keys
  87. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_BACK, R.string.spoken_description_back);
  88. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_HOME, R.string.spoken_description_home);
  89. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_SEARCH, R.string.spoken_description_search);
  90. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_MENU, R.string.spoken_description_menu);
  91. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_CALL, R.string.spoken_description_call);
  92. mKeyCodeMap.put(LatinKeyboardView.KEYCODE_ENDCALL, R.string.spoken_description_end_call);
  93. // Shifted versions of non-character codes defined in LatinKeyboardView
  94. mShiftedKeyCodeMap.put(LatinKeyboardView.KEYCODE_SHIFT, R.string.spoken_description_shift_shifted);
  95. // Shift-locked versions of non-character codes defined in LatinKeyboardView
  96. mShiftLockedKeyCodeMap.put(LatinKeyboardView.KEYCODE_SHIFT, R.string.spoken_description_caps_lock);
  97. }
  98. /**
  99. * Returns the description of the action performed by a specified key based
  100. * on the current keyboard state.
  101. * <p>
  102. * The order of precedence for key descriptions is:
  103. * <ol>
  104. * <li>Manually-defined based on the key label</li>
  105. * <li>Automatic or manually-defined based on the key code</li>
  106. * <li>Automatically based on the key label</li>
  107. * <li>{code null} for keys with no label or key code defined</li>
  108. * </p>
  109. *
  110. * @param res The package's resources.
  111. * @param switcher The keyboard switcher for the keyboard on which the key resides.
  112. * @param key The key from which to obtain a description.
  113. * @return a character sequence describing the action performed by pressing
  114. * the key
  115. */
  116. public CharSequence getDescriptionForKey(Resources res, KeyboardSwitcher switcher, Key key) {
  117. if (!TextUtils.isEmpty(key.label)) {
  118. final String label = key.label.toString().trim();
  119. if (mKeyLabelMap.containsKey(label)) {
  120. return res.getText(mKeyLabelMap.get(label));
  121. } else if (label.length() == 1) {
  122. return getDescriptionForKeyCode(res, switcher, key);
  123. } else {
  124. return label;
  125. }
  126. } else if (key.codes != null) {
  127. return getDescriptionForKeyCode(res, switcher, key);
  128. }
  129. return null;
  130. }
  131. /**
  132. * Returns a character sequence describing what will happen when the
  133. * specified key is pressed based on its key code.
  134. * <p>
  135. * The order of precedence for key code descriptions is:
  136. * <ol>
  137. * <li>Manually-defined shift-locked description</li>
  138. * <li>Manually-defined shifted description</li>
  139. * <li>Manually-defined normal description</li>
  140. * <li>Automatic based on the character represented by the key code</li>
  141. * <li>Fall-back for undefined or control characters</li>
  142. * </ol>
  143. * </p>
  144. *
  145. * @param res The package's resources.
  146. * @param switcher The keyboard switcher for the keyboard on which the key resides.
  147. * @param key The key from which to obtain a description.
  148. * @return a character sequence describing the action performed by pressing
  149. * the key
  150. */
  151. private CharSequence getDescriptionForKeyCode(Resources res, KeyboardSwitcher switcher, Key key) {
  152. final int code = key.codes[0];
  153. if (switcher.isShiftLocked() && mShiftLockedKeyCodeMap.containsKey(code)) {
  154. return res.getText(mShiftLockedKeyCodeMap.get(code));
  155. } else if (switcher.isShiftedOrShiftLocked() && mShiftedKeyCodeMap.containsKey(code)) {
  156. return res.getText(mShiftedKeyCodeMap.get(code));
  157. } else if (mKeyCodeMap.containsKey(code)) {
  158. return res.getText(mKeyCodeMap.get(code));
  159. } else if (Character.isDefined(code) && !Character.isISOControl(code)) {
  160. return Character.toString((char) code);
  161. } else {
  162. return res.getString(R.string.spoken_description_unknown, code);
  163. }
  164. }
  165. }