1 /* 2 * Copyright (C) 2012 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.latin; 18 19 import static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; 20 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.IS_ADDITIONAL_SUBTYPE; 21 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET; 22 import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME; 23 24 import android.os.Build; 25 import android.text.TextUtils; 26 import android.view.inputmethod.InputMethodSubtype; 27 28 import java.util.ArrayList; 29 30 public final class AdditionalSubtype { 31 private static final InputMethodSubtype[] EMPTY_SUBTYPE_ARRAY = new InputMethodSubtype[0]; 32 33 private AdditionalSubtype() { 34 // This utility class is not publicly instantiable. 35 } 36 37 public static boolean isAdditionalSubtype(final InputMethodSubtype subtype) { 38 return subtype.containsExtraValueKey(IS_ADDITIONAL_SUBTYPE); 39 } 40 41 private static final String LOCALE_AND_LAYOUT_SEPARATOR = ":"; 42 private static final String PREF_SUBTYPE_SEPARATOR = ";"; 43 44 public static InputMethodSubtype createAdditionalSubtype(final String localeString, 45 final String keyboardLayoutSetName, final String extraValue) { 46 final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName; 47 final String layoutDisplayNameExtraValue; 48 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN 49 && SubtypeLocale.isExceptionalLocale(localeString)) { 50 final String layoutDisplayName = SubtypeLocale.getKeyboardLayoutSetDisplayName( 51 keyboardLayoutSetName); 52 layoutDisplayNameExtraValue = StringUtils.appendToCsvIfNotExists( 53 UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME + "=" + layoutDisplayName, extraValue); 54 } else { 55 layoutDisplayNameExtraValue = extraValue; 56 } 57 final String additionalSubtypeExtraValue = StringUtils.appendToCsvIfNotExists( 58 IS_ADDITIONAL_SUBTYPE, layoutDisplayNameExtraValue); 59 final int nameId = SubtypeLocale.getSubtypeNameId(localeString, keyboardLayoutSetName); 60 return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard, 61 localeString, KEYBOARD_MODE, 62 layoutExtraValue + "," + additionalSubtypeExtraValue, false, false); 63 } 64 65 public static String getPrefSubtype(final InputMethodSubtype subtype) { 66 final String localeString = subtype.getLocale(); 67 final String keyboardLayoutSetName = SubtypeLocale.getKeyboardLayoutSetName(subtype); 68 final String layoutExtraValue = KEYBOARD_LAYOUT_SET + "=" + keyboardLayoutSetName; 69 final String extraValue = StringUtils.removeFromCsvIfExists(layoutExtraValue, 70 StringUtils.removeFromCsvIfExists(IS_ADDITIONAL_SUBTYPE, subtype.getExtraValue())); 71 final String basePrefSubtype = localeString + LOCALE_AND_LAYOUT_SEPARATOR 72 + keyboardLayoutSetName; 73 return extraValue.isEmpty() ? basePrefSubtype 74 : basePrefSubtype + LOCALE_AND_LAYOUT_SEPARATOR + extraValue; 75 } 76 77 public static InputMethodSubtype createAdditionalSubtype(final String prefSubtype) { 78 final String elems[] = prefSubtype.split(LOCALE_AND_LAYOUT_SEPARATOR); 79 if (elems.length < 2 || elems.length > 3) { 80 throw new RuntimeException("Unknown additional subtype specified: " + prefSubtype); 81 } 82 final String localeString = elems[0]; 83 final String keyboardLayoutSetName = elems[1]; 84 final String extraValue = (elems.length == 3) ? elems[2] : null; 85 return createAdditionalSubtype(localeString, keyboardLayoutSetName, extraValue); 86 } 87 88 public static InputMethodSubtype[] createAdditionalSubtypesArray(final String prefSubtypes) { 89 if (TextUtils.isEmpty(prefSubtypes)) { 90 return EMPTY_SUBTYPE_ARRAY; 91 } 92 final String[] prefSubtypeArray = prefSubtypes.split(PREF_SUBTYPE_SEPARATOR); 93 final ArrayList<InputMethodSubtype> subtypesList = 94 CollectionUtils.newArrayList(prefSubtypeArray.length); 95 for (final String prefSubtype : prefSubtypeArray) { 96 final InputMethodSubtype subtype = createAdditionalSubtype(prefSubtype); 97 if (subtype.getNameResId() == SubtypeLocale.UNKNOWN_KEYBOARD_LAYOUT) { 98 // Skip unknown keyboard layout subtype. This may happen when predefined keyboard 99 // layout has been removed. 100 continue; 101 } 102 subtypesList.add(subtype); 103 } 104 return subtypesList.toArray(new InputMethodSubtype[subtypesList.size()]); 105 } 106 107 public static String createPrefSubtypes(final InputMethodSubtype[] subtypes) { 108 if (subtypes == null || subtypes.length == 0) { 109 return ""; 110 } 111 final StringBuilder sb = new StringBuilder(); 112 for (final InputMethodSubtype subtype : subtypes) { 113 if (sb.length() > 0) { 114 sb.append(PREF_SUBTYPE_SEPARATOR); 115 } 116 sb.append(getPrefSubtype(subtype)); 117 } 118 return sb.toString(); 119 } 120 121 public static String createPrefSubtypes(final String[] prefSubtypes) { 122 if (prefSubtypes == null || prefSubtypes.length == 0) { 123 return ""; 124 } 125 final StringBuilder sb = new StringBuilder(); 126 for (final String prefSubtype : prefSubtypes) { 127 if (sb.length() > 0) { 128 sb.append(PREF_SUBTYPE_SEPARATOR); 129 } 130 sb.append(prefSubtype); 131 } 132 return sb.toString(); 133 } 134 } 135