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