KeyboardLayoutSetNavigateMoreKeysBase.java revision 464ff7c131b097e1320a6d7b9207ccbf3eb70d22
1/* 2 * Copyright (C) 2014 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 17package com.android.inputmethod.keyboard; 18 19import android.text.InputType; 20import android.view.inputmethod.EditorInfo; 21import android.view.inputmethod.InputMethodSubtype; 22 23import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; 24import com.android.inputmethod.keyboard.internal.MoreKeySpec; 25import com.android.inputmethod.latin.Constants; 26import com.android.inputmethod.latin.R; 27import com.android.inputmethod.latin.RichInputMethodManager; 28import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; 29 30import java.util.Arrays; 31import java.util.Locale; 32 33abstract class KeyboardLayoutSetNavigateMoreKeysBase extends KeyboardLayoutSetTestsBase { 34 private ExpectedMoreKey mExpectedNavigateNextMoreKey; 35 private ExpectedMoreKey mExpectedNavigatePreviousMoreKey; 36 private ExpectedMoreKey mExpectedEmojiMoreKey; 37 38 @Override 39 protected void setUp() throws Exception { 40 super.setUp(); 41 mExpectedNavigateNextMoreKey = new ExpectedMoreKey(R.string.label_next_key); 42 mExpectedNavigatePreviousMoreKey = new ExpectedMoreKey(R.string.label_previous_key); 43 mExpectedEmojiMoreKey = new ExpectedMoreKey(KeyboardIconsSet.NAME_EMOJI_ACTION_KEY); 44 } 45 46 /** 47 * This class represents an expected more key. 48 */ 49 protected static class ExpectedMoreKey { 50 public static final int NO_LABEL = 0; 51 public static final ExpectedMoreKey[] EMPTY_MORE_KEYS = new ExpectedMoreKey[0]; 52 53 public final int mLabelResId; 54 public final int mIconId; 55 56 public ExpectedMoreKey(final String iconName) { 57 mLabelResId = NO_LABEL; 58 mIconId = KeyboardIconsSet.getIconId(iconName); 59 } 60 61 public ExpectedMoreKey(final int labelResId) { 62 mLabelResId = labelResId; 63 mIconId = KeyboardIconsSet.ICON_UNDEFINED; 64 } 65 } 66 67 private void doTestMoreKeysOf(final int code, final InputMethodSubtype subtype, 68 final int elementId, final int inputType, final int imeOptions, 69 final ExpectedMoreKey ... expectedMoreKeys) { 70 final EditorInfo editorInfo = new EditorInfo(); 71 editorInfo.inputType = inputType; 72 editorInfo.imeOptions = imeOptions; 73 final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo); 74 final Keyboard keyboard = layoutSet.getKeyboard(elementId); 75 76 final Key actualKey = keyboard.getKey(code); 77 final MoreKeySpec[] actualMoreKeys = actualKey.getMoreKeys(); 78 final String tag = actualKey.toString() + " moreKeys=" + Arrays.toString(actualMoreKeys); 79 if (expectedMoreKeys.length == 0) { 80 assertEquals(tag, null, actualMoreKeys); 81 return; 82 } 83 if (expectedMoreKeys.length == 1) { 84 assertEquals(tag + " fixedOrder", false, actualKey.isMoreKeysFixedOrder()); 85 assertEquals(tag + " fixedColumn", false, actualKey.isMoreKeysFixedColumn()); 86 } else { 87 assertEquals(tag + " fixedOrder", true, actualKey.isMoreKeysFixedOrder()); 88 assertEquals(tag + " fixedColumn", true, actualKey.isMoreKeysFixedColumn()); 89 // TODO: Can't handle multiple rows of more keys. 90 assertEquals(tag + " column", 91 expectedMoreKeys.length, actualKey.getMoreKeysColumnNumber()); 92 } 93 assertEquals(tag, expectedMoreKeys.length, actualMoreKeys.length); 94 for (int index = 0; index < actualMoreKeys.length; index++) { 95 final int expectedLabelResId = expectedMoreKeys[index].mLabelResId; 96 if (expectedLabelResId == ExpectedMoreKey.NO_LABEL) { 97 assertEquals(tag + " label " + index, null, actualMoreKeys[index].mLabel); 98 } else { 99 final CharSequence expectedLabel = getContext().getText(expectedLabelResId); 100 assertEquals(tag + " label " + index, expectedLabel, actualMoreKeys[index].mLabel); 101 } 102 final int expectedIconId = expectedMoreKeys[index].mIconId; 103 assertEquals(tag + " icon " + index, expectedIconId, actualMoreKeys[index].mIconId); 104 } 105 } 106 107 private void doTestNavigationMoreKeysOf(final int code, final InputMethodSubtype subtype, 108 final int elementId, final int inputType) { 109 // No navigate flag. 110 doTestMoreKeysOf(code, subtype, elementId, inputType, 111 EditorInfo.IME_NULL, 112 ExpectedMoreKey.EMPTY_MORE_KEYS); 113 // With next navigate flag. 114 doTestMoreKeysOf(code, subtype, elementId, inputType, 115 EditorInfo.IME_FLAG_NAVIGATE_NEXT, 116 mExpectedNavigateNextMoreKey); 117 // With previous navigate flag. 118 doTestMoreKeysOf(code, subtype, elementId, inputType, 119 EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 120 mExpectedNavigatePreviousMoreKey); 121 // With next and previous naviagte flags. 122 doTestMoreKeysOf(code, subtype, elementId, inputType, 123 EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 124 mExpectedNavigatePreviousMoreKey, mExpectedNavigateNextMoreKey); 125 // Action next. 126 doTestMoreKeysOf(code, subtype, elementId, inputType, 127 EditorInfo.IME_ACTION_NEXT, 128 ExpectedMoreKey.EMPTY_MORE_KEYS); 129 // Action next with next navigate flag. 130 doTestMoreKeysOf(code, subtype, elementId, inputType, 131 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT, 132 ExpectedMoreKey.EMPTY_MORE_KEYS); 133 // Action next with previous navigate flag. 134 doTestMoreKeysOf(code, subtype, elementId, inputType, 135 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 136 mExpectedNavigatePreviousMoreKey); 137 // Action next with next and previous navigate flags. 138 doTestMoreKeysOf(code, subtype, elementId, inputType, 139 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT 140 | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 141 mExpectedNavigatePreviousMoreKey); 142 // Action previous. 143 doTestMoreKeysOf(code, subtype, elementId, inputType, 144 EditorInfo.IME_ACTION_PREVIOUS, 145 ExpectedMoreKey.EMPTY_MORE_KEYS); 146 // Action previous with next navigate flag. 147 doTestMoreKeysOf(code, subtype, elementId, inputType, 148 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT, 149 mExpectedNavigateNextMoreKey); 150 // Action previous with previous navigate flag. 151 doTestMoreKeysOf(code, subtype, elementId, inputType, 152 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 153 ExpectedMoreKey.EMPTY_MORE_KEYS); 154 // Action previous with next and previous navigate flags. 155 doTestMoreKeysOf(code, subtype, elementId, inputType, 156 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT 157 | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 158 mExpectedNavigateNextMoreKey); 159 } 160 161 private void doTestNavigationWithEmojiMoreKeysOf(final int code, 162 final InputMethodSubtype subtype, final int elementId, final int inputType) { 163 // No navigate flag. 164 doTestMoreKeysOf(code, subtype, elementId, inputType, 165 EditorInfo.IME_NULL, 166 mExpectedEmojiMoreKey); 167 // With next navigate flag. 168 doTestMoreKeysOf(code, subtype, elementId, inputType, 169 EditorInfo.IME_FLAG_NAVIGATE_NEXT, 170 mExpectedEmojiMoreKey, mExpectedNavigateNextMoreKey); 171 // With previous navigate flag. 172 doTestMoreKeysOf(code, subtype, elementId, inputType, 173 EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 174 mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey); 175 // With next and previous naviagte flags. 176 doTestMoreKeysOf(code, subtype, elementId, inputType, 177 EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 178 mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey, 179 mExpectedNavigateNextMoreKey); 180 // Action next. 181 doTestMoreKeysOf(code, subtype, elementId, inputType, 182 EditorInfo.IME_ACTION_NEXT, 183 mExpectedEmojiMoreKey); 184 // Action next with next navigate flag. 185 doTestMoreKeysOf(code, subtype, elementId, inputType, 186 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT, 187 mExpectedEmojiMoreKey); 188 // Action next with previous navigate flag. 189 doTestMoreKeysOf(code, subtype, elementId, inputType, 190 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 191 mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey); 192 // Action next with next and previous navigate flags. 193 doTestMoreKeysOf(code, subtype, elementId, inputType, 194 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT 195 | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 196 mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey); 197 // Action previous. 198 doTestMoreKeysOf(code, subtype, elementId, inputType, 199 EditorInfo.IME_ACTION_PREVIOUS, 200 mExpectedEmojiMoreKey); 201 // Action previous with next navigate flag. 202 doTestMoreKeysOf(code, subtype, elementId, inputType, 203 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT, 204 mExpectedEmojiMoreKey, mExpectedNavigateNextMoreKey); 205 // Action previous with previous navigate flag. 206 doTestMoreKeysOf(code, subtype, elementId, inputType, 207 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 208 mExpectedEmojiMoreKey); 209 // Action previous with next and previous navigate flags. 210 doTestMoreKeysOf(code, subtype, elementId, inputType, 211 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT 212 | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 213 mExpectedEmojiMoreKey, mExpectedNavigateNextMoreKey); 214 } 215 216 private void doTestNoNavigationMoreKeysOf(final int code, final InputMethodSubtype subtype, 217 final int elementId, final int inputType) { 218 // No navigate flag. 219 doTestMoreKeysOf(code, subtype, elementId, inputType, 220 EditorInfo.IME_NULL, 221 ExpectedMoreKey.EMPTY_MORE_KEYS); 222 // With next navigate flag. 223 doTestMoreKeysOf(code, subtype, elementId, inputType, 224 EditorInfo.IME_FLAG_NAVIGATE_NEXT, 225 ExpectedMoreKey.EMPTY_MORE_KEYS); 226 // With previous navigate flag. 227 doTestMoreKeysOf(code, subtype, elementId, inputType, 228 EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 229 ExpectedMoreKey.EMPTY_MORE_KEYS); 230 // With next and previous naviagte flags. 231 doTestMoreKeysOf(code, subtype, elementId, inputType, 232 EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 233 ExpectedMoreKey.EMPTY_MORE_KEYS); 234 // Action next. 235 doTestMoreKeysOf(code, subtype, elementId, inputType, 236 EditorInfo.IME_ACTION_NEXT, 237 ExpectedMoreKey.EMPTY_MORE_KEYS); 238 // Action next with next navigate flag. 239 doTestMoreKeysOf(code, subtype, elementId, inputType, 240 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT, 241 ExpectedMoreKey.EMPTY_MORE_KEYS); 242 // Action next with previous navigate flag. 243 doTestMoreKeysOf(code, subtype, elementId, inputType, 244 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 245 ExpectedMoreKey.EMPTY_MORE_KEYS); 246 // Action next with next and previous navigate flags. 247 doTestMoreKeysOf(code, subtype, elementId, inputType, 248 EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT 249 | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 250 ExpectedMoreKey.EMPTY_MORE_KEYS); 251 // Action previous. 252 doTestMoreKeysOf(code, subtype, elementId, inputType, 253 EditorInfo.IME_ACTION_PREVIOUS, 254 ExpectedMoreKey.EMPTY_MORE_KEYS); 255 // Action previous with next navigate flag. 256 doTestMoreKeysOf(code, subtype, elementId, inputType, 257 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT, 258 ExpectedMoreKey.EMPTY_MORE_KEYS); 259 // Action previous with previous navigate flag. 260 doTestMoreKeysOf(code, subtype, elementId, inputType, 261 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 262 ExpectedMoreKey.EMPTY_MORE_KEYS); 263 // Action previous with next and previous navigate flags. 264 doTestMoreKeysOf(code, subtype, elementId, inputType, 265 EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT 266 | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, 267 ExpectedMoreKey.EMPTY_MORE_KEYS); 268 } 269 270 public void testMoreKeysOfEnterKey() { 271 final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); 272 final InputMethodSubtype subtype = richImm.findSubtypeByLocaleAndKeyboardLayoutSet( 273 Locale.US.toString(), SubtypeLocaleUtils.QWERTY); 274 275 // Password field. 276 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_ALPHABET, 277 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); 278 // Email field. 279 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_ALPHABET, 280 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); 281 // Url field. 282 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_ALPHABET, 283 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); 284 // Phone number field. 285 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_PHONE, 286 InputType.TYPE_CLASS_PHONE); 287 // Number field. 288 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, 289 InputType.TYPE_CLASS_NUMBER); 290 // Date-time field. 291 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, 292 InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_NORMAL); 293 // Date field. 294 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, 295 InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE); 296 // Time field. 297 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, 298 InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_TIME); 299 // Text field. 300 if (isPhone()) { 301 // The enter key has an Emoji key as one of more keys. 302 doTestNavigationWithEmojiMoreKeysOf(Constants.CODE_ENTER, subtype, 303 KeyboardId.ELEMENT_ALPHABET, 304 InputType.TYPE_CLASS_TEXT); 305 } else { 306 // Tablet has a dedicated Emoji key, so the Enter key has no Emoji more key. 307 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, 308 KeyboardId.ELEMENT_ALPHABET, 309 InputType.TYPE_CLASS_TEXT); 310 } 311 // Short message field. 312 if (isPhone()) { 313 // Enter key is switched to Emoji key on a short message field. 314 // Emoji key has no navigation more keys. 315 doTestNoNavigationMoreKeysOf(Constants.CODE_EMOJI, subtype, 316 KeyboardId.ELEMENT_ALPHABET, 317 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); 318 } else { 319 doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, 320 KeyboardId.ELEMENT_ALPHABET, 321 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); 322 } 323 } 324} 325