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 17 package com.android.inputmethod.keyboard.layout; 18 19 import com.android.inputmethod.keyboard.KeyboardId; 20 import com.android.inputmethod.keyboard.layout.customizer.LayoutCustomizer; 21 import com.android.inputmethod.keyboard.layout.expected.AbstractLayoutBase; 22 import com.android.inputmethod.keyboard.layout.expected.ExpectedKey; 23 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder; 24 25 import java.util.Locale; 26 27 /** 28 * The base class of keyboard layout. 29 */ 30 public abstract class LayoutBase extends AbstractLayoutBase { 31 private final LayoutCustomizer mCustomizer; 32 private final Symbols mSymbols; 33 private final SymbolsShifted mSymbolsShifted; 34 35 LayoutBase(final LayoutCustomizer customizer, final Class<? extends Symbols> symbolsClass, 36 final Class<? extends SymbolsShifted> symbolsShiftedClass) { 37 mCustomizer = customizer; 38 try { 39 mSymbols = symbolsClass.getDeclaredConstructor(LayoutCustomizer.class) 40 .newInstance(customizer); 41 mSymbolsShifted = symbolsShiftedClass.getDeclaredConstructor(LayoutCustomizer.class) 42 .newInstance(customizer); 43 } catch (final Exception e) { 44 throw new RuntimeException("Unknown Symbols/SymbolsShifted class", e); 45 } 46 } 47 48 /** 49 * The layout name. 50 * @return the name of this layout. 51 */ 52 public abstract String getName(); 53 54 /** 55 * The locale of this layout. 56 * @return the locale of this layout. 57 */ 58 public final Locale getLocale() { return mCustomizer.getLocale(); } 59 60 /** 61 * The layout customizer for this layout. 62 * @return the layout customizer; 63 */ 64 public final LayoutCustomizer getCustomizer() { return mCustomizer; } 65 66 /** 67 * Helper method to create alphabet layout adding special function keys. 68 * @param builder the {@link ExpectedKeyboardBuilder} object that contains common keyboard 69 * layout 70 * @param isPhone true if requesting phone's layout. 71 * @return the {@link ExpectedKeyboardBuilder} object that is customized and have special keys. 72 */ 73 ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder, 74 final boolean isPhone) { 75 final LayoutCustomizer customizer = getCustomizer(); 76 final int numberOfRows = customizer.getNumberOfRows(); 77 builder.setKeysOfRow(numberOfRows, (Object[])customizer.getSpaceKeys(isPhone)); 78 builder.addKeysOnTheLeftOfRow( 79 numberOfRows, (Object[])customizer.getKeysLeftToSpacebar(isPhone)); 80 builder.addKeysOnTheRightOfRow( 81 numberOfRows, (Object[])customizer.getKeysRightToSpacebar(isPhone)); 82 if (isPhone) { 83 builder.addKeysOnTheRightOfRow(numberOfRows - 1, DELETE_KEY) 84 .addKeysOnTheLeftOfRow(numberOfRows, customizer.getSymbolsKey()) 85 .addKeysOnTheRightOfRow(numberOfRows, customizer.getEnterKey(isPhone)); 86 } else { 87 builder.addKeysOnTheRightOfRow(1, DELETE_KEY) 88 .addKeysOnTheRightOfRow(numberOfRows - 2, customizer.getEnterKey(isPhone)) 89 .addKeysOnTheLeftOfRow(numberOfRows, customizer.getSymbolsKey()) 90 .addKeysOnTheRightOfRow(numberOfRows, customizer.getEmojiKey(isPhone)); 91 } 92 builder.addKeysOnTheLeftOfRow( 93 numberOfRows - 1, (Object[])customizer.getLeftShiftKeys(isPhone)); 94 builder.addKeysOnTheRightOfRow( 95 numberOfRows - 1, (Object[])customizer.getRightShiftKeys(isPhone)); 96 return builder; 97 } 98 99 /** 100 * Get common alphabet layout. This layout doesn't contain any special keys. 101 * 102 * A keyboard layout is an array of rows, and a row consists of an array of 103 * {@link ExpectedKey}s. Each row may have different number of {@link ExpectedKey}s. 104 * 105 * @param isPhone true if requesting phone's layout. 106 * @return the common alphabet keyboard layout. 107 */ 108 abstract ExpectedKey[][] getCommonAlphabetLayout(boolean isPhone); 109 110 /** 111 * Get common alphabet shifted layout. This layout doesn't contain any special keys. 112 * 113 * A keyboard layout is an array of rows, and a row consists of an array of 114 * {@link ExpectedKey}s. Each row may have different number of {@link ExpectedKey}s. 115 * 116 * @param isPhone true if requesting phone's layout. 117 * @param elementId the element id of the requesting shifted mode. 118 * @return the common alphabet shifted keyboard layout. 119 */ 120 ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) { 121 final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder( 122 getCommonAlphabetLayout(isPhone)); 123 getCustomizer().setAccentedLetters(builder, elementId); 124 builder.toUpperCase(getLocale()); 125 return builder.build(); 126 } 127 128 /** 129 * Get the complete expected keyboard layout. 130 * 131 * A keyboard layout is an array of rows, and a row consists of an array of 132 * {@link ExpectedKey}s. Each row may have different number of {@link ExpectedKey}s. 133 * 134 * @param isPhone true if requesting phone's layout. 135 * @param elementId the element id of the requesting keyboard mode. 136 * @return the keyboard layout of the <code>elementId</code>. 137 */ 138 public ExpectedKey[][] getLayout(final boolean isPhone, final int elementId) { 139 if (elementId == KeyboardId.ELEMENT_SYMBOLS) { 140 return mSymbols.getLayout(isPhone); 141 } 142 if (elementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) { 143 return mSymbolsShifted.getLayout(isPhone); 144 } 145 final ExpectedKeyboardBuilder builder; 146 if (elementId == KeyboardId.ELEMENT_ALPHABET) { 147 builder = new ExpectedKeyboardBuilder(getCommonAlphabetLayout(isPhone)); 148 getCustomizer().setAccentedLetters(builder, elementId); 149 } else { 150 final ExpectedKey[][] commonLayout = getCommonAlphabetShiftLayout(isPhone, elementId); 151 if (commonLayout == null) { 152 return null; 153 } 154 builder = new ExpectedKeyboardBuilder(commonLayout); 155 } 156 convertCommonLayoutToKeyboard(builder, isPhone); 157 if (elementId != KeyboardId.ELEMENT_ALPHABET) { 158 builder.replaceKeysOfAll(SHIFT_KEY, SHIFTED_SHIFT_KEY); 159 } 160 return builder.build(); 161 } 162 } 163