1 /* 2 * Copyright (C) 2018 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.car.settings.language; 18 19 import android.content.Context; 20 21 import androidx.annotation.Nullable; 22 import androidx.annotation.VisibleForTesting; 23 import androidx.preference.Preference; 24 import androidx.preference.PreferenceCategory; 25 import androidx.preference.PreferenceGroup; 26 27 import com.android.car.settings.common.Logger; 28 import com.android.car.settings.common.PreferenceUtil; 29 import com.android.car.settingslib.R; 30 import com.android.car.settingslib.language.LanguagePickerUtils; 31 import com.android.car.ui.preference.CarUiPreference; 32 import com.android.internal.app.LocaleStore; 33 import com.android.internal.app.SuggestedLocaleAdapter; 34 35 import java.util.Set; 36 37 /** 38 * Provides a wrapper around the {@link SuggestedLocaleAdapter} to create Preferences to populate 39 * the Language Settings screen. 40 */ 41 public class LocalePreferenceProvider { 42 43 private static final Logger LOG = new Logger(LanguagePickerPreferenceController.class); 44 45 /** Creates a new instance of the preference provider. */ newInstance(Context context, Set<LocaleStore.LocaleInfo> localeInfoSet, @Nullable LocaleStore.LocaleInfo parentLocale)46 public static LocalePreferenceProvider newInstance(Context context, 47 Set<LocaleStore.LocaleInfo> localeInfoSet, 48 @Nullable LocaleStore.LocaleInfo parentLocale) { 49 SuggestedLocaleAdapter adapter = LanguagePickerUtils.createSuggestedLocaleAdapter(context, 50 localeInfoSet, parentLocale); 51 return new LocalePreferenceProvider(context, adapter); 52 } 53 54 /** 55 * Header types are copied from {@link SuggestedLocaleAdapter} in order to be able to 56 * determine the header rows. 57 */ 58 @VisibleForTesting 59 static final int TYPE_HEADER_SUGGESTED = 0; 60 @VisibleForTesting 61 static final int TYPE_HEADER_ALL_OTHERS = 1; 62 @VisibleForTesting 63 static final int TYPE_LOCALE = 2; 64 65 private final Context mContext; 66 private SuggestedLocaleAdapter mSuggestedLocaleAdapter; 67 68 @VisibleForTesting LocalePreferenceProvider(Context context, SuggestedLocaleAdapter localeAdapter)69 LocalePreferenceProvider(Context context, SuggestedLocaleAdapter localeAdapter) { 70 mContext = context; 71 mSuggestedLocaleAdapter = localeAdapter; 72 } 73 74 /** 75 * Populates the base preference group based on the hierarchy provided by this provider. 76 * 77 * @param base the preference container which will hold the language preferences created by 78 * this provider 79 * @param listener the click listener registered to the language/locale preferences contained in 80 * the base preference group 81 */ populateBasePreference(PreferenceGroup base, Set<String> ignorables, Preference.OnPreferenceClickListener listener)82 public void populateBasePreference(PreferenceGroup base, Set<String> ignorables, 83 Preference.OnPreferenceClickListener listener) { 84 /* 85 * LocalePreferenceProvider can give elements to be represented in 2 ways. In the first 86 * way, it simply provides the LocalePreferences which lists the available options. In the 87 * second way, this provider may also provide PreferenceCategories to break up the 88 * options into "Suggested" and "All others". The screen is constructed by taking a look 89 * at the type of Preference that is provided through LocalePreferenceProvider. 90 * 91 * In the first case (no subcategories), preferences are added directly to the base 92 * container. Otherwise, elements are added to the last category that was provided 93 * (stored in "category"). 94 */ 95 PreferenceCategory category = null; 96 for (int position = 0; position < mSuggestedLocaleAdapter.getCount(); position++) { 97 Preference preference = getPreference(position, ignorables); 98 if (PreferenceUtil.checkPreferenceType(preference, PreferenceCategory.class)) { 99 category = (PreferenceCategory) preference; 100 base.addPreference(category); 101 } else { 102 preference.setOnPreferenceClickListener(listener); 103 if (category == null) { 104 base.addPreference(preference); 105 } else { 106 category.addPreference(preference); 107 } 108 } 109 } 110 } 111 112 /** 113 * Constructs a PreferenceCategory or Preference with locale arguments based on the type of item 114 * provided. 115 */ getPreference(int position, Set<String> ignorables)116 private Preference getPreference(int position, Set<String> ignorables) { 117 int type = mSuggestedLocaleAdapter.getItemViewType(position); 118 switch (type) { 119 case TYPE_HEADER_SUGGESTED: 120 case TYPE_HEADER_ALL_OTHERS: 121 PreferenceCategory category = new PreferenceCategory(mContext); 122 category.setTitle(type == TYPE_HEADER_SUGGESTED 123 ? R.string.language_picker_list_suggested_header 124 : R.string.language_picker_list_all_header); 125 return category; 126 case TYPE_LOCALE: 127 LocaleStore.LocaleInfo info = 128 (LocaleStore.LocaleInfo) mSuggestedLocaleAdapter.getItem(position); 129 CarUiPreference preference = new CarUiPreference(mContext); 130 preference.setTitle(info.getFullNameNative()); 131 // Only locales with multiple sublocales needs to show the chevron, since in those 132 // cases, the user needs to navigate to the child fragment to select the sublocale. 133 Set<LocaleStore.LocaleInfo> subLocales = LocaleStore.getLevelLocales( 134 mContext, 135 ignorables, 136 info, 137 /* translatedOnly */ true); 138 preference.setShowChevron(subLocales.size() > 1); 139 LocaleUtil.setLocaleArgument(preference, info); 140 return preference; 141 default: 142 LOG.d("Attempting to get unknown type: " + type); 143 throw new IllegalStateException("Unknown locale list item type"); 144 } 145 } 146 } 147