Merge "Add input methods settings panel" into honeycomb

This commit is contained in:
satok
2011-01-14 12:03:40 -08:00
committed by Android (Google) Code Review
9 changed files with 595 additions and 45 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);