blob: 0b7bfa8871ee4a381885ff53b6e4e333fa5389ae [file] [log] [blame]
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +01001/*
2 * Copyright (C) 2016 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
17package com.android.systemui.statusbar;
18
19import android.app.AlertDialog;
20import android.app.Dialog;
21import android.content.Context;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000022import android.content.DialogInterface;
23import android.content.DialogInterface.OnClickListener;
Clara Bayarri75e09792015-07-29 16:20:40 +010024import android.os.Handler;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000025import android.os.Looper;
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +000026import android.view.ContextThemeWrapper;
Clara Bayarri75e09792015-07-29 16:20:40 +010027import android.view.KeyEvent;
28import android.view.KeyboardShortcutGroup;
29import android.view.KeyboardShortcutInfo;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010030import android.view.LayoutInflater;
31import android.view.View;
32import android.view.Window;
Clara Bayarri75e09792015-07-29 16:20:40 +010033import android.view.WindowManager.KeyboardShortcutsReceiver;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000034import android.widget.LinearLayout;
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000035import android.widget.TextView;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010036
37import com.android.systemui.R;
Clara Bayarri75e09792015-07-29 16:20:40 +010038import com.android.systemui.recents.Recents;
39
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000040import java.util.ArrayList;
Clara Bayarri75e09792015-07-29 16:20:40 +010041import java.util.List;
42
43import static android.content.Context.LAYOUT_INFLATER_SERVICE;
Clara Bayarri75e09792015-07-29 16:20:40 +010044import static android.view.Gravity.TOP;
45import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010046
47/**
48 * Contains functionality for handling keyboard shortcuts.
49 */
50public class KeyboardShortcuts {
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000051 private static final char SYSTEM_HOME_BASE_CHARACTER = '\u2386';
52 private static final char SYSTEM_BACK_BASE_CHARACTER = '\u007F';
53 private static final char SYSTEM_RECENTS_BASE_CHARACTER = '\u0009';
54
55 private final Handler mHandler = new Handler(Looper.getMainLooper());
56 private final Context mContext;
57 private final OnClickListener dialogCloseListener = new DialogInterface.OnClickListener() {
58 public void onClick(DialogInterface dialog, int id) {
59 dismissKeyboardShortcutsDialog();
60 }
61 };
Clara Bayarri75e09792015-07-29 16:20:40 +010062
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010063 private Dialog mKeyboardShortcutsDialog;
64
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000065 public KeyboardShortcuts(Context context) {
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +000066 this.mContext = new ContextThemeWrapper(context, android.R.style.Theme_Material_Light);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000067 }
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010068
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000069 public void toggleKeyboardShortcuts() {
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010070 if (mKeyboardShortcutsDialog == null) {
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000071 Recents.getSystemServices().requestKeyboardShortcuts(mContext,
Clara Bayarri75e09792015-07-29 16:20:40 +010072 new KeyboardShortcutsReceiver() {
73 @Override
74 public void onKeyboardShortcutsReceived(
75 final List<KeyboardShortcutGroup> result) {
76 KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000077 mContext.getString(R.string.keyboard_shortcut_group_system), true);
Clara Bayarri75e09792015-07-29 16:20:40 +010078 systemGroup.addItem(new KeyboardShortcutInfo(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000079 mContext.getString(R.string.keyboard_shortcut_group_system_home),
80 SYSTEM_HOME_BASE_CHARACTER, KeyEvent.META_META_ON));
Clara Bayarri75e09792015-07-29 16:20:40 +010081 systemGroup.addItem(new KeyboardShortcutInfo(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000082 mContext.getString(R.string.keyboard_shortcut_group_system_back),
83 SYSTEM_BACK_BASE_CHARACTER, KeyEvent.META_META_ON));
Clara Bayarri75e09792015-07-29 16:20:40 +010084 systemGroup.addItem(new KeyboardShortcutInfo(
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000085 mContext.getString(R.string.keyboard_shortcut_group_system_recents),
86 SYSTEM_RECENTS_BASE_CHARACTER, KeyEvent.META_ALT_ON));
Clara Bayarri75e09792015-07-29 16:20:40 +010087 result.add(systemGroup);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +000088 showKeyboardShortcutsDialog(result);
Clara Bayarri75e09792015-07-29 16:20:40 +010089 }
90 });
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010091 } else {
92 dismissKeyboardShortcutsDialog();
93 }
94 }
95
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +010096 public void dismissKeyboardShortcutsDialog() {
97 if (mKeyboardShortcutsDialog != null) {
98 mKeyboardShortcutsDialog.dismiss();
99 mKeyboardShortcutsDialog = null;
100 }
101 }
102
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000103 private void showKeyboardShortcutsDialog(
104 final List<KeyboardShortcutGroup> keyboardShortcutGroups) {
105 // Need to post on the main thread.
106 mHandler.post(new Runnable() {
107 @Override
108 public void run() {
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000109 handleShowKeyboardShortcuts(keyboardShortcutGroups);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000110 }
111 });
112 }
113
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000114 private void handleShowKeyboardShortcuts(List<KeyboardShortcutGroup> keyboardShortcutGroups) {
115 AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
116 LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
117 LAYOUT_INFLATER_SERVICE);
118 final View keyboardShortcutsView = inflater.inflate(
119 R.layout.keyboard_shortcuts_view, null);
120 populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
121 R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
122 dialogBuilder.setView(keyboardShortcutsView);
123 dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
124 mKeyboardShortcutsDialog = dialogBuilder.create();
125 mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
126 Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
127 keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
128 mKeyboardShortcutsDialog.show();
129 }
130
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000131 private void populateKeyboardShortcuts(LinearLayout keyboardShortcutsLayout,
132 List<KeyboardShortcutGroup> keyboardShortcutGroups) {
133 LayoutInflater inflater = LayoutInflater.from(mContext);
134 final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
135 for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
136 KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
137 TextView categoryTitle = (TextView) inflater.inflate(
138 R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
139 categoryTitle.setText(group.getLabel());
140 categoryTitle.setTextColor(group.isSystemGroup()
141 ? mContext.getColor(R.color.ksh_system_group_color)
142 : mContext.getColor(R.color.ksh_application_group_color));
143 keyboardShortcutsLayout.addView(categoryTitle);
144
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000145 LinearLayout shortcutContainer = (LinearLayout) inflater.inflate(
146 R.layout.keyboard_shortcuts_container, keyboardShortcutsLayout, false);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000147 final int itemsSize = group.getItems().size();
148 for (int j = 0; j < itemsSize; j++) {
149 KeyboardShortcutInfo info = group.getItems().get(j);
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000150 View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item,
151 shortcutContainer, false);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000152 TextView textView = (TextView) shortcutView
153 .findViewById(R.id.keyboard_shortcuts_keyword);
154 textView.setText(info.getLabel());
155
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000156 LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView
157 .findViewById(R.id.keyboard_shortcuts_item_container);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000158 List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
159 final int shortcutKeysSize = shortcutKeys.size();
160 for (int k = 0; k < shortcutKeysSize; k++) {
161 String shortcutKey = shortcutKeys.get(k);
162 TextView shortcutKeyView = (TextView) inflater.inflate(
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000163 R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer, false);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000164 shortcutKeyView.setText(shortcutKey);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000165 shortcutItemsContainer.addView(shortcutKeyView);
166 }
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000167 shortcutContainer.addView(shortcutView);
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000168 }
Andrei Stingaceanu2b909e92016-02-03 17:52:00 +0000169 keyboardShortcutsLayout.addView(shortcutContainer);
170 if (i < keyboardShortcutGroupsSize - 1) {
171 View separator = inflater.inflate(
172 R.layout.keyboard_shortcuts_category_separator, keyboardShortcutsLayout,
173 false);
174 keyboardShortcutsLayout.addView(separator);
175 }
Andrei Stingaceanu8861cb02016-01-20 16:48:30 +0000176 }
177 }
178
179 private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
180 // TODO: fix the shortcuts. Find or build an util which can produce human readable
181 // names of the baseCharacter and the modifiers.
182 List<String> shortcutKeys = new ArrayList<>();
183 shortcutKeys.add(KeyEvent.metaStateToString(info.getModifiers()).toUpperCase());
184 shortcutKeys.add(Character.getName(info.getBaseCharacter()).toUpperCase());
185 return shortcutKeys;
Andrei Stingaceanu9d9294c2015-08-24 17:19:06 +0100186 }
187}