satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 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.systemui.statusbar.tablet; |
| 18 | |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 19 | import com.android.systemui.R; |
| 20 | |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 21 | import android.content.BroadcastReceiver; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 22 | import android.content.Context; |
| 23 | import android.content.Intent; |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 24 | import android.content.IntentFilter; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 25 | import android.content.pm.PackageManager; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 26 | import android.graphics.drawable.Drawable; |
| 27 | import android.os.IBinder; |
| 28 | import android.provider.Settings; |
| 29 | import android.text.TextUtils; |
| 30 | import android.util.AttributeSet; |
| 31 | import android.util.Log; |
| 32 | import android.util.Pair; |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 33 | import android.view.MotionEvent; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 34 | import android.view.View; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 35 | import android.view.inputmethod.InputMethodInfo; |
| 36 | import android.view.inputmethod.InputMethodManager; |
| 37 | import android.view.inputmethod.InputMethodSubtype; |
| 38 | import android.widget.ImageView; |
| 39 | import android.widget.LinearLayout; |
| 40 | import android.widget.RadioButton; |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 41 | import android.widget.Switch; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 42 | import android.widget.TextView; |
| 43 | |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 44 | import java.util.Comparator; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 45 | import java.util.HashMap; |
| 46 | import java.util.List; |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 47 | import java.util.Map; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 48 | import java.util.Set; |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 49 | import java.util.TreeMap; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 50 | |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 51 | public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, |
| 52 | View.OnClickListener { |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 53 | private static final boolean DEBUG = TabletStatusBar.DEBUG; |
| 54 | private static final String TAG = "InputMethodsPanel"; |
| 55 | |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 56 | private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { |
| 57 | @Override |
| 58 | public void onReceive(Context context, Intent intent) { |
| 59 | onPackageChanged(); |
| 60 | } |
| 61 | }; |
| 62 | |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 63 | private final InputMethodManager mImm; |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 64 | private final IntentFilter mIntentFilter = new IntentFilter(); |
| 65 | private final HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>> mRadioViewAndImiMap = |
| 66 | new HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>>(); |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 67 | private final TreeMap<InputMethodInfo, List<InputMethodSubtype>> |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 68 | mEnabledInputMethodAndSubtypesCache = |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 69 | new TreeMap<InputMethodInfo, List<InputMethodSubtype>>( |
| 70 | new InputMethodComparator()); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 71 | |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 72 | private boolean mAttached = false; |
| 73 | private boolean mPackageChanged = false; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 74 | private Context mContext; |
| 75 | private IBinder mToken; |
satok | 913f42d | 2011-01-17 16:58:10 +0900 | [diff] [blame] | 76 | private InputMethodButton mInputMethodSwitchButton; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 77 | private LinearLayout mInputMethodMenuList; |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 78 | private boolean mHardKeyboardAvailable; |
| 79 | private boolean mHardKeyboardEnabled; |
| 80 | private OnHardKeyboardEnabledChangeListener mHardKeyboardEnabledChangeListener; |
| 81 | private LinearLayout mHardKeyboardSection; |
| 82 | private Switch mHardKeyboardSwitch; |
satok | 913f42d | 2011-01-17 16:58:10 +0900 | [diff] [blame] | 83 | private PackageManager mPackageManager; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 84 | private String mEnabledInputMethodAndSubtypesCacheStr; |
satok | cf5f6d1 | 2011-01-28 12:16:31 +0900 | [diff] [blame] | 85 | private String mLastSystemLocaleString; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 86 | private View mConfigureImeShortcut; |
| 87 | |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 88 | private class InputMethodComparator implements Comparator<InputMethodInfo> { |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 89 | @Override |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 90 | public int compare(InputMethodInfo imi1, InputMethodInfo imi2) { |
| 91 | if (imi2 == null) return 0; |
| 92 | if (imi1 == null) return 1; |
Ken Wakasa | 761eb37 | 2011-03-04 19:06:18 +0900 | [diff] [blame] | 93 | if (mPackageManager == null) { |
| 94 | return imi1.getId().compareTo(imi2.getId()); |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 95 | } |
Ken Wakasa | 761eb37 | 2011-03-04 19:06:18 +0900 | [diff] [blame] | 96 | CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId(); |
| 97 | CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId(); |
| 98 | return imiId1.toString().compareTo(imiId2.toString()); |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 99 | } |
| 100 | } |
| 101 | |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 102 | public InputMethodsPanel(Context context, AttributeSet attrs) { |
| 103 | this(context, attrs, 0); |
| 104 | } |
| 105 | |
| 106 | public InputMethodsPanel(Context context, AttributeSet attrs, int defStyle) { |
| 107 | super(context, attrs, defStyle); |
| 108 | mContext = context; |
| 109 | mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 110 | mIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED); |
| 111 | mIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); |
| 112 | mIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); |
| 113 | mIntentFilter.addDataScheme("package"); |
| 114 | } |
| 115 | |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 116 | public void setHardKeyboardEnabledChangeListener( |
| 117 | OnHardKeyboardEnabledChangeListener listener) { |
| 118 | mHardKeyboardEnabledChangeListener = listener; |
| 119 | } |
| 120 | |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 121 | @Override |
| 122 | protected void onDetachedFromWindow() { |
| 123 | super.onDetachedFromWindow(); |
| 124 | if (mAttached) { |
| 125 | getContext().unregisterReceiver(mBroadcastReceiver); |
| 126 | mAttached = false; |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | @Override |
| 131 | protected void onAttachedToWindow() { |
| 132 | super.onAttachedToWindow(); |
| 133 | if (!mAttached) { |
| 134 | getContext().registerReceiver(mBroadcastReceiver, mIntentFilter); |
| 135 | mAttached = true; |
| 136 | } |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | @Override |
| 140 | public void onFinishInflate() { |
| 141 | mInputMethodMenuList = (LinearLayout) findViewById(R.id.input_method_menu_list); |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 142 | mHardKeyboardSection = (LinearLayout) findViewById(R.id.hard_keyboard_section); |
| 143 | mHardKeyboardSwitch = (Switch) findViewById(R.id.hard_keyboard_switch); |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 144 | mConfigureImeShortcut = findViewById(R.id.ime_settings_shortcut); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 145 | mConfigureImeShortcut.setOnClickListener(this); |
| 146 | // TODO: If configurations for IME are not changed, do not update |
| 147 | // by checking onConfigurationChanged. |
| 148 | updateUiElements(); |
| 149 | } |
| 150 | |
| 151 | @Override |
| 152 | public boolean isInContentArea(int x, int y) { |
| 153 | return false; |
| 154 | } |
| 155 | |
| 156 | @Override |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 157 | public void onClick(View view) { |
| 158 | if (view == mConfigureImeShortcut) { |
| 159 | showConfigureInputMethods(); |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 160 | closePanel(true); |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 161 | } |
| 162 | } |
| 163 | |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 164 | @Override |
| 165 | public boolean dispatchHoverEvent(MotionEvent event) { |
| 166 | // Ignore hover events outside of this panel bounds since such events |
| 167 | // generate spurious accessibility events with the panel content when |
| 168 | // tapping outside of it, thus confusing the user. |
| 169 | final int x = (int) event.getX(); |
| 170 | final int y = (int) event.getY(); |
| 171 | if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) { |
| 172 | return super.dispatchHoverEvent(event); |
| 173 | } |
| 174 | return true; |
| 175 | } |
| 176 | |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 177 | private void updateHardKeyboardEnabled() { |
| 178 | if (mHardKeyboardAvailable) { |
| 179 | final boolean checked = mHardKeyboardSwitch.isChecked(); |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 180 | if (mHardKeyboardEnabled != checked) { |
| 181 | mHardKeyboardEnabled = checked; |
| 182 | if (mHardKeyboardEnabledChangeListener != null) |
| 183 | mHardKeyboardEnabledChangeListener.onHardKeyboardEnabledChange(checked); |
| 184 | } |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 185 | } |
| 186 | } |
| 187 | |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 188 | public void openPanel() { |
| 189 | setVisibility(View.VISIBLE); |
| 190 | updateUiElements(); |
| 191 | if (mInputMethodSwitchButton != null) { |
| 192 | mInputMethodSwitchButton.setIconImage(R.drawable.ic_sysbar_ime_pressed); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | public void closePanel(boolean closeKeyboard) { |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 197 | setVisibility(View.GONE); |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 198 | if (mInputMethodSwitchButton != null) { |
| 199 | mInputMethodSwitchButton.setIconImage(R.drawable.ic_sysbar_ime); |
| 200 | } |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 201 | if (closeKeyboard) { |
| 202 | mImm.hideSoftInputFromWindow(getWindowToken(), 0); |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | private void startActivity(Intent intent) { |
| 207 | mContext.startActivity(intent); |
| 208 | } |
| 209 | |
| 210 | private void showConfigureInputMethods() { |
| 211 | Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS); |
| 212 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
| 213 | | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED |
| 214 | | Intent.FLAG_ACTIVITY_CLEAR_TOP); |
| 215 | startActivity(intent); |
| 216 | } |
| 217 | |
| 218 | private View createInputMethodItem( |
| 219 | final InputMethodInfo imi, final InputMethodSubtype subtype) { |
Ken Wakasa | e00633e | 2011-09-12 12:01:25 +0900 | [diff] [blame] | 220 | final CharSequence subtypeName; |
| 221 | if (subtype == null || subtype.overridesImplicitlyEnabledSubtype()) { |
| 222 | subtypeName = null; |
| 223 | } else { |
| 224 | subtypeName = getSubtypeName(imi, subtype); |
| 225 | } |
Ken Wakasa | bbf0b66 | 2011-09-10 01:47:49 +0900 | [diff] [blame] | 226 | final CharSequence imiName = getIMIName(imi); |
| 227 | final Drawable icon = getSubtypeIcon(imi, subtype); |
Daniel Sandler | 4a066c5 | 2012-04-20 14:49:13 -0400 | [diff] [blame] | 228 | final View view = View.inflate(mContext, R.layout.system_bar_input_methods_item, null); |
Ken Wakasa | bbf0b66 | 2011-09-10 01:47:49 +0900 | [diff] [blame] | 229 | final ImageView subtypeIcon = (ImageView)view.findViewById(R.id.item_icon); |
| 230 | final TextView itemTitle = (TextView)view.findViewById(R.id.item_title); |
| 231 | final TextView itemSubtitle = (TextView)view.findViewById(R.id.item_subtitle); |
| 232 | final ImageView settingsIcon = (ImageView)view.findViewById(R.id.item_settings_icon); |
| 233 | final View subtypeView = view.findViewById(R.id.item_subtype); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 234 | if (subtypeName == null) { |
| 235 | itemTitle.setText(imiName); |
| 236 | itemSubtitle.setVisibility(View.GONE); |
| 237 | } else { |
| 238 | itemTitle.setText(subtypeName); |
| 239 | itemSubtitle.setVisibility(View.VISIBLE); |
| 240 | itemSubtitle.setText(imiName); |
| 241 | } |
| 242 | subtypeIcon.setImageDrawable(icon); |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 243 | subtypeIcon.setContentDescription(itemTitle.getText()); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 244 | final String settingsActivity = imi.getSettingsActivity(); |
| 245 | if (!TextUtils.isEmpty(settingsActivity)) { |
| 246 | settingsIcon.setOnClickListener(new View.OnClickListener() { |
| 247 | @Override |
| 248 | public void onClick(View arg0) { |
| 249 | Intent intent = new Intent(Intent.ACTION_MAIN); |
| 250 | intent.setClassName(imi.getPackageName(), settingsActivity); |
| 251 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
| 252 | | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED |
| 253 | | Intent.FLAG_ACTIVITY_CLEAR_TOP); |
| 254 | startActivity(intent); |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 255 | closePanel(true); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 256 | } |
| 257 | }); |
| 258 | } else { |
| 259 | // Do not show the settings icon if the IME does not have a settings preference |
| 260 | view.findViewById(R.id.item_vertical_separator).setVisibility(View.GONE); |
| 261 | settingsIcon.setVisibility(View.GONE); |
| 262 | } |
| 263 | mRadioViewAndImiMap.put( |
| 264 | subtypeView, new Pair<InputMethodInfo, InputMethodSubtype> (imi, subtype)); |
| 265 | subtypeView.setOnClickListener(new View.OnClickListener() { |
| 266 | @Override |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 267 | public void onClick(View v) { |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 268 | Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype = |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 269 | updateRadioButtonsByView(v); |
Tadashi G. Takaoka | e385f0c | 2011-02-01 02:57:44 +0900 | [diff] [blame] | 270 | closePanel(false); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 271 | setInputMethodAndSubtype(imiAndSubtype.first, imiAndSubtype.second); |
| 272 | } |
| 273 | }); |
| 274 | return view; |
| 275 | } |
| 276 | |
| 277 | private void updateUiElements() { |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 278 | updateHardKeyboardSection(); |
| 279 | |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 280 | // TODO: Reuse subtype views. |
| 281 | mInputMethodMenuList.removeAllViews(); |
| 282 | mRadioViewAndImiMap.clear(); |
satok | 913f42d | 2011-01-17 16:58:10 +0900 | [diff] [blame] | 283 | mPackageManager = mContext.getPackageManager(); |
| 284 | |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 285 | Map<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs = |
| 286 | getEnabledInputMethodAndSubtypeList(); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 287 | Set<InputMethodInfo> cachedImiSet = enabledIMIs.keySet(); |
| 288 | for (InputMethodInfo imi: cachedImiSet) { |
| 289 | List<InputMethodSubtype> subtypes = enabledIMIs.get(imi); |
| 290 | if (subtypes == null || subtypes.size() == 0) { |
| 291 | mInputMethodMenuList.addView( |
| 292 | createInputMethodItem(imi, null)); |
| 293 | continue; |
| 294 | } |
| 295 | for (InputMethodSubtype subtype: subtypes) { |
| 296 | mInputMethodMenuList.addView(createInputMethodItem(imi, subtype)); |
| 297 | } |
| 298 | } |
| 299 | updateRadioButtons(); |
| 300 | } |
| 301 | |
satok | 913f42d | 2011-01-17 16:58:10 +0900 | [diff] [blame] | 302 | public void setImeToken(IBinder token) { |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 303 | mToken = token; |
| 304 | } |
| 305 | |
satok | 913f42d | 2011-01-17 16:58:10 +0900 | [diff] [blame] | 306 | public void setImeSwitchButton(InputMethodButton imb) { |
| 307 | mInputMethodSwitchButton = imb; |
| 308 | } |
| 309 | |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 310 | private void setInputMethodAndSubtype(InputMethodInfo imi, InputMethodSubtype subtype) { |
| 311 | if (mToken != null) { |
| 312 | mImm.setInputMethodAndSubtype(mToken, imi.getId(), subtype); |
| 313 | } else { |
| 314 | Log.w(TAG, "IME Token is not set yet."); |
| 315 | } |
| 316 | } |
| 317 | |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 318 | public void setHardKeyboardStatus(boolean available, boolean enabled) { |
| 319 | if (mHardKeyboardAvailable != available || mHardKeyboardEnabled != enabled) { |
| 320 | mHardKeyboardAvailable = available; |
| 321 | mHardKeyboardEnabled = enabled; |
| 322 | updateHardKeyboardSection(); |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | private void updateHardKeyboardSection() { |
| 327 | if (mHardKeyboardAvailable) { |
| 328 | mHardKeyboardSection.setVisibility(View.VISIBLE); |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 329 | if (mHardKeyboardSwitch.isChecked() != mHardKeyboardEnabled) { |
| 330 | mHardKeyboardSwitch.setChecked(mHardKeyboardEnabled); |
satok | 0103849 | 2012-04-09 21:08:27 +0900 | [diff] [blame] | 331 | updateHardKeyboardEnabled(); |
Tadashi G. Takaoka | 1c9debf | 2011-01-31 18:39:27 +0900 | [diff] [blame] | 332 | } |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 333 | } else { |
| 334 | mHardKeyboardSection.setVisibility(View.GONE); |
| 335 | } |
| 336 | } |
| 337 | |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 338 | // Turn on the selected radio button when the user chooses the item |
| 339 | private Pair<InputMethodInfo, InputMethodSubtype> updateRadioButtonsByView(View selectedView) { |
| 340 | Pair<InputMethodInfo, InputMethodSubtype> selectedImiAndSubtype = null; |
| 341 | if (mRadioViewAndImiMap.containsKey(selectedView)) { |
| 342 | for (View radioView: mRadioViewAndImiMap.keySet()) { |
| 343 | RadioButton subtypeRadioButton = |
| 344 | (RadioButton) radioView.findViewById(R.id.item_radio); |
| 345 | if (subtypeRadioButton == null) { |
| 346 | Log.w(TAG, "RadioButton was not found in the selected subtype view"); |
| 347 | return null; |
| 348 | } |
| 349 | if (radioView == selectedView) { |
| 350 | Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype = |
| 351 | mRadioViewAndImiMap.get(radioView); |
| 352 | selectedImiAndSubtype = imiAndSubtype; |
| 353 | subtypeRadioButton.setChecked(true); |
| 354 | } else { |
| 355 | subtypeRadioButton.setChecked(false); |
| 356 | } |
| 357 | } |
| 358 | } |
| 359 | return selectedImiAndSubtype; |
| 360 | } |
| 361 | |
| 362 | private void updateRadioButtons() { |
| 363 | updateRadioButtonsByImiAndSubtype( |
| 364 | getCurrentInputMethodInfo(), mImm.getCurrentInputMethodSubtype()); |
| 365 | } |
| 366 | |
| 367 | // Turn on the selected radio button at startup |
| 368 | private void updateRadioButtonsByImiAndSubtype( |
| 369 | InputMethodInfo imi, InputMethodSubtype subtype) { |
satok | f6cafb6 | 2011-01-17 16:29:02 +0900 | [diff] [blame] | 370 | if (imi == null) return; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 371 | if (DEBUG) { |
| 372 | Log.d(TAG, "Update radio buttons by " + imi.getId() + ", " + subtype); |
| 373 | } |
| 374 | for (View radioView: mRadioViewAndImiMap.keySet()) { |
| 375 | RadioButton subtypeRadioButton = |
| 376 | (RadioButton) radioView.findViewById(R.id.item_radio); |
| 377 | if (subtypeRadioButton == null) { |
| 378 | Log.w(TAG, "RadioButton was not found in the selected subtype view"); |
| 379 | return; |
| 380 | } |
| 381 | Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype = |
satok | f6cafb6 | 2011-01-17 16:29:02 +0900 | [diff] [blame] | 382 | mRadioViewAndImiMap.get(radioView); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 383 | if (imiAndSubtype.first.getId().equals(imi.getId()) |
| 384 | && (imiAndSubtype.second == null || imiAndSubtype.second.equals(subtype))) { |
| 385 | subtypeRadioButton.setChecked(true); |
| 386 | } else { |
| 387 | subtypeRadioButton.setChecked(false); |
| 388 | } |
| 389 | } |
| 390 | } |
| 391 | |
satok | 7dc93a1 | 2011-01-25 18:00:23 +0900 | [diff] [blame] | 392 | private TreeMap<InputMethodInfo, List<InputMethodSubtype>> |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 393 | getEnabledInputMethodAndSubtypeList() { |
| 394 | String newEnabledIMIs = Settings.Secure.getString( |
| 395 | mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS); |
satok | cf5f6d1 | 2011-01-28 12:16:31 +0900 | [diff] [blame] | 396 | String currentSystemLocaleString = |
| 397 | mContext.getResources().getConfiguration().locale.toString(); |
| 398 | if (!TextUtils.equals(mEnabledInputMethodAndSubtypesCacheStr, newEnabledIMIs) |
| 399 | || !TextUtils.equals(mLastSystemLocaleString, currentSystemLocaleString) |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 400 | || mPackageChanged) { |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 401 | mEnabledInputMethodAndSubtypesCache.clear(); |
| 402 | final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList(); |
| 403 | for (InputMethodInfo imi: imis) { |
| 404 | mEnabledInputMethodAndSubtypesCache.put(imi, |
| 405 | mImm.getEnabledInputMethodSubtypeList(imi, true)); |
| 406 | } |
| 407 | mEnabledInputMethodAndSubtypesCacheStr = newEnabledIMIs; |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 408 | mPackageChanged = false; |
satok | cf5f6d1 | 2011-01-28 12:16:31 +0900 | [diff] [blame] | 409 | mLastSystemLocaleString = currentSystemLocaleString; |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 410 | } |
| 411 | return mEnabledInputMethodAndSubtypesCache; |
| 412 | } |
| 413 | |
| 414 | private InputMethodInfo getCurrentInputMethodInfo() { |
| 415 | String curInputMethodId = Settings.Secure.getString(getContext() |
| 416 | .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); |
| 417 | Set<InputMethodInfo> cachedImiSet = mEnabledInputMethodAndSubtypesCache.keySet(); |
| 418 | // 1. Search IMI in cache |
| 419 | for (InputMethodInfo imi: cachedImiSet) { |
| 420 | if (imi.getId().equals(curInputMethodId)) { |
| 421 | return imi; |
| 422 | } |
| 423 | } |
| 424 | // 2. Get current enabled IMEs and search IMI |
| 425 | cachedImiSet = getEnabledInputMethodAndSubtypeList().keySet(); |
| 426 | for (InputMethodInfo imi: cachedImiSet) { |
| 427 | if (imi.getId().equals(curInputMethodId)) { |
| 428 | return imi; |
| 429 | } |
| 430 | } |
| 431 | return null; |
| 432 | } |
| 433 | |
| 434 | private CharSequence getIMIName(InputMethodInfo imi) { |
| 435 | if (imi == null) return null; |
satok | 209cf04 | 2011-08-31 20:16:17 +0900 | [diff] [blame] | 436 | return imi.loadLabel(mPackageManager); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 437 | } |
| 438 | |
| 439 | private CharSequence getSubtypeName(InputMethodInfo imi, InputMethodSubtype subtype) { |
| 440 | if (imi == null || subtype == null) return null; |
satok | 913f42d | 2011-01-17 16:58:10 +0900 | [diff] [blame] | 441 | if (DEBUG) { |
| 442 | Log.d(TAG, "Get text from: " + imi.getPackageName() + subtype.getNameResId() |
| 443 | + imi.getServiceInfo().applicationInfo); |
| 444 | } |
satok | 4f31353 | 2011-06-01 16:13:45 +0900 | [diff] [blame] | 445 | return subtype.getDisplayName( |
| 446 | mContext, imi.getPackageName(), imi.getServiceInfo().applicationInfo); |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 447 | } |
| 448 | |
| 449 | private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) { |
| 450 | if (imi != null) { |
| 451 | if (DEBUG) { |
| 452 | Log.d(TAG, "Update icons of IME: " + imi.getPackageName()); |
| 453 | if (subtype != null) { |
| 454 | Log.d(TAG, "subtype =" + subtype.getLocale() + "," + subtype.getMode()); |
| 455 | } |
| 456 | } |
| 457 | if (subtype != null) { |
| 458 | return mPackageManager.getDrawable(imi.getPackageName(), subtype.getIconResId(), |
| 459 | imi.getServiceInfo().applicationInfo); |
Ken Wakasa | 586f051 | 2011-01-20 22:31:01 +0900 | [diff] [blame] | 460 | } else if (imi.getSubtypeCount() > 0) { |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 461 | return mPackageManager.getDrawable(imi.getPackageName(), |
Ken Wakasa | 586f051 | 2011-01-20 22:31:01 +0900 | [diff] [blame] | 462 | imi.getSubtypeAt(0).getIconResId(), |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 463 | imi.getServiceInfo().applicationInfo); |
| 464 | } else { |
| 465 | try { |
| 466 | return mPackageManager.getApplicationInfo( |
| 467 | imi.getPackageName(), 0).loadIcon(mPackageManager); |
| 468 | } catch (PackageManager.NameNotFoundException e) { |
| 469 | Log.w(TAG, "IME can't be found: " + imi.getPackageName()); |
| 470 | } |
| 471 | } |
| 472 | } |
| 473 | return null; |
| 474 | } |
satok | 0ee6613 | 2011-01-26 16:57:50 +0900 | [diff] [blame] | 475 | |
| 476 | private void onPackageChanged() { |
| 477 | if (DEBUG) { |
| 478 | Log.d(TAG, "onPackageChanged."); |
| 479 | } |
| 480 | mPackageChanged = true; |
| 481 | } |
Jeff Brown | 2992ea7 | 2011-01-28 22:04:14 -0800 | [diff] [blame] | 482 | |
| 483 | public interface OnHardKeyboardEnabledChangeListener { |
| 484 | public void onHardKeyboardEnabledChange(boolean enabled); |
| 485 | } |
Svetoslav Ganov | 6179ea3 | 2011-06-28 01:12:41 -0700 | [diff] [blame] | 486 | |
satok | 82beadf | 2010-12-27 19:03:06 +0900 | [diff] [blame] | 487 | } |