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.layout.expected; 18 19import com.android.inputmethod.keyboard.Key; 20import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; 21import com.android.inputmethod.keyboard.internal.MoreKeySpec; 22import com.android.inputmethod.latin.Constants; 23import com.android.inputmethod.latin.utils.StringUtils; 24 25import java.util.ArrayList; 26import java.util.List; 27 28/** 29 * This class builds an actual keyboard for unit test. 30 * 31 * An actual keyboard is an array of rows, and a row consists of an array of {@link Key}s. 32 * Each row may have different number of {@link Key}s. 33 */ 34public final class ActualKeyboardBuilder extends AbstractKeyboardBuilder<Key> { 35 private static ArrayList<Key> filterOutSpacer(final List<Key> keys) { 36 final ArrayList<Key> filteredKeys = new ArrayList<>(); 37 for (final Key key : keys) { 38 if (key.isSpacer()) { 39 continue; 40 } 41 filteredKeys.add(key); 42 } 43 return filteredKeys; 44 } 45 46 /** 47 * Create the keyboard that consists of the array of rows of the actual keyboard's keys. 48 * @param sortedKeys keys list of the actual keyboard that is sorted from top-left to 49 * bottom-right. 50 * @return the actual keyboard grouped with rows. 51 */ 52 public static Key[][] buildKeyboard(final List<Key> sortedKeys) { 53 // Filter out spacer to prepare to create rows. 54 final ArrayList<Key> filteredSortedKeys = filterOutSpacer(sortedKeys); 55 56 // Grouping keys into rows. 57 final ArrayList<ArrayList<Key>> rows = new ArrayList<>(); 58 ArrayList<Key> elements = new ArrayList<>(); 59 int lastY = filteredSortedKeys.get(0).getY(); 60 for (final Key key : filteredSortedKeys) { 61 if (lastY != key.getY()) { 62 // A new row is starting. 63 lastY = key.getY(); 64 rows.add(elements); 65 elements = new ArrayList<>(); 66 } 67 elements.add(key); 68 } 69 rows.add(elements); // Add the last row. 70 71 // Calculate each dimension of rows and create a builder. 72 final int[] dimensions = new int[rows.size()]; 73 for (int rowIndex = 0; rowIndex < dimensions.length; rowIndex++) { 74 dimensions[rowIndex] = rows.get(rowIndex).size(); 75 } 76 final ActualKeyboardBuilder builder = new ActualKeyboardBuilder(); 77 78 for (int rowIndex = 0; rowIndex < rows.size(); rowIndex++) { 79 final int row = rowIndex + 1; 80 final ArrayList<Key> rowKeys = rows.get(rowIndex); 81 builder.setRowAt(row, rowKeys.toArray(new Key[rowKeys.size()])); 82 } 83 return builder.build(); 84 } 85 86 @Override 87 Key defaultElement() { return null; } 88 89 @Override 90 Key[] newArray(final int size) { return new Key[size]; } 91 92 @Override 93 Key[][] newArrayOfArray(final int size) { return new Key[size][]; } 94 95 // Helper class to create concise representation from the key specification. 96 static class MoreKeySpecStringizer extends StringUtils.Stringizer<MoreKeySpec> { 97 static final MoreKeySpecStringizer STRINGIZER = new MoreKeySpecStringizer(); 98 99 @Override 100 public String stringize(final MoreKeySpec spec) { 101 return toString(spec.mLabel, spec.mIconId, spec.mOutputText, spec.mCode); 102 } 103 104 static String toString(final String label, final int iconId, final String outputText, 105 final int code) { 106 final String visual = (iconId != KeyboardIconsSet.ICON_UNDEFINED) 107 ? KeyboardIconsSet.getIconName(iconId) : label; 108 final String output; 109 if (code == Constants.CODE_OUTPUT_TEXT) { 110 output = outputText; 111 } else if (code < Constants.CODE_SPACE) { 112 output = Constants.printableCode(code); 113 } else { 114 output = StringUtils.newSingleCodePointString(code); 115 } 116 if (visual.equals(output)) { 117 return visual; 118 } 119 return visual + "|" + output; 120 } 121 } 122 123 // Helper class to create concise representation from the key. 124 static class KeyStringizer extends StringUtils.Stringizer<Key> { 125 static final KeyStringizer STRINGIZER = new KeyStringizer(); 126 127 @Override 128 public String stringize(final Key key) { 129 if (key == null) { 130 return "NULL"; 131 } 132 if (key.isSpacer()) { 133 return "SPACER"; 134 } 135 final StringBuilder sb = new StringBuilder(); 136 sb.append(MoreKeySpecStringizer.toString( 137 key.getLabel(), key.getIconId(), key.getOutputText(), key.getCode())); 138 final MoreKeySpec[] moreKeys = key.getMoreKeys(); 139 if (moreKeys == null) { 140 return sb.toString(); 141 } 142 sb.append("^"); 143 sb.append(MoreKeySpecStringizer.STRINGIZER.join(moreKeys)); 144 return sb.toString(); 145 } 146 } 147 148 /** 149 * Convert the key to human readable string. 150 * @param key the key to be converted to string. 151 * @return the human readable representation of <code>key</code>. 152 */ 153 public static String toString(final Key key) { 154 return KeyStringizer.STRINGIZER.stringize(key); 155 } 156 157 /** 158 * Convert the keyboard row to human readable string. 159 * @param keys the keyboard row to be converted to string. 160 * @return the human readable representation of <code>keys</code>. 161 */ 162 public static String toString(final Key[] keys) { 163 return KeyStringizer.STRINGIZER.join(keys); 164 } 165 166 // Helper class to create concise representation from the array of the key. 167 static class KeyArrayStringizer extends StringUtils.Stringizer<Key[]> { 168 static final KeyArrayStringizer STRINGIZER = new KeyArrayStringizer(); 169 170 @Override 171 public String stringize(final Key[] keyArray) { 172 return KeyStringizer.STRINGIZER.join(keyArray); 173 } 174 } 175 176 /** 177 * Convert the keyboard to human readable string. 178 * @param rows the keyboard to be converted to string. 179 * @return the human readable representation of <code>rows</code>. 180 */ 181 public static String toString(final Key[][] rows) { 182 return KeyArrayStringizer.STRINGIZER.join(rows, "\n" /* delimiter */); 183 } 184} 185