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.expected.ExpectedKey;
21 import com.android.inputmethod.keyboard.layout.expected.ExpectedKeyboardBuilder;
22 
23 import java.util.Locale;
24 
25 /**
26  * The PC QWERTY alphabet keyboard.
27  */
28 public final class PcQwerty extends LayoutBase {
29     private static final String LAYOUT_NAME = "pcqwerty";
30 
PcQwerty(final LayoutCustomizer customizer)31     public PcQwerty(final LayoutCustomizer customizer) {
32         super(customizer, Symbols.class, SymbolsShifted.class);
33     }
34 
35     @Override
getName()36     public String getName() { return LAYOUT_NAME; }
37 
38     public static class PcQwertyCustomizer extends LayoutCustomizer {
PcQwertyCustomizer(final Locale locale)39         public PcQwertyCustomizer(final Locale locale) { super(locale); }
40 
41         @Override
getNumberOfRows()42         public int getNumberOfRows() { return 5; }
43 
44         @Override
getLeftShiftKeys(final boolean isPhone)45         public ExpectedKey[] getLeftShiftKeys(final boolean isPhone) {
46             return joinKeys(SHIFT_KEY);
47         }
48 
49         @Override
getRightShiftKeys(final boolean isPhone)50         public ExpectedKey[] getRightShiftKeys(final boolean isPhone) {
51             return joinKeys(SHIFT_KEY);
52         }
53 
54         @Override
getKeysLeftToSpacebar(final boolean isPhone)55         public ExpectedKey[] getKeysLeftToSpacebar(final boolean isPhone) {
56             return joinKeys(SETTINGS_KEY);
57         }
58 
59         @Override
getKeysRightToSpacebar(final boolean isPhone)60         public ExpectedKey[] getKeysRightToSpacebar(final boolean isPhone) {
61             return isPhone
62                     ? joinKeys(key(ENTER_KEY, EMOJI_ACTION_KEY))
63                     : joinKeys(EMOJI_NORMAL_KEY);
64         }
65     }
66 
67     @Override
getCommonAlphabetLayout(final boolean isPhone)68     ExpectedKey[][] getCommonAlphabetLayout(final boolean isPhone) {
69         final LayoutCustomizer customizer = getCustomizer();
70         final ExpectedKeyboardBuilder builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON);
71         customizer.setAccentedLetters(builder);
72         builder.replaceKeyOfLabel(ROW1_1, key("`", moreKey("~")))
73                 .replaceKeyOfLabel(ROW2_11, key("[", moreKey("{")))
74                 .replaceKeyOfLabel(ROW2_12, key("]", moreKey("}")))
75                 .replaceKeyOfLabel(ROW2_13, key("\\", moreKey("|")))
76                 .replaceKeyOfLabel(ROW3_10, key(";", moreKey(":")))
77                 .replaceKeyOfLabel(ROW3_11, key("'", joinMoreKeys(additionalMoreKey("\""),
78                         customizer.getDoubleQuoteMoreKeys(),
79                         customizer.getSingleQuoteMoreKeys())))
80                 .setAdditionalMoreKeysPositionOf("'", 4)
81                 .replaceKeyOfLabel(ROW4_8, key(",", moreKey("<")))
82                 .replaceKeyOfLabel(ROW4_9, key(".", moreKey(">")))
83                 // U+00BF: "¿" INVERTED QUESTION MARK
84                 .replaceKeyOfLabel(ROW4_10, key("/", joinMoreKeys("?", "\u00BF")));
85         if (isPhone) {
86             // U+221E: "∞" INFINITY
87             // U+2260: "≠" NOT EQUAL TO
88             // U+2248: "≈" ALMOST EQUAL TO
89             builder.replaceKeyOfLabel(ROW1_13, key("=",
90                     joinMoreKeys("\u221E", "\u2260", "\u2248", "+")));
91         } else {
92             // U+221E: "∞" INFINITY
93             // U+2260: "≠" NOT EQUAL TO
94             // U+2248: "≈" ALMOST EQUAL TO
95             builder.replaceKeyOfLabel(ROW1_13, key("=",
96                     joinMoreKeys("+", "\u221E", "\u2260", "\u2248")));
97         }
98         return builder.build();
99     }
100 
101     @Override
getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId)102     ExpectedKey[][] getCommonAlphabetShiftLayout(final boolean isPhone, final int elementId) {
103         final ExpectedKeyboardBuilder builder;
104         if (elementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED
105                 || elementId == KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED) {
106             builder = new ExpectedKeyboardBuilder(getCommonAlphabetLayout(isPhone));
107         } else {
108             builder = new ExpectedKeyboardBuilder(ALPHABET_COMMON);
109             final LayoutCustomizer customizer = getCustomizer();
110             customizer.setAccentedLetters(builder);
111             builder.setKeysOfRow(1,
112                     "~",
113                     // U+00A1: "¡" INVERTED EXCLAMATION MARK
114                     key("!", moreKey("\u00A1")),
115                     "@", "#",
116                     customizer.getCurrencyKey(),
117                     // U+2030: "‰" PER MILLE SIGN
118                     key("%", moreKey("\u2030")),
119                     "^", "&",
120                     // U+2020: "†" DAGGER
121                     // U+2021: "‡" DOUBLE DAGGER
122                     // U+2605: "★" BLACK STAR
123                     key("*", joinMoreKeys("\u2020", "\u2021", "\u2605")),
124                     "(", ")", "_",
125                     // U+00B1: "±" PLUS-MINUS SIGN
126                     // U+00D7: "×" MULTIPLICATION SIGN
127                     // U+00F7: "÷" DIVISION SIGN
128                     // U+221A: "√" SQUARE ROOT
129                     key("+", joinMoreKeys("\u00B1", "\u00D7", "\u00F7", "\u221A")))
130                     .replaceKeyOfLabel(ROW2_11, key("{"))
131                     .replaceKeyOfLabel(ROW2_12, key("}"))
132                     .replaceKeyOfLabel(ROW2_13, key("|"))
133                     .replaceKeyOfLabel(ROW3_10, key(":"))
134                     .replaceKeyOfLabel(ROW3_11, key("\"", joinMoreKeys(
135                             customizer.getDoubleQuoteMoreKeys(),
136                             customizer.getSingleQuoteMoreKeys())))
137                     // U+2039: "‹" SINGLE LEFT-POINTING ANGLE QUOTATION MARK
138                     // U+2264: "≤" LESS-THAN OR EQUAL TO
139                     // U+00AB: "«" LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
140                     .replaceKeyOfLabel(ROW4_8, key("<", joinMoreKeys("\u2039", "\u2264", "\u00AB")))
141                     // U+203A: "›" SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
142                     // U+2265: "≥" GREATER-THAN EQUAL TO
143                     // U+00BB: "»" RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
144                     .replaceKeyOfLabel(ROW4_9, key(">", joinMoreKeys("\u203A", "\u2265", "\u00BB")))
145                     // U+00BF: "¿" INVERTED QUESTION MARK
146                     .replaceKeyOfLabel(ROW4_10, key("?", moreKey("\u00BF")));
147         }
148         builder.toUpperCase(getLocale());
149         return builder.build();
150     }
151 
152     // Helper method to create alphabet layout by adding special function keys.
153     @Override
convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder, final boolean isPhone)154     ExpectedKeyboardBuilder convertCommonLayoutToKeyboard(final ExpectedKeyboardBuilder builder,
155             final boolean isPhone) {
156         final LayoutCustomizer customizer = getCustomizer();
157         builder.setKeysOfRow(5, (Object[])customizer.getSpaceKeys(isPhone));
158         builder.addKeysOnTheLeftOfRow(5, (Object[])customizer.getKeysLeftToSpacebar(isPhone));
159         builder.addKeysOnTheRightOfRow(5, (Object[])customizer.getKeysRightToSpacebar(isPhone));
160         if (isPhone) {
161             builder.addKeysOnTheRightOfRow(3, DELETE_KEY);
162         } else {
163             builder.addKeysOnTheRightOfRow(1, DELETE_KEY)
164                     .addKeysOnTheLeftOfRow(2, TAB_KEY)
165                     .addKeysOnTheRightOfRow(3, ENTER_KEY);
166         }
167         builder.addKeysOnTheLeftOfRow(4, (Object[])customizer.getLeftShiftKeys(isPhone))
168                 .addKeysOnTheRightOfRow(4, (Object[])customizer.getRightShiftKeys(isPhone));
169         return builder;
170     }
171 
172     @Override
getLayout(final boolean isPhone, final int elementId)173     public ExpectedKey[][] getLayout(final boolean isPhone, final int elementId) {
174         if (elementId == KeyboardId.ELEMENT_SYMBOLS
175                 || elementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED) {
176             return null;
177         }
178         return super.getLayout(isPhone, elementId);
179     }
180 
181     private static final String ROW1_1 = "ROW1_1";
182     private static final String ROW1_13 = "ROW1_13";
183     private static final String ROW2_11 = "ROW2_11";
184     private static final String ROW2_12 = "ROW2_12";
185     private static final String ROW2_13 = "ROW2_13";
186     private static final String ROW3_10 = "ROW3_10";
187     private static final String ROW3_11 = "ROW3_11";
188     private static final String ROW4_8 = "ROW4_8";
189     private static final String ROW4_9 = "ROW4_9";
190     private static final String ROW4_10 = "ROW4_10";
191 
192     private static final ExpectedKey[][] ALPHABET_COMMON = new ExpectedKeyboardBuilder()
193             .setKeysOfRow(1,
194                     ROW1_1,
195                     // U+00A1: "¡" INVERTED EXCLAMATION MARK
196                     // U+00B9: "¹" SUPERSCRIPT ONE
197                     // U+00BD: "½" VULGAR FRACTION ONE HALF
198                     // U+2153: "⅓" VULGAR FRACTION ONE THIRD
199                     // U+00BC: "¼" VULGAR FRACTION ONE QUARTER
200                     // U+215B: "⅛" VULGAR FRACTION ONE EIGHTH
201                     key("1", joinMoreKeys(
202                             "!", "\u00A1", "\u00B9", "\u00BD", "\u2153", "\u00BC", "\u215B")),
203                     // U+00B2: "²" SUPERSCRIPT TWO
204                     // U+2154: "⅔" VULGAR FRACTION TWO THIRDS
205                     key("2", joinMoreKeys("@", "\u00B2", "\u2154")),
206                     // U+00B3: "³" SUPERSCRIPT THREE
207                     // U+00BE: "¾" VULGAR FRACTION THREE QUARTERS
208                     // U+215C: "⅜" VULGAR FRACTION THREE EIGHTHS
209                     key("3", joinMoreKeys("#", "\u00B3", "\u00BE", "\u215C")),
210                     // U+2074: "⁴" SUPERSCRIPT FOUR
211                     key("4", joinMoreKeys("$", "\u2074")),
212                     // U+215D: "⅝" VULGAR FRACTION FIVE EIGHTHS
213                     key("5", joinMoreKeys("%", "\u215D")),
214                     key("6", moreKey("^")),
215                     // U+215E: "⅞" VULGAR FRACTION SEVEN EIGHTHS
216                     key("7", joinMoreKeys("&", "\u215E")),
217                     key("8", moreKey("*")),
218                     key("9", moreKey("(")),
219                     // U+207F: "ⁿ" SUPERSCRIPT LATIN SMALL LETTER N
220                     // U+2205: "∅" EMPTY SET
221                     key("0", joinMoreKeys(")", "\u207F", "\u2205")),
222                     // U+2013: "–" EN DASH
223                     // U+2014: "—" EM DASH
224                     // U+00B7: "·" MIDDLE DOT
225                     key("-", joinMoreKeys("_", "\u2013", "\u2014", "\u00B7")),
226                     ROW1_13)
227             .setKeysOfRow(2, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
228                     ROW2_11, ROW2_12, ROW2_13)
229             .setKeysOfRow(3, "a", "s", "d", "f", "g", "h", "j", "k", "l", ROW3_10, ROW3_11)
230             .setKeysOfRow(4, "z", "x", "c", "v", "b", "n", "m", ROW4_8, ROW4_9, ROW4_10)
231             .build();
232 }
233