/*
* Copyright (C) 2013 The CyanogenMod Project
* This code is loosely based on portions of the ParanoidAndroid Project source, Copyright (C) 2012.
*
* 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;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
import android.view.KeyEvent;
import com.android.systemui.R;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Class that holds the global information about supported navigation buttons
* in CyanogenMod.
*/
public class NavigationButtons {
/**
* Defines how many keys / key slots there may be for navigation.
* WARNING If you ever change this, don't forget check the source in
* {@code /phone/NavBarEdit.java} and {/pie/PieController.java}
*/
public static final int SLOT_COUNT = 6;
/**
* Defines the weight of each of the 6 keys. For most implementations this is
* hard-coded within a resource file.
*/
public static final boolean IS_SLOT_SMALL[] = { true, false, false, false, false, true };
/**
* Class to store the information about supported buttons
*/
public static final class ButtonInfo {
public final int displayId;
public final int contentDescription;
public final int keyCode;
public final int portResource;
public final int landResource;
public final int sideResource;
private final String key;
/**
* Public constructor for new button types. Use this to create own {@link ButtonInfo}s
* for additional special keys you may want to support. Note: You can not
* persist your own {@link ButtonInfo}s with
* {@link NavigationButtons#storeButtonMap(Context, ButtonInfo[])}!
* @param rId - resource id of text shown to user in choose dialog
* @param cD - accessibility information regarding button
* @param mC - keyCode to execute on button press
* @param pR - portrait resource used to display button
* @param lR - landscape resource used to display button
* @param sR - smaller scaled resource for side buttons
*/
public ButtonInfo(int rId, int cD, int mC, int pR, int lR, int sR) {
displayId = rId;
contentDescription = cD;
keyCode = mC;
portResource = pR;
landResource = lR;
sideResource = sR;
key = "";
}
/**
* Constructor for new button types
* @param rId - resource id of text shown to user in choose dialog
* @param cD - accessibility information regarding button
* @param mC - keyCode to execute on button press
* @param pR - portrait resource used to display button
* @param lR - landscape resource used to display button
* @param sR - smaller scaled resource for side buttons
* @param key - the internal key of the button
*/
public ButtonInfo(int rId, int cD, int mC, int pR, int lR, int sR, String key) {
displayId = rId;
contentDescription = cD;
keyCode = mC;
portResource = pR;
landResource = lR;
sideResource = sR;
this.key = key;
}
@Override
public String toString() {
return "ButtonInfo[" + key + "]";
}
}
// Available buttons string constants
private static final String EMPTY_STRING = "empty";
private static final String HOME_STRING = "home";
private static final String BACK_STRING = "back";
private static final String SEARCH_STRING = "search";
private static final String RECENT_STRING = "recent";
private static final String CONDITIONAL_MENU_STRING = "menu0";
private static final String ALWAYS_MENU_STRING = "menu1";
private static final String MENU_BIG_STRING = "menu2";
private static final String DEFAULT_SETTING_STRING = "empty|back|home|recent|empty|menu0";
// All navigation button information CyanogenMod needs
public static final ButtonInfo HOME = new ButtonInfo(
R.string.navbar_home_button,
R.string.accessibility_home, KeyEvent.KEYCODE_HOME, R.drawable.ic_sysbar_home,
R.drawable.ic_sysbar_home_land, R.drawable.ic_sysbar_home, HOME_STRING);
public static final ButtonInfo CONDITIONAL_MENU = new ButtonInfo(
R.string.navbar_menu_conditional_button,
R.string.accessibility_menu, KeyEvent.KEYCODE_MENU, R.drawable.ic_sysbar_menu,
R.drawable.ic_sysbar_menu_land, R.drawable.ic_sysbar_menu, CONDITIONAL_MENU_STRING);
public static final ButtonInfo ALWAYS_MENU = new ButtonInfo(
R.string.navbar_menu_always_button,
R.string.accessibility_menu, KeyEvent.KEYCODE_MENU, R.drawable.ic_sysbar_menu,
R.drawable.ic_sysbar_menu_land, R.drawable.ic_sysbar_menu, ALWAYS_MENU_STRING);
public static final ButtonInfo MENU_BIG = new ButtonInfo(
R.string.navbar_menu_big_button,
R.string.accessibility_menu, KeyEvent.KEYCODE_MENU, R.drawable.ic_sysbar_menu_big,
R.drawable.ic_sysbar_menu_big_land, 0, MENU_BIG_STRING);
public static final ButtonInfo BACK = new ButtonInfo(
R.string.navbar_back_button, R.string.accessibility_back,
KeyEvent.KEYCODE_BACK, R.drawable.ic_sysbar_back,
R.drawable.ic_sysbar_back_land, R.drawable.ic_sysbar_back_side, BACK_STRING);
public static final ButtonInfo SEARCH = new ButtonInfo(
R.string.navbar_search_button,
R.string.accessibility_back, KeyEvent.KEYCODE_SEARCH, R.drawable.ic_sysbar_search,
R.drawable.ic_sysbar_search_land, R.drawable.ic_sysbar_search_side, SEARCH_STRING);
public static final ButtonInfo RECENT = new ButtonInfo(
R.string.navbar_recent_button,
R.string.accessibility_recent, 0, R.drawable.ic_sysbar_recent,
R.drawable.ic_sysbar_recent_land, R.drawable.ic_sysbar_recent_side, RECENT_STRING);
public static final ButtonInfo EMPTY = new ButtonInfo(
R.string.navbar_empty_button,
R.string.accessibility_clear_all, 0, R.drawable.ic_sysbar_add,
R.drawable.ic_sysbar_add_land, R.drawable.ic_sysbar_add_side, EMPTY_STRING);
/**
* Map which holds references to supported/available buttons. This is a unmodifiable map.
*/
public static final Map BUTTON_MAP;
static {
Map temp = new LinkedHashMap();
temp.put(HOME_STRING, HOME);
temp.put(CONDITIONAL_MENU_STRING, CONDITIONAL_MENU);
temp.put(ALWAYS_MENU_STRING, ALWAYS_MENU);
temp.put(MENU_BIG_STRING, MENU_BIG);
temp.put(BACK_STRING, BACK);
temp.put(SEARCH_STRING, SEARCH);
temp.put(RECENT_STRING, RECENT);
temp.put(EMPTY_STRING, EMPTY);
BUTTON_MAP = Collections.unmodifiableMap(temp);
}
/**
* Retrieves the button configuration from the settings.
* @return the current button map, or the default button map.
*/
public static ButtonInfo[] loadButtonMap(Context context) {
String saved = Settings.System.getStringForUser(context.getContentResolver(),
Settings.System.NAV_BUTTONS, UserHandle.USER_CURRENT);
if (saved == null) {
saved = NavigationButtons.DEFAULT_SETTING_STRING;
}
String[] buttons = saved.split("\\|");
if (buttons.length < SLOT_COUNT) {
buttons = NavigationButtons.DEFAULT_SETTING_STRING.split("\\|");
}
ButtonInfo[] result = new ButtonInfo[6];
for (int i = 0; i < result.length; i++) {
result[i] = BUTTON_MAP.get(buttons[i]);
if (result[i] == null) {
result[i] = EMPTY;
}
}
return result;
}
public static void storeButtonMap(Context context, ButtonInfo[] map) {
if (map.length != SLOT_COUNT) {
throw new IllegalArgumentException("Navigation button count does not match! Is: "
+ map.length + " expected: " + SLOT_COUNT);
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < SLOT_COUNT; i++) {
if (i != 0) sb.append("|");
sb.append(map[i].key);
}
Settings.System.putStringForUser(context.getContentResolver(),
Settings.System.NAV_BUTTONS, sb.toString(), UserHandle.USER_CURRENT);
}
}