diff --git a/core/java/android/view/KeyboardShortcutGroup.java b/core/java/android/view/KeyboardShortcutGroup.java index 013255b9a6123..57d07c0d0eac8 100644 --- a/core/java/android/view/KeyboardShortcutGroup.java +++ b/core/java/android/view/KeyboardShortcutGroup.java @@ -32,6 +32,8 @@ import static com.android.internal.util.Preconditions.checkNotNull; public final class KeyboardShortcutGroup implements Parcelable { private final CharSequence mLabel; private final List mItems; + // The system group looks different UI wise. + private boolean mSystemGroup; /** * @param label The title to be used for this group, or null if there is none. @@ -50,10 +52,33 @@ public final class KeyboardShortcutGroup implements Parcelable { this(label, Collections.emptyList()); } + /** + * @param label The title to be used for this group, or null if there is none. + * @param items The set of items to be included. + * @param isSystemGroup Set this to {@code true} if this is s system group. + * @hide + */ + public KeyboardShortcutGroup(@Nullable CharSequence label, + @NonNull List items, boolean isSystemGroup) { + mLabel = label; + mItems = new ArrayList<>(checkNotNull(items)); + mSystemGroup = isSystemGroup; + } + + /** + * @param label The title to be used for this group, or null if there is none. + * @param isSystemGroup Set this to {@code true} if this is s system group. + * @hide + */ + public KeyboardShortcutGroup(@Nullable CharSequence label, boolean isSystemGroup) { + this(label, Collections.emptyList(), isSystemGroup); + } + private KeyboardShortcutGroup(Parcel source) { mItems = new ArrayList<>(); mLabel = source.readCharSequence(); source.readTypedList(mItems, KeyboardShortcutInfo.CREATOR); + mSystemGroup = source.readInt() == 1; } /** @@ -70,6 +95,11 @@ public final class KeyboardShortcutGroup implements Parcelable { return mItems; } + /** @hide **/ + public boolean isSystemGroup() { + return mSystemGroup; + } + /** * Adds an item to the existing list. * @@ -88,6 +118,7 @@ public final class KeyboardShortcutGroup implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeCharSequence(mLabel); dest.writeTypedList(mItems); + dest.writeInt(mSystemGroup ? 1 : 0); } public static final Creator CREATOR = @@ -99,4 +130,4 @@ public final class KeyboardShortcutGroup implements Parcelable { return new KeyboardShortcutGroup[size]; } }; -} \ No newline at end of file +} diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml new file mode 100644 index 0000000000000..5a6553ff90db9 --- /dev/null +++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml @@ -0,0 +1,55 @@ + + + + + + + diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml new file mode 100644 index 0000000000000..80a478a6d3d87 --- /dev/null +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml @@ -0,0 +1,25 @@ + + + + diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml new file mode 100644 index 0000000000000..fa07eb1b105ce --- /dev/null +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml @@ -0,0 +1,22 @@ + + + + + diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml new file mode 100644 index 0000000000000..5002c1298eb2a --- /dev/null +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml @@ -0,0 +1,25 @@ + + + diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml index 460433ea1c214..77b12641c8c64 100644 --- a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml @@ -1,6 +1,6 @@ - - + + + + + + diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml new file mode 100644 index 0000000000000..802acfed73e80 --- /dev/null +++ b/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml @@ -0,0 +1,22 @@ + + + + + diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index f0d9949fa90c1..9bb6dc6abb752 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -154,4 +154,9 @@ #ff37474f #ff7fcac3 + + + #ff00bcd4 + #fff44336 + #ffffffff diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 240d32ec95bb2..4edb976b0c4d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1175,7 +1175,7 @@ public abstract class BaseStatusBar extends SystemUI implements } protected void toggleKeyboardShortcuts() { - getKeyboardShortcuts().toggleKeyboardShortcuts(mContext); + getKeyboardShortcuts().toggleKeyboardShortcuts(); } protected void cancelPreloadingRecents() { @@ -1518,7 +1518,7 @@ public abstract class BaseStatusBar extends SystemUI implements protected KeyboardShortcuts getKeyboardShortcuts() { if (mKeyboardShortcuts == null) { - mKeyboardShortcuts = new KeyboardShortcuts(); + mKeyboardShortcuts = new KeyboardShortcuts(mContext); } return mKeyboardShortcuts; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java index b36fb7e65f7e1..25e9a7aa1d8bf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java @@ -19,25 +19,38 @@ package com.android.systemui.statusbar; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.graphics.Color; +import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Handler; +import android.os.Looper; +import android.util.DisplayMetrics; import android.util.Log; +import android.util.TypedValue; import android.view.KeyEvent; import android.view.KeyboardShortcutGroup; import android.view.KeyboardShortcutInfo; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.Window; -import android.view.WindowManager; import android.view.WindowManager.KeyboardShortcutsReceiver; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.recents.Recents; +import java.util.ArrayList; import java.util.List; import static android.content.Context.LAYOUT_INFLATER_SERVICE; -import static android.graphics.Color.TRANSPARENT; +import static android.graphics.Color.WHITE; import static android.view.Gravity.TOP; import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; @@ -45,33 +58,44 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; * Contains functionality for handling keyboard shortcuts. */ public class KeyboardShortcuts { - private static final String TAG = "KeyboardShortcuts"; + private static final char SYSTEM_HOME_BASE_CHARACTER = '\u2386'; + private static final char SYSTEM_BACK_BASE_CHARACTER = '\u007F'; + private static final char SYSTEM_RECENTS_BASE_CHARACTER = '\u0009'; + + private final Handler mHandler = new Handler(Looper.getMainLooper()); + private final Context mContext; + private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dismissKeyboardShortcutsDialog(); + } + }; private Dialog mKeyboardShortcutsDialog; - public KeyboardShortcuts() {} + public KeyboardShortcuts(Context context) { + this.mContext = context; + } - public void toggleKeyboardShortcuts(final Context context) { + public void toggleKeyboardShortcuts() { if (mKeyboardShortcutsDialog == null) { - Recents.getSystemServices().requestKeyboardShortcuts(context, + Recents.getSystemServices().requestKeyboardShortcuts(mContext, new KeyboardShortcutsReceiver() { @Override public void onKeyboardShortcutsReceived( final List result) { KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup( - context.getString(R.string.keyboard_shortcut_group_system)); + mContext.getString(R.string.keyboard_shortcut_group_system), true); systemGroup.addItem(new KeyboardShortcutInfo( - context.getString(R.string.keyboard_shortcut_group_system_home), - '\u2386', KeyEvent.META_META_ON)); + mContext.getString(R.string.keyboard_shortcut_group_system_home), + SYSTEM_HOME_BASE_CHARACTER, KeyEvent.META_META_ON)); systemGroup.addItem(new KeyboardShortcutInfo( - context.getString(R.string.keyboard_shortcut_group_system_back), - '\u007F', KeyEvent.META_META_ON)); + mContext.getString(R.string.keyboard_shortcut_group_system_back), + SYSTEM_BACK_BASE_CHARACTER, KeyEvent.META_META_ON)); systemGroup.addItem(new KeyboardShortcutInfo( - context.getString(R.string.keyboard_shortcut_group_system_recents), - '\u0009', KeyEvent.META_ALT_ON)); + mContext.getString(R.string.keyboard_shortcut_group_system_recents), + SYSTEM_RECENTS_BASE_CHARACTER, KeyEvent.META_ALT_ON)); result.add(systemGroup); - Log.i(TAG, "Keyboard shortcuts received: " + String.valueOf(result)); - showKeyboardShortcutsDialog(context); + showKeyboardShortcutsDialog(result); } }); } else { @@ -79,33 +103,6 @@ public class KeyboardShortcuts { } } - private void showKeyboardShortcutsDialog(Context context) { - // Create dialog. - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context); - LayoutInflater inflater = (LayoutInflater) context.getSystemService( - LAYOUT_INFLATER_SERVICE); - final View keyboardShortcutsView = inflater.inflate( - R.layout.keyboard_shortcuts_view, null); - - populateKeyboardShortcuts(keyboardShortcutsView.findViewById( - R.id.keyboard_shortcuts_wrapper)); - dialogBuilder.setView(keyboardShortcutsView); - mKeyboardShortcutsDialog = dialogBuilder.create(); - mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true); - - // Setup window. - Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow(); - keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG); - keyboardShortcutsWindow.setBackgroundDrawable( - new ColorDrawable(TRANSPARENT)); - keyboardShortcutsWindow.setGravity(TOP); - keyboardShortcutsView.post(new Runnable() { - public void run() { - mKeyboardShortcutsDialog.show(); - } - }); - } - public void dismissKeyboardShortcutsDialog() { if (mKeyboardShortcutsDialog != null) { mKeyboardShortcutsDialog.dismiss(); @@ -113,11 +110,99 @@ public class KeyboardShortcuts { } } - /** - * @return {@code true} if the keyboard shortcuts have been successfully populated. - */ - private boolean populateKeyboardShortcuts(View keyboardShortcutsLayout) { - // TODO: Populate shortcuts. - return true; + private void showKeyboardShortcutsDialog( + final List keyboardShortcutGroups) { + // Need to post on the main thread. + mHandler.post(new Runnable() { + @Override + public void run() { + // TODO: break all this code out into a handleShowKeyboard... + // Might add more things posted; should consider adding a custom handler so + // you can send the keyboardShortcutsGroups as part of the message. + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext); + LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + LAYOUT_INFLATER_SERVICE); + final View keyboardShortcutsView = inflater.inflate( + R.layout.keyboard_shortcuts_view, null); + DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); + ScrollView scrollView = (ScrollView) keyboardShortcutsView.findViewById( + R.id.keyboard_shortcuts_scroll_view); + // TODO: find a better way to set the height. + scrollView.setLayoutParams(new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, + (int) (dm.heightPixels * dm.density))); + + populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById( + R.id.keyboard_shortcuts_container), keyboardShortcutGroups); + dialogBuilder.setView(keyboardShortcutsView); + dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener); + mKeyboardShortcutsDialog = dialogBuilder.create(); + mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true); + + // Setup window. + Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow(); + keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG); + keyboardShortcutsWindow.setBackgroundDrawable( + mContext.getDrawable(R.color.ksh_dialog_background_color)); + keyboardShortcutsWindow.setGravity(TOP); + mKeyboardShortcutsDialog.show(); + } + }); + } + + private void populateKeyboardShortcuts(LinearLayout keyboardShortcutsLayout, + List keyboardShortcutGroups) { + LayoutInflater inflater = LayoutInflater.from(mContext); + final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size(); + for (int i = 0; i < keyboardShortcutGroupsSize; i++) { + KeyboardShortcutGroup group = keyboardShortcutGroups.get(i); + TextView categoryTitle = (TextView) inflater.inflate( + R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false); + categoryTitle.setText(group.getLabel()); + categoryTitle.setTextColor(group.isSystemGroup() + ? mContext.getColor(R.color.ksh_system_group_color) + : mContext.getColor(R.color.ksh_application_group_color)); + keyboardShortcutsLayout.addView(categoryTitle); + + LinearLayout shortcutWrapper = (LinearLayout) inflater.inflate( + R.layout.keyboard_shortcuts_wrapper, null); + final int itemsSize = group.getItems().size(); + for (int j = 0; j < itemsSize; j++) { + KeyboardShortcutInfo info = group.getItems().get(j); + View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item, null); + TextView textView = (TextView) shortcutView + .findViewById(R.id.keyboard_shortcuts_keyword); + textView.setText(info.getLabel()); + + List shortcutKeys = getHumanReadableShortcutKeys(info); + final int shortcutKeysSize = shortcutKeys.size(); + for (int k = 0; k < shortcutKeysSize; k++) { + String shortcutKey = shortcutKeys.get(k); + TextView shortcutKeyView = (TextView) inflater.inflate( + R.layout.keyboard_shortcuts_key_view, null); + shortcutKeyView.setText(shortcutKey); + LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView + .findViewById(R.id.keyboard_shortcuts_item_container); + shortcutItemsContainer.addView(shortcutKeyView); + } + shortcutWrapper.addView(shortcutView); + } + + // TODO: merge container and wrapper into one xml file - wrapper is always a child of + // container. + LinearLayout shortcutsContainer = (LinearLayout) inflater.inflate( + R.layout.keyboard_shortcuts_container, null); + shortcutsContainer.addView(shortcutWrapper); + keyboardShortcutsLayout.addView(shortcutsContainer); + } + } + + private List getHumanReadableShortcutKeys(KeyboardShortcutInfo info) { + // TODO: fix the shortcuts. Find or build an util which can produce human readable + // names of the baseCharacter and the modifiers. + List shortcutKeys = new ArrayList<>(); + shortcutKeys.add(KeyEvent.metaStateToString(info.getModifiers()).toUpperCase()); + shortcutKeys.add(Character.getName(info.getBaseCharacter()).toUpperCase()); + return shortcutKeys; } }