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.navigationbar.NavigationBarInflaterView.KEY; 18 import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY_CODE_END; 19 import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY_CODE_START; 20 import static com.android.systemui.navigationbar.NavigationBarInflaterView.KEY_IMAGE_DELIM; 21 import static com.android.systemui.navigationbar.NavigationBarInflaterView.MENU_IME_ROTATE; 22 import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAVSPACE; 23 import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAV_BAR_LEFT; 24 import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAV_BAR_RIGHT; 25 import static com.android.systemui.navigationbar.NavigationBarInflaterView.NAV_BAR_VIEWS; 26 import static com.android.systemui.navigationbar.NavigationBarInflaterView.extractButton; 27 import static com.android.systemui.navigationbar.NavigationBarInflaterView.extractImage; 28 import static com.android.systemui.navigationbar.NavigationBarInflaterView.extractKeycode; 29 30 import android.annotation.Nullable; 31 import android.app.AlertDialog; 32 import android.graphics.Color; 33 import android.graphics.drawable.Drawable; 34 import android.graphics.drawable.Icon; 35 import android.os.Bundle; 36 import android.os.Handler; 37 import android.text.SpannableStringBuilder; 38 import android.text.style.ImageSpan; 39 import android.util.Log; 40 import android.util.TypedValue; 41 import android.view.KeyEvent; 42 import android.widget.EditText; 43 44 import androidx.preference.ListPreference; 45 import androidx.preference.Preference; 46 import androidx.preference.Preference.OnPreferenceChangeListener; 47 48 import com.android.systemui.Dependency; 49 import com.android.systemui.res.R; 50 import com.android.systemui.tuner.TunerService.Tunable; 51 52 import java.util.ArrayList; 53 54 @Deprecated 55 public class NavBarTuner extends TunerPreferenceFragment { 56 57 private static final String LAYOUT = "layout"; 58 private static final String LEFT = "left"; 59 private static final String RIGHT = "right"; 60 61 private static final String TYPE = "type"; 62 private static final String KEYCODE = "keycode"; 63 private static final String ICON = "icon"; 64 65 private static final int[][] ICONS = new int[][]{ 66 {R.drawable.ic_qs_circle, R.string.tuner_circle}, 67 {R.drawable.ic_add, R.string.tuner_plus}, 68 {R.drawable.ic_remove, R.string.tuner_minus}, 69 {R.drawable.ic_left, R.string.tuner_left}, 70 {R.drawable.ic_right, R.string.tuner_right}, 71 {R.drawable.ic_menu, R.string.tuner_menu}, 72 }; 73 74 private final ArrayList<Tunable> mTunables = new ArrayList<>(); 75 private Handler mHandler; 76 77 @Override onCreate(@ullable Bundle savedInstanceState)78 public void onCreate(@Nullable Bundle savedInstanceState) { 79 mHandler = new Handler(); 80 super.onCreate(savedInstanceState); 81 } 82 83 @Override onActivityCreated(@ullable Bundle savedInstanceState)84 public void onActivityCreated(@Nullable Bundle savedInstanceState) { 85 super.onActivityCreated(savedInstanceState); 86 getActivity().getActionBar().setDisplayHomeAsUpEnabled(true); 87 } 88 89 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)90 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 91 addPreferencesFromResource(R.xml.nav_bar_tuner); 92 bindLayout((ListPreference) findPreference(LAYOUT)); 93 bindButton(NAV_BAR_LEFT, NAVSPACE, LEFT); 94 bindButton(NAV_BAR_RIGHT, MENU_IME_ROTATE, RIGHT); 95 } 96 97 @Override onDestroy()98 public void onDestroy() { 99 super.onDestroy(); 100 mTunables.forEach(t -> Dependency.get(TunerService.class).removeTunable(t)); 101 } 102 addTunable(Tunable tunable, String... keys)103 private void addTunable(Tunable tunable, String... keys) { 104 mTunables.add(tunable); 105 Dependency.get(TunerService.class).addTunable(tunable, keys); 106 } 107 bindLayout(ListPreference preference)108 private void bindLayout(ListPreference preference) { 109 addTunable((key, newValue) -> mHandler.post(() -> { 110 String val = newValue; 111 if (val == null) { 112 val = "default"; 113 } 114 preference.setValue(val); 115 }), NAV_BAR_VIEWS); 116 preference.setOnPreferenceChangeListener((preference1, newValue) -> { 117 String val = (String) newValue; 118 if ("default".equals(val)) val = null; 119 Dependency.get(TunerService.class).setValue(NAV_BAR_VIEWS, val); 120 return true; 121 }); 122 } 123 bindButton(String setting, String def, String k)124 private void bindButton(String setting, String def, String k) { 125 ListPreference type = (ListPreference) findPreference(TYPE + "_" + k); 126 Preference keycode = findPreference(KEYCODE + "_" + k); 127 ListPreference icon = (ListPreference) findPreference(ICON + "_" + k); 128 setupIcons(icon); 129 addTunable((key, newValue) -> mHandler.post(() -> { 130 String val = newValue; 131 if (val == null) { 132 val = def; 133 } 134 String button = extractButton(val); 135 if (button.startsWith(KEY)) { 136 type.setValue(KEY); 137 String uri = extractImage(button); 138 int code = extractKeycode(button); 139 icon.setValue(uri); 140 updateSummary(icon); 141 keycode.setSummary(code + ""); 142 keycode.setVisible(true); 143 icon.setVisible(true); 144 } else { 145 type.setValue(button); 146 keycode.setVisible(false); 147 icon.setVisible(false); 148 } 149 }), setting); 150 OnPreferenceChangeListener listener = (preference, newValue) -> { 151 mHandler.post(() -> { 152 setValue(setting, type, keycode, icon); 153 updateSummary(icon); 154 }); 155 return true; 156 }; 157 type.setOnPreferenceChangeListener(listener); 158 icon.setOnPreferenceChangeListener(listener); 159 keycode.setOnPreferenceClickListener(preference -> { 160 EditText editText = new EditText(getContext()); 161 new AlertDialog.Builder(getContext()) 162 .setTitle(preference.getTitle()) 163 .setView(editText) 164 .setNegativeButton(android.R.string.cancel, null) 165 .setPositiveButton(android.R.string.ok, (dialog, which) -> { 166 int code = KeyEvent.KEYCODE_ENTER; 167 try { 168 code = Integer.parseInt(editText.getText().toString()); 169 } catch (Exception e) { 170 } 171 keycode.setSummary(code + ""); 172 setValue(setting, type, keycode, icon); 173 }).show(); 174 return true; 175 }); 176 } 177 updateSummary(ListPreference icon)178 private void updateSummary(ListPreference icon) { 179 try { 180 int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, 181 getContext().getResources().getDisplayMetrics()); 182 String pkg = icon.getValue().split("/")[0]; 183 int id = Integer.parseInt(icon.getValue().split("/")[1]); 184 SpannableStringBuilder builder = new SpannableStringBuilder(); 185 Drawable d = Icon.createWithResource(pkg, id) 186 .loadDrawable(getContext()); 187 d.setTint(Color.BLACK); 188 d.setBounds(0, 0, size, size); 189 ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); 190 builder.append(" ", span, 0); 191 builder.append(" "); 192 for (int i = 0; i < ICONS.length; i++) { 193 if (ICONS[i][0] == id) { 194 builder.append(getString(ICONS[i][1])); 195 } 196 } 197 icon.setSummary(builder); 198 } catch (Exception e) { 199 Log.d("NavButton", "Problem with summary", e); 200 icon.setSummary(null); 201 } 202 } 203 setValue(String setting, ListPreference type, Preference keycode, ListPreference icon)204 private void setValue(String setting, ListPreference type, Preference keycode, 205 ListPreference icon) { 206 String button = type.getValue(); 207 if (KEY.equals(button)) { 208 String uri = icon.getValue(); 209 int code = KeyEvent.KEYCODE_ENTER; 210 try { 211 code = Integer.parseInt(keycode.getSummary().toString()); 212 } catch (Exception e) { 213 } 214 button = button + KEY_CODE_START + code + KEY_IMAGE_DELIM + uri + KEY_CODE_END; 215 } 216 Dependency.get(TunerService.class).setValue(setting, button); 217 } 218 setupIcons(ListPreference icon)219 private void setupIcons(ListPreference icon) { 220 CharSequence[] labels = new CharSequence[ICONS.length]; 221 CharSequence[] values = new CharSequence[ICONS.length]; 222 int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, 223 getContext().getResources().getDisplayMetrics()); 224 for (int i = 0; i < ICONS.length; i++) { 225 SpannableStringBuilder builder = new SpannableStringBuilder(); 226 Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i][0]) 227 .loadDrawable(getContext()); 228 d.setTint(Color.BLACK); 229 d.setBounds(0, 0, size, size); 230 ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); 231 builder.append(" ", span, 0); 232 builder.append(" "); 233 builder.append(getString(ICONS[i][1])); 234 labels[i] = builder; 235 values[i] = getContext().getPackageName() + "/" + ICONS[i][0]; 236 } 237 icon.setEntries(labels); 238 icon.setEntryValues(values); 239 } 240 } 241