| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * 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 com.android.inputmethod.keyboard; |
| |
| import android.text.InputType; |
| import android.view.inputmethod.EditorInfo; |
| import android.view.inputmethod.InputMethodSubtype; |
| |
| import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; |
| import com.android.inputmethod.keyboard.internal.MoreKeySpec; |
| import com.android.inputmethod.latin.R; |
| import com.android.inputmethod.latin.RichInputMethodManager; |
| import com.android.inputmethod.latin.common.Constants; |
| import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; |
| |
| import java.util.Arrays; |
| import java.util.Locale; |
| |
| abstract class KeyboardLayoutSetNavigateMoreKeysBase extends KeyboardLayoutSetTestsBase { |
| private ExpectedMoreKey mExpectedNavigateNextMoreKey; |
| private ExpectedMoreKey mExpectedNavigatePreviousMoreKey; |
| private ExpectedMoreKey mExpectedEmojiMoreKey; |
| |
| protected ExpectedMoreKey getExpectedNavigateNextMoreKey() { |
| return new ExpectedMoreKey(R.string.label_next_key); |
| } |
| |
| protected ExpectedMoreKey getExpectedNavigatePreviousMoreKey() { |
| return new ExpectedMoreKey(R.string.label_previous_key); |
| } |
| |
| protected ExpectedMoreKey getExpectedEmojiMoreKey() { |
| return new ExpectedMoreKey(KeyboardIconsSet.NAME_EMOJI_ACTION_KEY); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| mExpectedNavigateNextMoreKey = getExpectedNavigateNextMoreKey(); |
| mExpectedNavigatePreviousMoreKey = getExpectedNavigatePreviousMoreKey(); |
| mExpectedEmojiMoreKey = getExpectedEmojiMoreKey(); |
| } |
| |
| /** |
| * This class represents an expected more key. |
| */ |
| protected static class ExpectedMoreKey { |
| public static final int NO_LABEL = 0; |
| public static final ExpectedMoreKey[] EMPTY_MORE_KEYS = new ExpectedMoreKey[0]; |
| |
| public final int mLabelResId; |
| public final int mIconId; |
| |
| public ExpectedMoreKey(final String iconName) { |
| mLabelResId = NO_LABEL; |
| mIconId = KeyboardIconsSet.getIconId(iconName); |
| } |
| |
| public ExpectedMoreKey(final int labelResId) { |
| mLabelResId = labelResId; |
| mIconId = KeyboardIconsSet.ICON_UNDEFINED; |
| } |
| } |
| |
| private void doTestMoreKeysOf(final int code, final InputMethodSubtype subtype, |
| final int elementId, final int inputType, final int imeOptions, |
| final ExpectedMoreKey ... expectedMoreKeys) { |
| final EditorInfo editorInfo = new EditorInfo(); |
| editorInfo.inputType = inputType; |
| editorInfo.imeOptions = imeOptions; |
| final KeyboardLayoutSet layoutSet = createKeyboardLayoutSet(subtype, editorInfo); |
| final Keyboard keyboard = layoutSet.getKeyboard(elementId); |
| |
| final Key actualKey = keyboard.getKey(code); |
| final MoreKeySpec[] actualMoreKeys = actualKey.getMoreKeys(); |
| final String tag = actualKey.toString() + " moreKeys=" + Arrays.toString(actualMoreKeys); |
| if (expectedMoreKeys.length == 0) { |
| assertEquals(tag, null, actualMoreKeys); |
| return; |
| } |
| if (expectedMoreKeys.length == 1) { |
| assertEquals(tag + " fixedOrder", false, actualKey.isMoreKeysFixedOrder()); |
| assertEquals(tag + " fixedColumn", false, actualKey.isMoreKeysFixedColumn()); |
| } else { |
| assertEquals(tag + " fixedOrder", true, actualKey.isMoreKeysFixedOrder()); |
| assertEquals(tag + " fixedColumn", true, actualKey.isMoreKeysFixedColumn()); |
| // TODO: Can't handle multiple rows of more keys. |
| assertEquals(tag + " column", |
| expectedMoreKeys.length, actualKey.getMoreKeysColumnNumber()); |
| } |
| assertNotNull(tag + " moreKeys", actualMoreKeys); |
| assertEquals(tag, expectedMoreKeys.length, actualMoreKeys.length); |
| for (int index = 0; index < actualMoreKeys.length; index++) { |
| final int expectedLabelResId = expectedMoreKeys[index].mLabelResId; |
| if (expectedLabelResId == ExpectedMoreKey.NO_LABEL) { |
| assertEquals(tag + " label " + index, null, actualMoreKeys[index].mLabel); |
| } else { |
| final CharSequence expectedLabel = getContext().getText(expectedLabelResId); |
| assertEquals(tag + " label " + index, expectedLabel, actualMoreKeys[index].mLabel); |
| } |
| final int expectedIconId = expectedMoreKeys[index].mIconId; |
| assertEquals(tag + " icon " + index, expectedIconId, actualMoreKeys[index].mIconId); |
| } |
| } |
| |
| private void doTestNavigationMoreKeysOf(final int code, final InputMethodSubtype subtype, |
| final int elementId, final int inputType) { |
| // No navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_NULL, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // With next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| mExpectedNavigateNextMoreKey); |
| // With previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedNavigatePreviousMoreKey); |
| // With next and previous naviagte flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedNavigatePreviousMoreKey, mExpectedNavigateNextMoreKey); |
| // Action next. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action next with next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action next with previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedNavigatePreviousMoreKey); |
| // Action next with next and previous navigate flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT |
| | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedNavigatePreviousMoreKey); |
| // Action previous. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action previous with next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| mExpectedNavigateNextMoreKey); |
| // Action previous with previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action previous with next and previous navigate flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT |
| | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedNavigateNextMoreKey); |
| } |
| |
| private void doTestNavigationWithEmojiMoreKeysOf(final int code, |
| final InputMethodSubtype subtype, final int elementId, final int inputType) { |
| // No navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_NULL, |
| mExpectedEmojiMoreKey); |
| // With next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| mExpectedEmojiMoreKey, mExpectedNavigateNextMoreKey); |
| // With previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey); |
| // With next and previous naviagte flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey, |
| mExpectedNavigateNextMoreKey); |
| // Action next. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT, |
| mExpectedEmojiMoreKey); |
| // Action next with next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| mExpectedEmojiMoreKey); |
| // Action next with previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey); |
| // Action next with next and previous navigate flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT |
| | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedEmojiMoreKey, mExpectedNavigatePreviousMoreKey); |
| // Action previous. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS, |
| mExpectedEmojiMoreKey); |
| // Action previous with next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| mExpectedEmojiMoreKey, mExpectedNavigateNextMoreKey); |
| // Action previous with previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedEmojiMoreKey); |
| // Action previous with next and previous navigate flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT |
| | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| mExpectedEmojiMoreKey, mExpectedNavigateNextMoreKey); |
| } |
| |
| private void doTestNoNavigationMoreKeysOf(final int code, final InputMethodSubtype subtype, |
| final int elementId, final int inputType) { |
| // No navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_NULL, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // With next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // With previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // With next and previous naviagte flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action next. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action next with next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action next with previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action next with next and previous navigate flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NAVIGATE_NEXT |
| | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action previous. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action previous with next navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action previous with previous navigate flag. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| // Action previous with next and previous navigate flags. |
| doTestMoreKeysOf(code, subtype, elementId, inputType, |
| EditorInfo.IME_ACTION_PREVIOUS | EditorInfo.IME_FLAG_NAVIGATE_NEXT |
| | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS, |
| ExpectedMoreKey.EMPTY_MORE_KEYS); |
| } |
| |
| public void testMoreKeysOfEnterKey() { |
| final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); |
| final InputMethodSubtype subtype = richImm.findSubtypeByLocaleAndKeyboardLayoutSet( |
| Locale.US.toString(), SubtypeLocaleUtils.QWERTY); |
| |
| // Password field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); |
| // Email field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); |
| // Url field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI); |
| // Phone number field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_PHONE, |
| InputType.TYPE_CLASS_PHONE); |
| // Number field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, |
| InputType.TYPE_CLASS_NUMBER); |
| // Date-time field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, |
| InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_NORMAL); |
| // Date field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, |
| InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE); |
| // Time field. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, KeyboardId.ELEMENT_NUMBER, |
| InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_TIME); |
| // Text field. |
| if (isPhone()) { |
| // The enter key has an Emoji key as one of more keys. |
| doTestNavigationWithEmojiMoreKeysOf(Constants.CODE_ENTER, subtype, |
| KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT); |
| } else { |
| // Tablet has a dedicated Emoji key, so the Enter key has no Emoji more key. |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, |
| KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT); |
| } |
| // Short message field. |
| if (isPhone()) { |
| // Enter key is switched to Emoji key on a short message field. |
| // Emoji key has no navigation more keys. |
| doTestNoNavigationMoreKeysOf(Constants.CODE_EMOJI, subtype, |
| KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); |
| } else { |
| doTestNavigationMoreKeysOf(Constants.CODE_ENTER, subtype, |
| KeyboardId.ELEMENT_ALPHABET, |
| InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE); |
| } |
| } |
| } |