/*
* Copyright (C) 2016 The DirtyUnicorns Project
*
* 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.settings.du;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserHandle;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.internal.utils.du.ActionConstants;
import com.android.internal.utils.du.Config;
import com.android.internal.utils.du.Config.ButtonConfig;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.du.preference.CustomSeekBarPreference;
import net.margaritov.preference.colorpicker.ColorPickerPreference;
public class SmartbarSettings extends SettingsPreferenceFragment implements
OnPreferenceChangeListener {
private ListPreference mSmartBarContext;
private ListPreference mImeActions;
private ListPreference mButtonAnim;
private PreferenceScreen mPixel;
private ColorPickerPreference mNavbuttoncolor;
private CustomSeekBarPreference mButtonsAlpha;
private static final int MENU_RESET = Menu.FIRST;
private static final int MENU_SAVE = Menu.FIRST + 1;
private static final int MENU_RESTORE = Menu.FIRST + 2;
private static final int DEFAULT_TINT_COLOR = 0xFFFFFFFF;
private static final int DIALOG_RESET_CONFIRM = 1;
private static final int DIALOG_RESTORE_PROFILE = 2;
private static final int DIALOG_SAVE_PROFILE = 3;
private static final String CONFIG_STORAGE = Environment.getExternalStorageDirectory()
+ File.separator
+ "smartbar_configs";
private static final String SMARTBAR_CONFIGS_PREFIX = "smartbar_config_";
private static final String KEY_SMARTBAR_BACKUP = "smartbar_profile_save";
private static final String KEY_SMARTBAR_RESTORE = "smartbar_profile_restore";
private static final String PREF_NAVBAR_BUTTONS_ALPHA = "navbar_buttons_alpha";
private static final String NAVBAR_COLOR = "navbar_button_color";
private static final String PIXEL = "pixel_anim";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.smartbar_settings);
int intColor;
String hexColor;
int contextVal = Settings.Secure.getIntForUser(getContentResolver(),
"smartbar_context_menu_mode", 0, UserHandle.USER_CURRENT);
mSmartBarContext = (ListPreference) findPreference("smartbar_context_menu_position");
mSmartBarContext.setValue(String.valueOf(contextVal));
mSmartBarContext.setOnPreferenceChangeListener(this);
int imeVal = Settings.Secure.getIntForUser(getContentResolver(),
"smartbar_ime_hint_mode", 1, UserHandle.USER_CURRENT);
mImeActions = (ListPreference) findPreference("smartbar_ime_action");
mImeActions.setValue(String.valueOf(imeVal));
mImeActions.setOnPreferenceChangeListener(this);
int buttonAnimVal = Settings.Secure.getIntForUser(getContentResolver(),
"smartbar_button_animation_style", 0, UserHandle.USER_CURRENT);
mButtonAnim = (ListPreference) findPreference("smartbar_button_animation");
mButtonAnim.setValue(String.valueOf(buttonAnimVal));
mButtonAnim.setOnPreferenceChangeListener(this);
mButtonsAlpha =
(CustomSeekBarPreference) findPreference(PREF_NAVBAR_BUTTONS_ALPHA);
int bAlpha = Settings.Secure.getIntForUser(getContentResolver(),
Settings.Secure.NAVBAR_BUTTONS_ALPHA, 255, UserHandle.USER_CURRENT);
mButtonsAlpha.setValue(bAlpha / 1);
mButtonsAlpha.setOnPreferenceChangeListener(this);
mNavbuttoncolor = (ColorPickerPreference) findPreference(NAVBAR_COLOR);
mNavbuttoncolor.setOnPreferenceChangeListener(this);
intColor = Settings.System.getInt(getContentResolver(),
Settings.System.NAVBAR_BUTTON_COLOR, DEFAULT_TINT_COLOR);
hexColor = String.format("#%08x", (0xffffffff & intColor));
mNavbuttoncolor.setSummary(hexColor);
mNavbuttoncolor.setNewPreviewColor(intColor);
mPixel = (PreferenceScreen) findPreference(PIXEL);
updateAnimDurationPref(buttonAnimVal);
setHasOptionsMenu(true);
}
@Override
public Dialog onCreateDialog(int dialogId) {
Dialog dialog = null;
switch (dialogId) {
case DIALOG_RESET_CONFIRM:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
alertDialog.setTitle(R.string.smartbar_factory_reset_title);
alertDialog.setMessage(R.string.smartbar_factory_reset_confirm);
alertDialog.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
resetSmartbar();
}
});
alertDialog.setNegativeButton(R.string.write_settings_off, null);
dialog = alertDialog.create();
break;
case DIALOG_RESTORE_PROFILE:
final ConfigAdapter configAdapter = new ConfigAdapter(getActivity(),
getConfigFiles(CONFIG_STORAGE));
AlertDialog.Builder configDialog = new AlertDialog.Builder(getActivity());
configDialog.setTitle(R.string.smartbar_config_dialog_title);
configDialog.setNegativeButton(getString(android.R.string.cancel), null);
configDialog.setAdapter(configAdapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
String resultMsg;
try {
File configFile = (File) configAdapter.getItem(item);
String config = getSmartbarConfigFromStorage(configFile);
restoreConfig(getActivity(), config);
resultMsg = getString(R.string.smartbar_config_restore_success_toast);
} catch (Exception e) {
resultMsg = getString(R.string.smartbar_config_restore_error_toast);
}
Toast.makeText(getActivity(), resultMsg, Toast.LENGTH_SHORT).show();
}
});
dialog = configDialog.create();
break;
case DIALOG_SAVE_PROFILE:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final EditText input = new EditText(getActivity());
builder.setTitle(getString(R.string.smartbar_config_name_edit_dialog_title));
builder.setMessage(R.string.smartbar_config_name_edit_dialog_message);
builder.setView(input);
builder.setNegativeButton(getString(android.R.string.cancel), null);
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String inputText = input.getText().toString();
if (TextUtils.isEmpty(inputText)) {
inputText = String.valueOf(android.text.format.DateFormat
.format(
"yyyy-MM-dd_hh:mm:ss", new java.util.Date()));
}
String resultMsg;
try {
String currentConfig = getCurrentConfig(getActivity());
backupSmartbarConfig(currentConfig, inputText);
resultMsg = getString(R.string.smartbar_config_backup_success_toast);
} catch (Exception e) {
resultMsg = getString(R.string.smartbar_config_backup_error_toast);
}
Toast.makeText(getActivity(), resultMsg, Toast.LENGTH_SHORT).show();
}
});
dialog = builder.create();
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
break;
}
return dialog;
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (preference == findPreference("smartbar_editor_mode")) {
getActivity().sendBroadcastAsUser(new Intent("intent_navbar_edit"), UserHandle.CURRENT);
return true;
}
return super.onPreferenceTreeClick(preference);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_RESET, 0, R.string.reset)
.setIcon(com.android.internal.R.drawable.ic_menu_refresh)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(0, MENU_SAVE, 0, R.string.smartbar_backup_current_config_title)
.setIcon(R.drawable.ic_smartbar_save_profile)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
menu.add(0, MENU_RESTORE, 0, R.string.smartbar_restore_config_title)
.setIcon(R.drawable.ic_smartbar_restore_profile)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_RESET:
showDialog(DIALOG_RESET_CONFIRM);
return true;
case MENU_SAVE:
showDialog(DIALOG_SAVE_PROFILE);
return true;
case MENU_RESTORE:
showDialog(DIALOG_RESTORE_PROFILE);
return true;
default:
return super.onContextItemSelected(item);
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference.equals(mSmartBarContext)) {
int position = Integer.parseInt(((String) newValue).toString());
Settings.Secure.putInt(getContentResolver(), "smartbar_context_menu_mode",
position);
return true;
} else if (preference.equals(mButtonAnim)) {
int val = Integer.parseInt(((String) newValue).toString());
Settings.Secure.putInt(getContentResolver(), "smartbar_button_animation_style",
val);
updateAnimDurationPref(val);
return true;
} else if (preference.equals(mImeActions)) {
int val = Integer.parseInt(((String) newValue).toString());
Settings.Secure.putInt(getContentResolver(), "smartbar_ime_hint_mode",
val);
return true;
} else if (preference == mButtonsAlpha) {
int val = (Integer) newValue;
Settings.Secure.putIntForUser(getContentResolver(),
Settings.Secure.NAVBAR_BUTTONS_ALPHA, val * 1, UserHandle.USER_CURRENT);
return true;
} else if (preference == mNavbuttoncolor) {
String hex = ColorPickerPreference.convertToARGB(
Integer.valueOf(String.valueOf(newValue)));
preference.setSummary(hex);
int intHex = ColorPickerPreference.convertToColorInt(hex);
Settings.System.putInt(getContentResolver(),
Settings.System.NAVBAR_BUTTON_COLOR, intHex);
return true;
}
return false;
}
public void updateAnimDurationPref(int buttonAnimVal) {
if (buttonAnimVal == 0 || buttonAnimVal == 1 || buttonAnimVal == 2) {
mPixel.setEnabled(false);
} else {
mPixel.setEnabled(true);
}
}
private void resetSmartbar() {
ArrayList<ButtonConfig> buttonConfigs = Config.getDefaultConfig(
getActivity(),
ActionConstants.getDefaults(ActionConstants.SMARTBAR));
Config.setConfig(getActivity(),
ActionConstants.getDefaults(ActionConstants.SMARTBAR),
buttonConfigs);
Intent intent = new Intent("intent_navbar_edit");
intent.putExtra("extra_navbar_edit_reset_layout", "resetMePlox");
getActivity().sendBroadcastAsUser(intent, UserHandle.CURRENT);
Settings.Secure.putInt(getContentResolver(),
"smartbar_context_menu_mode", 0);
mSmartBarContext.setValue(String.valueOf(0));
mSmartBarContext.setOnPreferenceChangeListener(this);
Settings.Secure.putInt(getContentResolver(),
"smartbar_ime_hint_mode", 1);
mImeActions.setValue(String.valueOf(1));
mImeActions.setOnPreferenceChangeListener(this);
Settings.Secure.putInt(getContentResolver(),
"smartbar_button_animation_style", 0);
mButtonAnim.setValue(String.valueOf(0));
mButtonAnim.setOnPreferenceChangeListener(this);
Settings.Secure.putInt(getContentResolver(),
"navbar_buttons_alpha", 255);
mButtonsAlpha.setValue(255);
mButtonsAlpha.setOnPreferenceChangeListener(this);
}
static class ConfigAdapter extends ArrayAdapter<File> {
private final ArrayList<File> mConfigFiles;
private final Context mContext;
public ConfigAdapter(Context context, ArrayList<File> files) {
super(context, android.R.layout.select_dialog_item, files);
mContext = context;
mConfigFiles = files;
}
public View getView(int position, View convertView, ViewGroup parent) {
View itemRow = convertView;
File f = mConfigFiles.get(position);
itemRow = ((LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(android.R.layout.select_dialog_item, null);
String name = f.getName();
if (name.startsWith(SMARTBAR_CONFIGS_PREFIX)) {
name = f.getName().substring(SMARTBAR_CONFIGS_PREFIX.length(), f.getName().length());
}
((TextView) itemRow.findViewById(android.R.id.text1)).setText(name);
return itemRow;
}
}
private static class StartsWithFilter implements FileFilter {
private String[] mStartsWith;
public StartsWithFilter(String[] startsWith) {
mStartsWith = startsWith;
}
@Override
public boolean accept(File file) {
for (String extension : mStartsWith) {
if (file.getName().toLowerCase().startsWith(extension)) {
return true;
}
}
return false;
}
}
static String getCurrentConfig(Context ctx) {
String config = Settings.Secure.getStringForUser(
ctx.getContentResolver(), ActionConstants.getDefaults(ActionConstants.SMARTBAR)
.getUri(),
UserHandle.USER_CURRENT);
if (TextUtils.isEmpty(config)) {
config = ActionConstants.getDefaults(ActionConstants.SMARTBAR).getDefaultConfig();
}
return config;
}
static void restoreConfig(Context context, String config) {
Settings.Secure.putStringForUser(context.getContentResolver(),
ActionConstants.getDefaults(ActionConstants.SMARTBAR)
.getUri(), config,
UserHandle.USER_CURRENT);
Intent intent = new Intent("intent_navbar_edit");
intent.putExtra("extra_navbar_edit_reset_layout", "resetMePlox");
context.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
static void backupSmartbarConfig(String config, String suffix) {
File dir = new File(CONFIG_STORAGE);
if (!dir.exists()) {
dir.mkdirs();
}
File configFile = new File(dir, SMARTBAR_CONFIGS_PREFIX + suffix);
FileOutputStream stream;
try {
stream = new FileOutputStream(configFile);
stream.write(config.getBytes());
stream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static String getSmartbarConfigFromStorage(File file) {
int length = (int) file.length();
byte[] bytes = new byte[length];
FileInputStream in;
try {
in = new FileInputStream(file);
in.read(bytes);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
String contents = new String(bytes);
return contents;
}
public static ArrayList<File> getConfigFiles(String path) {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
ArrayList<File> list = new ArrayList<File>();
for (File tmp : dir.listFiles(new StartsWithFilter(new String[] {
SMARTBAR_CONFIGS_PREFIX
}))) {
list.add(tmp);
}
return list;
}
@Override
protected int getMetricsCategory() {
return MetricsEvent.APPLICATION;
}
}