Merge "Add input methods settings panel" into honeycomb
This commit is contained in:
@@ -2403,6 +2403,8 @@
|
||||
|
||||
<!-- Title of the pop-up dialog in which the user switches input method components. -->
|
||||
<string name="select_input_method">Select input method</string>
|
||||
<!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
|
||||
<string name="configure_input_methods">Configure input methods</string>
|
||||
|
||||
<string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
|
||||
<string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright 2011, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:background="@drawable/status_bar_item_background"
|
||||
android:orientation="vertical"
|
||||
android:paddingRight="6dip"
|
||||
android:paddingLeft="6dip"
|
||||
android:paddingTop="5dip"
|
||||
android:paddingBottom="5dip"
|
||||
android:gravity="center_vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
<LinearLayout
|
||||
android:id="@+id/item_subtype"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
<RadioButton
|
||||
android:id="@+id/item_radio"
|
||||
android:layout_width="30dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="11dip"
|
||||
android:focusable="false"
|
||||
android:clickable="false" />
|
||||
<ImageView
|
||||
android:id="@+id/item_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitCenter" />
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="0px"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:id="@+id/item_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_marginBottom="2dip" />
|
||||
<TextView
|
||||
android:id="@+id/item_subtitle"
|
||||
android:layout_marginTop="-4dip"
|
||||
android:layout_gravity="center_vertical|left"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:id="@+id/item_vertical_separator"
|
||||
android:layout_width="2dip"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="5dip"
|
||||
android:background="@android:drawable/divider_horizontal_dark" />
|
||||
<ImageView
|
||||
android:id="@+id/item_settings_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingRight="10dip"
|
||||
android:paddingLeft="10dip"
|
||||
android:src="@drawable/ic_sysbar_quicksettings"
|
||||
android:visibility="visible"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?android:attr/selectableItemBackground" />
|
||||
</LinearLayout>
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dip"
|
||||
android:background="@android:drawable/divider_horizontal_dark" />
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
**
|
||||
** Copyright 2011, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<com.android.systemui.statusbar.tablet.InputMethodsPanel
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingBottom="28dip"
|
||||
android:orientation="vertical">
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1" />
|
||||
<FrameLayout
|
||||
android:id="@+id/glow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/recents_blue_glow">
|
||||
<LinearLayout
|
||||
android:layout_width="450dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="20dip"
|
||||
android:orientation="vertical"
|
||||
android:background="@*android:drawable/dialog_full_holo_dark">
|
||||
<ScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
android:layout_marginTop="3dip"
|
||||
android:layout_weight="1">
|
||||
<LinearLayout
|
||||
android:id="@+id/input_method_menu_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
</ScrollView>
|
||||
<TextView
|
||||
android:id="@+id/ime_settings_shortcut"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
android:paddingRight="6dip"
|
||||
android:paddingLeft="30dip"
|
||||
android:paddingTop="5dip"
|
||||
android:paddingBottom="5dip"
|
||||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:text="@string/status_bar_input_method_settings_configure_input_methods"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:ellipsize="marquee" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
</com.android.systemui.statusbar.tablet.InputMethodsPanel>
|
||||
@@ -109,5 +109,7 @@
|
||||
<string name="recent_tasks_app_label">Apps</string>
|
||||
|
||||
<!-- Network connection string for Bluetooth Reverse Tethering -->
|
||||
<string name="bluetooth_tethered">Bluetooth tethered"</string>
|
||||
<string name="bluetooth_tethered">Bluetooth tethered</string>
|
||||
<!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
|
||||
<string name="status_bar_input_method_settings_configure_input_methods">Configure input methods</string>
|
||||
</resources>
|
||||
|
||||
@@ -19,11 +19,9 @@ package com.android.systemui.statusbar.tablet;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
@@ -31,11 +29,8 @@ import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.server.InputMethodManagerService;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -56,9 +51,6 @@ public class InputMethodButton extends ImageView {
|
||||
// other services we wish to talk to
|
||||
private final InputMethodManager mImm;
|
||||
private final int mId;
|
||||
// Cache of InputMethodsInfo
|
||||
private final HashMap<String, InputMethodInfo> mInputMethodsInfo =
|
||||
new HashMap<String, InputMethodInfo>();
|
||||
private ImageView mIcon;
|
||||
private IBinder mToken;
|
||||
private boolean mKeyboardVisible = false;
|
||||
@@ -102,20 +94,6 @@ public class InputMethodButton extends ImageView {
|
||||
refreshStatusIcon();
|
||||
}
|
||||
|
||||
private InputMethodInfo getCurrentInputMethodInfo() {
|
||||
String curInputMethodId = Settings.Secure.getString(getContext()
|
||||
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
if (!mInputMethodsInfo.containsKey(curInputMethodId)) {
|
||||
mInputMethodsInfo.clear();
|
||||
List<InputMethodInfo> imis = mImm.getInputMethodList();
|
||||
for (int i = 0; i < imis.size(); ++i) {
|
||||
InputMethodInfo imi = imis.get(i);
|
||||
mInputMethodsInfo.put(imi.getId(), imi);
|
||||
}
|
||||
}
|
||||
return mInputMethodsInfo.get(curInputMethodId);
|
||||
}
|
||||
|
||||
// TODO: Need to show an appropriate drawable for this shortcut button,
|
||||
// if there are two or more shortcut input methods contained in this button.
|
||||
// And need to add other methods to handle multiple shortcuts as appropriate.
|
||||
@@ -141,8 +119,7 @@ public class InputMethodButton extends ImageView {
|
||||
final PackageManager pm = getContext().getPackageManager();
|
||||
if (imi != null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Update icons of IME: " + imi.getPackageName() + ","
|
||||
+ subtype.getLocale() + "," + subtype.getMode());
|
||||
Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
|
||||
}
|
||||
if (subtype != null) {
|
||||
return pm.getDrawable(imi.getPackageName(), subtype.getIconResId(),
|
||||
@@ -188,25 +165,19 @@ public class InputMethodButton extends ImageView {
|
||||
return;
|
||||
}
|
||||
if (!needsToShowIMEButton()) {
|
||||
setVisibility(View.INVISIBLE);
|
||||
setVisibility(View.GONE);
|
||||
return;
|
||||
} else {
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
Drawable icon = null;
|
||||
switch (mId) {
|
||||
case ID_IME_SWITCH_BUTTON:
|
||||
// TODO: Just showing the first shortcut IME subtype for now. Should handle all
|
||||
// shortcuts as appropriate.
|
||||
icon = getSubtypeIcon(getCurrentInputMethodInfo(),
|
||||
mImm.getCurrentInputMethodSubtype());
|
||||
break;
|
||||
case ID_IME_SHORTCUT_BUTTON:
|
||||
icon = getShortcutInputMethodAndSubtypeDrawable();
|
||||
break;
|
||||
}
|
||||
if (icon == null) {
|
||||
mIcon.setImageResource(R.drawable.ic_sysbar_ime_default);
|
||||
mIcon.setImageResource(R.drawable.ic_sysbar_ime);
|
||||
} else {
|
||||
mIcon.setImageDrawable(icon);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar.tablet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.inputmethod.InputMethodInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, OnClickListener {
|
||||
private static final boolean DEBUG = TabletStatusBar.DEBUG;
|
||||
private static final String TAG = "InputMethodsPanel";
|
||||
|
||||
private final InputMethodManager mImm;
|
||||
private final HashMap<InputMethodInfo, List<InputMethodSubtype>>
|
||||
mEnabledInputMethodAndSubtypesCache =
|
||||
new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
|
||||
private final HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>> mRadioViewAndImiMap =
|
||||
new HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>>();
|
||||
private final PackageManager mPackageManager;
|
||||
|
||||
private Context mContext;
|
||||
private IBinder mToken;
|
||||
private LinearLayout mInputMethodMenuList;
|
||||
private String mEnabledInputMethodAndSubtypesCacheStr;
|
||||
private View mConfigureImeShortcut;
|
||||
|
||||
public InputMethodsPanel(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public InputMethodsPanel(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mContext = context;
|
||||
mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
mPackageManager = context.getPackageManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishInflate() {
|
||||
mInputMethodMenuList = (LinearLayout) findViewById(R.id.input_method_menu_list);
|
||||
mConfigureImeShortcut = ((View) findViewById(R.id.ime_settings_shortcut));
|
||||
mConfigureImeShortcut.setOnClickListener(this);
|
||||
// TODO: If configurations for IME are not changed, do not update
|
||||
// by checking onConfigurationChanged.
|
||||
updateUiElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInContentArea(int x, int y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onVisibilityChanged(View changedView, int visibility) {
|
||||
super.onVisibilityChanged(changedView, visibility);
|
||||
if (visibility == View.VISIBLE && changedView == this) {
|
||||
updateUiElements();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (view == mConfigureImeShortcut) {
|
||||
showConfigureInputMethods();
|
||||
onFinishPanel(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void onFinishPanel(boolean closeKeyboard) {
|
||||
setVisibility(View.GONE);
|
||||
if (closeKeyboard) {
|
||||
mImm.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void startActivity(Intent intent) {
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
private void showConfigureInputMethods() {
|
||||
Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private View createInputMethodItem(
|
||||
final InputMethodInfo imi, final InputMethodSubtype subtype) {
|
||||
CharSequence subtypeName = getSubtypeName(imi, subtype);
|
||||
CharSequence imiName = getIMIName(imi);
|
||||
Drawable icon = getSubtypeIcon(imi, subtype);
|
||||
View view = View.inflate(mContext, R.layout.status_bar_input_methods_item, null);
|
||||
ImageView subtypeIcon = (ImageView)view.findViewById(R.id.item_icon);
|
||||
TextView itemTitle = (TextView)view.findViewById(R.id.item_title);
|
||||
TextView itemSubtitle = (TextView)view.findViewById(R.id.item_subtitle);
|
||||
ImageView settingsIcon = (ImageView)view.findViewById(R.id.item_settings_icon);
|
||||
View subtypeView = view.findViewById(R.id.item_subtype);
|
||||
if (subtypeName == null) {
|
||||
itemTitle.setText(imiName);
|
||||
itemSubtitle.setVisibility(View.GONE);
|
||||
} else {
|
||||
itemTitle.setText(subtypeName);
|
||||
itemSubtitle.setVisibility(View.VISIBLE);
|
||||
itemSubtitle.setText(imiName);
|
||||
}
|
||||
subtypeIcon.setImageDrawable(icon);
|
||||
final String settingsActivity = imi.getSettingsActivity();
|
||||
if (!TextUtils.isEmpty(settingsActivity)) {
|
||||
settingsIcon.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View arg0) {
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setClassName(imi.getPackageName(), settingsActivity);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(intent);
|
||||
onFinishPanel(true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Do not show the settings icon if the IME does not have a settings preference
|
||||
view.findViewById(R.id.item_vertical_separator).setVisibility(View.GONE);
|
||||
settingsIcon.setVisibility(View.GONE);
|
||||
}
|
||||
mRadioViewAndImiMap.put(
|
||||
subtypeView, new Pair<InputMethodInfo, InputMethodSubtype> (imi, subtype));
|
||||
subtypeView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
|
||||
updateRadioButtonsByView(view);
|
||||
onFinishPanel(false);
|
||||
setInputMethodAndSubtype(imiAndSubtype.first, imiAndSubtype.second);
|
||||
}
|
||||
});
|
||||
return view;
|
||||
}
|
||||
|
||||
private void updateUiElements() {
|
||||
// TODO: Reuse subtype views.
|
||||
mInputMethodMenuList.removeAllViews();
|
||||
mRadioViewAndImiMap.clear();
|
||||
HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs
|
||||
= getEnabledInputMethodAndSubtypeList();
|
||||
// TODO: Sort by alphabet and mode.
|
||||
Set<InputMethodInfo> cachedImiSet = enabledIMIs.keySet();
|
||||
for (InputMethodInfo imi: cachedImiSet) {
|
||||
List<InputMethodSubtype> subtypes = enabledIMIs.get(imi);
|
||||
if (subtypes == null || subtypes.size() == 0) {
|
||||
mInputMethodMenuList.addView(
|
||||
createInputMethodItem(imi, null));
|
||||
continue;
|
||||
}
|
||||
for (InputMethodSubtype subtype: subtypes) {
|
||||
mInputMethodMenuList.addView(createInputMethodItem(imi, subtype));
|
||||
}
|
||||
}
|
||||
updateRadioButtons();
|
||||
}
|
||||
|
||||
public void setIMEToken(IBinder token) {
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
private void setInputMethodAndSubtype(InputMethodInfo imi, InputMethodSubtype subtype) {
|
||||
if (mToken != null) {
|
||||
mImm.setInputMethodAndSubtype(mToken, imi.getId(), subtype);
|
||||
} else {
|
||||
Log.w(TAG, "IME Token is not set yet.");
|
||||
}
|
||||
}
|
||||
|
||||
// Turn on the selected radio button when the user chooses the item
|
||||
private Pair<InputMethodInfo, InputMethodSubtype> updateRadioButtonsByView(View selectedView) {
|
||||
Pair<InputMethodInfo, InputMethodSubtype> selectedImiAndSubtype = null;
|
||||
if (mRadioViewAndImiMap.containsKey(selectedView)) {
|
||||
for (View radioView: mRadioViewAndImiMap.keySet()) {
|
||||
RadioButton subtypeRadioButton =
|
||||
(RadioButton) radioView.findViewById(R.id.item_radio);
|
||||
if (subtypeRadioButton == null) {
|
||||
Log.w(TAG, "RadioButton was not found in the selected subtype view");
|
||||
return null;
|
||||
}
|
||||
if (radioView == selectedView) {
|
||||
Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
|
||||
mRadioViewAndImiMap.get(radioView);
|
||||
selectedImiAndSubtype = imiAndSubtype;
|
||||
subtypeRadioButton.setChecked(true);
|
||||
} else {
|
||||
subtypeRadioButton.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedImiAndSubtype;
|
||||
}
|
||||
|
||||
private void updateRadioButtons() {
|
||||
updateRadioButtonsByImiAndSubtype(
|
||||
getCurrentInputMethodInfo(), mImm.getCurrentInputMethodSubtype());
|
||||
}
|
||||
|
||||
// Turn on the selected radio button at startup
|
||||
private void updateRadioButtonsByImiAndSubtype(
|
||||
InputMethodInfo imi, InputMethodSubtype subtype) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Update radio buttons by " + imi.getId() + ", " + subtype);
|
||||
}
|
||||
for (View radioView: mRadioViewAndImiMap.keySet()) {
|
||||
RadioButton subtypeRadioButton =
|
||||
(RadioButton) radioView.findViewById(R.id.item_radio);
|
||||
if (subtypeRadioButton == null) {
|
||||
Log.w(TAG, "RadioButton was not found in the selected subtype view");
|
||||
return;
|
||||
}
|
||||
Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
|
||||
mRadioViewAndImiMap.get(radioView);
|
||||
if (imiAndSubtype.first.getId().equals(imi.getId())
|
||||
&& (imiAndSubtype.second == null || imiAndSubtype.second.equals(subtype))) {
|
||||
subtypeRadioButton.setChecked(true);
|
||||
} else {
|
||||
subtypeRadioButton.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<InputMethodInfo, List<InputMethodSubtype>>
|
||||
getEnabledInputMethodAndSubtypeList() {
|
||||
String newEnabledIMIs = Settings.Secure.getString(
|
||||
mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS);
|
||||
if (mEnabledInputMethodAndSubtypesCacheStr == null
|
||||
|| !mEnabledInputMethodAndSubtypesCacheStr.equals(newEnabledIMIs)) {
|
||||
mEnabledInputMethodAndSubtypesCache.clear();
|
||||
final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
|
||||
for (InputMethodInfo imi: imis) {
|
||||
mEnabledInputMethodAndSubtypesCache.put(imi,
|
||||
mImm.getEnabledInputMethodSubtypeList(imi, true));
|
||||
}
|
||||
mEnabledInputMethodAndSubtypesCacheStr = newEnabledIMIs;
|
||||
}
|
||||
return mEnabledInputMethodAndSubtypesCache;
|
||||
}
|
||||
|
||||
private InputMethodInfo getCurrentInputMethodInfo() {
|
||||
String curInputMethodId = Settings.Secure.getString(getContext()
|
||||
.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
Set<InputMethodInfo> cachedImiSet = mEnabledInputMethodAndSubtypesCache.keySet();
|
||||
// 1. Search IMI in cache
|
||||
for (InputMethodInfo imi: cachedImiSet) {
|
||||
if (imi.getId().equals(curInputMethodId)) {
|
||||
return imi;
|
||||
}
|
||||
}
|
||||
// 2. Get current enabled IMEs and search IMI
|
||||
cachedImiSet = getEnabledInputMethodAndSubtypeList().keySet();
|
||||
for (InputMethodInfo imi: cachedImiSet) {
|
||||
if (imi.getId().equals(curInputMethodId)) {
|
||||
return imi;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private CharSequence getIMIName(InputMethodInfo imi) {
|
||||
if (imi == null) return null;
|
||||
return mPackageManager.getApplicationLabel(imi.getServiceInfo().applicationInfo);
|
||||
}
|
||||
|
||||
private CharSequence getSubtypeName(InputMethodInfo imi, InputMethodSubtype subtype) {
|
||||
if (imi == null || subtype == null) return null;
|
||||
// TODO: Change the language of subtype name according to subtype's locale.
|
||||
return mPackageManager.getText(
|
||||
imi.getPackageName(), subtype.getNameResId(), imi.getServiceInfo().applicationInfo);
|
||||
}
|
||||
|
||||
private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
|
||||
if (imi != null) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
|
||||
if (subtype != null) {
|
||||
Log.d(TAG, "subtype =" + subtype.getLocale() + "," + subtype.getMode());
|
||||
}
|
||||
}
|
||||
if (subtype != null) {
|
||||
return mPackageManager.getDrawable(imi.getPackageName(), subtype.getIconResId(),
|
||||
imi.getServiceInfo().applicationInfo);
|
||||
} else if (imi.getSubtypes().size() > 0) {
|
||||
return mPackageManager.getDrawable(imi.getPackageName(),
|
||||
imi.getSubtypes().get(0).getIconResId(),
|
||||
imi.getServiceInfo().applicationInfo);
|
||||
} else {
|
||||
try {
|
||||
return mPackageManager.getApplicationInfo(
|
||||
imi.getPackageName(), 0).loadIcon(mPackageManager);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.w(TAG, "IME can't be found: " + imi.getPackageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,8 @@ public class TabletStatusBar extends StatusBar implements
|
||||
public static final String TAG = "TabletStatusBar";
|
||||
|
||||
public static final int MAX_NOTIFICATION_ICONS = 5;
|
||||
// IME switcher icon is big and occupy width of two icons
|
||||
public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 2;
|
||||
|
||||
public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
|
||||
public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
|
||||
@@ -89,6 +91,8 @@ public class TabletStatusBar extends StatusBar implements
|
||||
public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
|
||||
public static final int MSG_SHOW_CHROME = 1030;
|
||||
public static final int MSG_HIDE_CHROME = 1031;
|
||||
public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
|
||||
public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
|
||||
|
||||
// Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
|
||||
private static final boolean FAKE_SPACE_BAR = true;
|
||||
@@ -155,6 +159,7 @@ public class TabletStatusBar extends StatusBar implements
|
||||
|
||||
boolean mNotificationsOn = true;
|
||||
private RecentAppsPanel mRecentsPanel;
|
||||
private InputMethodsPanel mInputMethodsPanel;
|
||||
|
||||
public Context getContext() { return mContext; }
|
||||
|
||||
@@ -260,6 +265,28 @@ public class TabletStatusBar extends StatusBar implements
|
||||
|
||||
WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
|
||||
mRecentsPanel.setBar(this);
|
||||
|
||||
// Input methods Panel
|
||||
mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
|
||||
R.layout.status_bar_input_methods_panel, null);
|
||||
mInputMethodsPanel.setVisibility(View.GONE);
|
||||
mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
|
||||
MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
|
||||
mStatusBarView.setIgnoreChildren(3, mInputMethodSwitchButton, mInputMethodsPanel);
|
||||
lp = new WindowManager.LayoutParams(
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
|
||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
|
||||
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
|
||||
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
|
||||
lp.setTitle("InputMethodsPanel");
|
||||
lp.windowAnimations = R.style.Animation_RecentPanel;
|
||||
|
||||
WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -351,6 +378,8 @@ public class TabletStatusBar extends StatusBar implements
|
||||
// The bar contents buttons
|
||||
mNotificationAndImeArea = (ViewGroup)sb.findViewById(R.id.notificationAndImeArea);
|
||||
mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
|
||||
// Overwrite the lister
|
||||
mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
|
||||
|
||||
// for redirecting errant bar taps to the IME
|
||||
mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
|
||||
@@ -522,6 +551,14 @@ public class TabletStatusBar extends StatusBar implements
|
||||
mRecentsPanel.show(false, true);
|
||||
}
|
||||
break;
|
||||
case MSG_OPEN_INPUT_METHODS_PANEL:
|
||||
if (DEBUG) Slog.d(TAG, "opening input methods panel");
|
||||
if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case MSG_CLOSE_INPUT_METHODS_PANEL:
|
||||
if (DEBUG) Slog.d(TAG, "closing input methods panel");
|
||||
if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.GONE);
|
||||
break;
|
||||
case MSG_SHOW_CHROME:
|
||||
if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
|
||||
mBarContents.setVisibility(View.VISIBLE);
|
||||
@@ -774,6 +811,8 @@ public class TabletStatusBar extends StatusBar implements
|
||||
mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
|
||||
mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
|
||||
mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
|
||||
mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
|
||||
mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
|
||||
}
|
||||
|
||||
// called by StatusBar
|
||||
@@ -803,7 +842,12 @@ public class TabletStatusBar extends StatusBar implements
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
|
||||
}
|
||||
int oldVisibility = mInputMethodSwitchButton.getVisibility();
|
||||
mInputMethodSwitchButton.setIMEButtonVisible(token, visible);
|
||||
if (oldVisibility != mInputMethodSwitchButton.getVisibility()) {
|
||||
updateNotificationIcons();
|
||||
}
|
||||
mInputMethodsPanel.setIMEToken(token);
|
||||
mBackButton.setImageResource(
|
||||
visible ? R.drawable.ic_sysbar_back_ime : R.drawable.ic_sysbar_back);
|
||||
if (FAKE_SPACE_BAR) {
|
||||
@@ -851,6 +895,8 @@ public class TabletStatusBar extends StatusBar implements
|
||||
onClickNotificationTrigger();
|
||||
} else if (v == mRecentButton) {
|
||||
onClickRecentButton();
|
||||
} else if (v == mInputMethodSwitchButton) {
|
||||
onClickInputMethodSwitchButton();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -890,6 +936,14 @@ public class TabletStatusBar extends StatusBar implements
|
||||
}
|
||||
}
|
||||
|
||||
public void onClickInputMethodSwitchButton() {
|
||||
if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
|
||||
int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
|
||||
MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
|
||||
mHandler.removeMessages(msg);
|
||||
mHandler.sendEmptyMessage(msg);
|
||||
}
|
||||
|
||||
public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
|
||||
return new NotificationClicker(intent, pkg, tag, id);
|
||||
}
|
||||
@@ -1086,7 +1140,12 @@ public class TabletStatusBar extends StatusBar implements
|
||||
|
||||
ArrayList<View> toShow = new ArrayList<View>();
|
||||
|
||||
for (int i=0; i<MAX_NOTIFICATION_ICONS; i++) {
|
||||
// When IME button is visible, the number of notification icons should be decremented
|
||||
// to fit the upper limit.
|
||||
final int maxNotificationIconsCount =
|
||||
(mInputMethodSwitchButton.getVisibility() != View.GONE) ?
|
||||
MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
|
||||
for (int i=0; i< maxNotificationIconsCount; i++) {
|
||||
if (i>=N) break;
|
||||
toShow.add(mNotns.get(N-i-1).icon);
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ import android.widget.FrameLayout;
|
||||
public class TabletStatusBarView extends FrameLayout {
|
||||
private Handler mHandler;
|
||||
|
||||
private View[] mIgnoreChildren = new View[3];
|
||||
private View[] mPanels = new View[3];
|
||||
private int[] mPos = new int[2];
|
||||
private final View[] mIgnoreChildren = new View[4];
|
||||
private final View[] mPanels = new View[4];
|
||||
private final int[] mPos = new int[2];
|
||||
|
||||
public TabletStatusBarView(Context context) {
|
||||
super(context);
|
||||
@@ -39,6 +39,7 @@ public class TabletStatusBarView extends FrameLayout {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
if (TabletStatusBar.DEBUG) {
|
||||
@@ -48,12 +49,16 @@ public class TabletStatusBarView extends FrameLayout {
|
||||
mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_NOTIFICATION_PANEL);
|
||||
mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
|
||||
mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
|
||||
mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_INPUT_METHODS_PANEL);
|
||||
mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_INPUT_METHODS_PANEL);
|
||||
|
||||
for (int i=0; i < mPanels.length; i++) {
|
||||
if (mPanels[i] != null && mPanels[i].getVisibility() == View.VISIBLE) {
|
||||
if (eventInside(mIgnoreChildren[i], ev)) {
|
||||
if (TabletStatusBar.DEBUG) {
|
||||
Slog.d(TabletStatusBar.TAG, "TabletStatusBarView eating event for view: " + mIgnoreChildren[i]);
|
||||
Slog.d(TabletStatusBar.TAG,
|
||||
"TabletStatusBarView eating event for view: "
|
||||
+ mIgnoreChildren[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1800,19 +1800,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
});
|
||||
|
||||
if (showSubtypes) {
|
||||
mDialogBuilder.setPositiveButton(com.android.internal.R.string.more_item_label,
|
||||
mDialogBuilder.setPositiveButton(
|
||||
com.android.internal.R.string.configure_input_methods,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
showConfigureInputMethods();
|
||||
}
|
||||
});
|
||||
}
|
||||
mDialogBuilder.setNegativeButton(com.android.internal.R.string.cancel,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
hideInputMethodMenu();
|
||||
}
|
||||
});
|
||||
mSwitchingDialog = mDialogBuilder.create();
|
||||
mSwitchingDialog.getWindow().setType(
|
||||
WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
|
||||
|
||||
Reference in New Issue
Block a user