• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.tuner;
16 
17 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY;
18 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END;
19 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START;
20 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM;
21 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME;
22 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE;
23 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT;
24 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT;
25 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
26 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractButton;
27 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractImage;
28 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractKeycode;
29 
30 import android.annotation.Nullable;
31 import android.app.AlertDialog;
32 import android.content.DialogInterface;
33 import android.content.DialogInterface.OnClickListener;
34 import android.content.res.Resources;
35 import android.graphics.Color;
36 import android.graphics.Paint;
37 import android.graphics.Paint.FontMetricsInt;
38 import android.graphics.Rect;
39 import android.graphics.drawable.Drawable;
40 import android.graphics.drawable.Icon;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.support.v14.preference.PreferenceFragment;
44 import android.support.v7.preference.DropDownPreference;
45 import android.support.v7.preference.ListPreference;
46 import android.support.v7.preference.Preference;
47 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
48 import android.support.v7.preference.Preference.OnPreferenceClickListener;
49 import android.support.v7.preference.PreferenceCategory;
50 import android.text.SpannableStringBuilder;
51 import android.text.style.ImageSpan;
52 import android.util.Log;
53 import android.util.TypedValue;
54 import android.view.KeyEvent;
55 import android.widget.EditText;
56 
57 import com.android.systemui.Dependency;
58 import com.android.systemui.R;
59 import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
60 import com.android.systemui.tuner.TunerService.Tunable;
61 
62 import java.util.ArrayList;
63 
64 public class NavBarTuner extends TunerPreferenceFragment {
65 
66     private static final String LAYOUT = "layout";
67     private static final String LEFT = "left";
68     private static final String RIGHT = "right";
69 
70     private static final String TYPE = "type";
71     private static final String KEYCODE = "keycode";
72     private static final String ICON = "icon";
73 
74     private static final int[][] ICONS = new int[][]{
75             {R.drawable.ic_qs_circle, R.string.tuner_circle},
76             {R.drawable.ic_add, R.string.tuner_plus},
77             {R.drawable.ic_remove, R.string.tuner_minus},
78             {R.drawable.ic_left, R.string.tuner_left},
79             {R.drawable.ic_right, R.string.tuner_right},
80             {R.drawable.ic_menu, R.string.tuner_menu},
81     };
82 
83     private final ArrayList<Tunable> mTunables = new ArrayList<>();
84     private Handler mHandler;
85 
86     @Override
onCreate(@ullable Bundle savedInstanceState)87     public void onCreate(@Nullable Bundle savedInstanceState) {
88         mHandler = new Handler();
89         super.onCreate(savedInstanceState);
90     }
91 
92     @Override
onActivityCreated(@ullable Bundle savedInstanceState)93     public void onActivityCreated(@Nullable Bundle savedInstanceState) {
94         super.onActivityCreated(savedInstanceState);
95         getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
96     }
97 
98     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)99     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
100         addPreferencesFromResource(R.xml.nav_bar_tuner);
101         bindLayout((ListPreference) findPreference(LAYOUT));
102         bindButton(NAV_BAR_LEFT, NAVSPACE, LEFT);
103         bindButton(NAV_BAR_RIGHT, MENU_IME, RIGHT);
104     }
105 
106     @Override
onDestroy()107     public void onDestroy() {
108         super.onDestroy();
109         mTunables.forEach(t -> Dependency.get(TunerService.class).removeTunable(t));
110     }
111 
addTunable(Tunable tunable, String... keys)112     private void addTunable(Tunable tunable, String... keys) {
113         mTunables.add(tunable);
114         Dependency.get(TunerService.class).addTunable(tunable, keys);
115     }
116 
bindLayout(ListPreference preference)117     private void bindLayout(ListPreference preference) {
118         addTunable((key, newValue) -> mHandler.post(() -> {
119             String val = newValue;
120             if (val == null) {
121                 val = "default";
122             }
123             preference.setValue(val);
124         }), NAV_BAR_VIEWS);
125         preference.setOnPreferenceChangeListener((preference1, newValue) -> {
126             String val = (String) newValue;
127             if ("default".equals(val)) val = null;
128             Dependency.get(TunerService.class).setValue(NAV_BAR_VIEWS, val);
129             return true;
130         });
131     }
132 
bindButton(String setting, String def, String k)133     private void bindButton(String setting, String def, String k) {
134         ListPreference type = (ListPreference) findPreference(TYPE + "_" + k);
135         Preference keycode = findPreference(KEYCODE + "_" + k);
136         ListPreference icon = (ListPreference) findPreference(ICON + "_" + k);
137         setupIcons(icon);
138         addTunable((key, newValue) -> mHandler.post(() -> {
139             String val = newValue;
140             if (val == null) {
141                 val = def;
142             }
143             String button = extractButton(val);
144             if (button.startsWith(KEY)) {
145                 type.setValue(KEY);
146                 String uri = extractImage(button);
147                 int code = extractKeycode(button);
148                 icon.setValue(uri);
149                 updateSummary(icon);
150                 keycode.setSummary(code + "");
151                 keycode.setVisible(true);
152                 icon.setVisible(true);
153             } else {
154                 type.setValue(button);
155                 keycode.setVisible(false);
156                 icon.setVisible(false);
157             }
158         }), setting);
159         OnPreferenceChangeListener listener = (preference, newValue) -> {
160             mHandler.post(() -> {
161                 setValue(setting, type, keycode, icon);
162                 updateSummary(icon);
163             });
164             return true;
165         };
166         type.setOnPreferenceChangeListener(listener);
167         icon.setOnPreferenceChangeListener(listener);
168         keycode.setOnPreferenceClickListener(preference -> {
169             EditText editText = new EditText(getContext());
170             new AlertDialog.Builder(getContext())
171                     .setTitle(preference.getTitle())
172                     .setView(editText)
173                     .setNegativeButton(android.R.string.cancel, null)
174                     .setPositiveButton(android.R.string.ok, (dialog, which) -> {
175                         int code = KeyEvent.KEYCODE_ENTER;
176                         try {
177                             code = Integer.parseInt(editText.getText().toString());
178                         } catch (Exception e) {
179                         }
180                         keycode.setSummary(code + "");
181                         setValue(setting, type, keycode, icon);
182                     }).show();
183             return true;
184         });
185     }
186 
updateSummary(ListPreference icon)187     private void updateSummary(ListPreference icon) {
188         try {
189             int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
190                     getContext().getResources().getDisplayMetrics());
191             String pkg = icon.getValue().split("/")[0];
192             int id = Integer.parseInt(icon.getValue().split("/")[1]);
193             SpannableStringBuilder builder = new SpannableStringBuilder();
194             Drawable d = Icon.createWithResource(pkg, id)
195                     .loadDrawable(getContext());
196             d.setTint(Color.BLACK);
197             d.setBounds(0, 0, size, size);
198             ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
199             builder.append("  ", span, 0);
200             builder.append(" ");
201             for (int i = 0; i < ICONS.length; i++) {
202                 if (ICONS[i][0] == id) {
203                     builder.append(getString(ICONS[i][1]));
204                 }
205             }
206             icon.setSummary(builder);
207         } catch (Exception e) {
208             Log.d("NavButton", "Problem with summary", e);
209             icon.setSummary(null);
210         }
211     }
212 
setValue(String setting, ListPreference type, Preference keycode, ListPreference icon)213     private void setValue(String setting, ListPreference type, Preference keycode,
214             ListPreference icon) {
215         String button = type.getValue();
216         if (KEY.equals(button)) {
217             String uri = icon.getValue();
218             int code = KeyEvent.KEYCODE_ENTER;
219             try {
220                 code = Integer.parseInt(keycode.getSummary().toString());
221             } catch (Exception e) {
222             }
223             button = button + KEY_CODE_START + code + KEY_IMAGE_DELIM + uri + KEY_CODE_END;
224         }
225         Dependency.get(TunerService.class).setValue(setting, button);
226     }
227 
setupIcons(ListPreference icon)228     private void setupIcons(ListPreference icon) {
229         CharSequence[] labels = new CharSequence[ICONS.length];
230         CharSequence[] values = new CharSequence[ICONS.length];
231         int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
232                 getContext().getResources().getDisplayMetrics());
233         for (int i = 0; i < ICONS.length; i++) {
234             SpannableStringBuilder builder = new SpannableStringBuilder();
235             Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i][0])
236                     .loadDrawable(getContext());
237             d.setTint(Color.BLACK);
238             d.setBounds(0, 0, size, size);
239             ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
240             builder.append("  ", span, 0);
241             builder.append(" ");
242             builder.append(getString(ICONS[i][1]));
243             labels[i] = builder;
244             values[i] = getContext().getPackageName() + "/" + ICONS[i][0];
245         }
246         icon.setEntries(labels);
247         icon.setEntryValues(values);
248     }
249 }
250