OmniLib: Introduce OmniRom SDK
* omnilib-res app will be installed to system/frameworks for the futur internal ressources add-on
* OmniLib java_library will be installed to system/frameworks for the futur internal java/aidl add-on
* The OmniPreference android_library need to be moved outside system/frameworks because of some nested dependency breakage
Change-Id: I2b9a7bc7f4aa72052ae6600933eb114d2a481b35
omnilib-res: Add allow-reserved-package-id
Thx to the LineageOS team
https://github.com/LineageOS/android_lineage-sdk/blob/lineage-20.0/Android.bp#L44-L49
Change-Id: I07ba56685981a8735bdef5ea75528ec82dd68318
diff --git a/omnipreference/java/omnirom/preference/AppMultiSelectListPreference.java b/omnipreference/java/omnirom/preference/AppMultiSelectListPreference.java
new file mode 100644
index 0000000..008b77d
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/AppMultiSelectListPreference.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package omnirom.preference;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import omnirom.preference.R;
+import com.android.settingslib.CustomDialogPreferenceCompat;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class AppMultiSelectListPreference extends CustomDialogPreferenceCompat {
+ private static final String TAG = "AppMultiSelectList";
+ private static final boolean DEBUG = false;
+
+ private final List<PackageItem> mPackageInfoList = new ArrayList<PackageItem>();
+ private AppListAdapter mAdapter;
+ private List<String> mValues = new ArrayList<String>();
+ private PackageManager mPm;
+
+ public AppMultiSelectListPreference(Context context) {
+ this(context, null);
+ }
+
+ public AppMultiSelectListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setDialogLayoutResource(R.layout.preference_app_list);
+
+ mPm = context.getPackageManager();
+
+ final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ List<ResolveInfo> installedAppsInfo = getContext().getPackageManager().queryIntentActivities(
+ mainIntent, 0);
+
+ for (ResolveInfo info : installedAppsInfo) {
+ ComponentName componentName = new ComponentName(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name);
+
+ try {
+ final PackageItem item = new PackageItem(
+ info.activityInfo.loadLabel(mPm), 0, componentName);
+ mPackageInfoList.add(item);
+ } catch (Exception e) {
+ if (DEBUG) Log.e(TAG, "Load installed apps", e);
+ }
+ }
+ Collections.sort(mPackageInfoList);
+
+ setPositiveButtonText(R.string.action_save);
+ setNegativeButtonText(android.R.string.cancel);
+ }
+
+ public void setValues(Collection<String> values) {
+ mValues.clear();
+ mValues.addAll(values);
+ }
+
+ public Collection<String> getValues() {
+ return mValues;
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mAdapter = new AppListAdapter(getContext());
+ final ListView listView = (ListView) view.findViewById(R.id.app_list);
+ listView.setAdapter(mAdapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final AppViewHolder holder = (AppViewHolder) view.getTag();
+ final boolean isChecked = !holder.checkBox.isChecked();
+
+ holder.checkBox.setChecked(isChecked);
+ PackageItem info = mAdapter.getItem(position);
+
+ if (isChecked) {
+ mValues.add(info.mValue);
+ } else {
+ mValues.remove(info.mValue);
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ if (positiveResult) {
+ callChangeListener(mValues.size() > 0 ? mValues : null);
+ }
+ }
+
+ public class PackageItem implements Comparable<PackageItem> {
+ public final CharSequence mTitle;
+ public final int mAppIconResourceId;
+ public final ComponentName mComponentName;
+ public final String mValue;
+
+ PackageItem(CharSequence title, int iconResourceId, ComponentName componentName) {
+ mTitle = title;
+ mAppIconResourceId = iconResourceId;
+ mComponentName = componentName;
+ mValue = componentName.flattenToString();
+ }
+
+ PackageItem(CharSequence title, int iconResourceId, String value) {
+ mTitle = title;
+ mAppIconResourceId = iconResourceId;
+ mComponentName = null;
+ mValue = value;
+ }
+
+ @Override
+ public int compareTo(PackageItem another) {
+ return mTitle.toString().toUpperCase().compareTo(another.mTitle.toString().toUpperCase());
+ }
+
+ @Override
+ public int hashCode() {
+ return mValue.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object another) {
+ if (another == null || !(another instanceof PackageItem)) {
+ return false;
+ }
+ return mValue.equals(((PackageItem) another).mValue);
+ }
+ }
+
+ public class AppListAdapter extends ArrayAdapter<PackageItem> {
+ private final LayoutInflater mInflater;
+
+ public AppListAdapter(Context context) {
+ super(context, 0);
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ addAll(mPackageInfoList);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
+ convertView = holder.rootView;
+ PackageItem info = getItem(position);
+ holder.appName.setText(info.mTitle);
+ if (info.mAppIconResourceId != 0) {
+ holder.appIcon.setImageResource(info.mAppIconResourceId);
+ } else {
+ Drawable d = resolveAppIcon(info);
+ holder.appIcon.setImageDrawable(d);
+ }
+ holder.checkBox.setChecked(mValues.contains(info.mValue));
+ return convertView;
+ }
+
+ @Override
+ public PackageItem getItem(int position) {
+ return mPackageInfoList.get(position);
+ }
+ }
+
+ public static class AppViewHolder {
+ public View rootView;
+ public TextView appName;
+ public ImageView appIcon;
+ public CheckBox checkBox;
+
+ public static AppViewHolder createOrRecycle(LayoutInflater inflater, View convertView) {
+ if (convertView == null) {
+ convertView = inflater.inflate(R.layout.app_select_item, null);
+
+ // Creates a ViewHolder and store references to the two children views
+ // we want to bind data to.
+ AppViewHolder holder = new AppViewHolder();
+ holder.rootView = convertView;
+ holder.appName = (TextView) convertView.findViewById(R.id.app_name);
+ holder.appIcon = (ImageView) convertView.findViewById(R.id.app_icon);
+ holder.checkBox = (CheckBox) convertView.findViewById(android.R.id.checkbox);
+ convertView.setTag(holder);
+ return holder;
+ } else {
+ // Get the ViewHolder back to get fast access to the TextView
+ // and the ImageView.
+ return (AppViewHolder) convertView.getTag();
+ }
+ }
+ }
+
+ private Drawable getDefaultActivityIcon() {
+ return getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
+ }
+
+ private Drawable resolveAppIcon(PackageItem item) {
+ Drawable appIcon = null;
+ try {
+ appIcon = mPm.getActivityIcon(item.mComponentName);
+ } catch (PackageManager.NameNotFoundException e) {
+ if (DEBUG) Log.e(TAG, "resolveAppIcon", e);
+ }
+ if (appIcon == null) {
+ appIcon = getDefaultActivityIcon();
+ }
+ return appIcon;
+ }
+}
+
diff --git a/omnipreference/java/omnirom/preference/AppSelectListPreference.java b/omnipreference/java/omnirom/preference/AppSelectListPreference.java
new file mode 100644
index 0000000..86c3152
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/AppSelectListPreference.java
@@ -0,0 +1,339 @@
+/*
+* Copyright (C) 2017 The OmniROM Project
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package omnirom.preference;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.PreferenceDialogFragment;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.android.settingslib.CustomDialogPreferenceCompat;
+import omnirom.preference.R;
+
+public class AppSelectListPreference extends CustomDialogPreferenceCompat {
+
+ private static String TAG = "AppSelectListPreference";
+ public static final String DISABLED_ENTRY = "disabled";
+
+ private AppSelectListAdapter mAdapter;
+ private Drawable mAppIconDrawable;
+ private int mAppIconResourceId;
+ private CharSequence mTitle;
+ private String mValue;
+ private PackageManager mPm;
+
+ public class PackageItem implements Comparable<PackageItem> {
+ public final CharSequence mTitle;
+ public final int mAppIconResourceId;
+ public final ComponentName mComponentName;
+ public final String mValue;
+
+ PackageItem(CharSequence title, int iconResourceId, ComponentName componentName) {
+ mTitle = title;
+ mAppIconResourceId = iconResourceId;
+ mComponentName = componentName;
+ mValue = componentName.flattenToString();
+ }
+
+ PackageItem(CharSequence title, int iconResourceId, String value) {
+ mTitle = title;
+ mAppIconResourceId = iconResourceId;
+ mComponentName = null;
+ mValue = value;
+ }
+
+ @Override
+ public int compareTo(PackageItem another) {
+ return mTitle.toString().toUpperCase().compareTo(another.mTitle.toString().toUpperCase());
+ }
+
+ @Override
+ public int hashCode() {
+ return mValue.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object another) {
+ if (another == null || !(another instanceof PackageItem)) {
+ return false;
+ }
+ return mValue.equals(((PackageItem) another).mValue);
+ }
+ }
+
+ public class AppSelectListAdapter extends BaseAdapter implements Runnable {
+ private LayoutInflater mInflater;
+ private List<PackageItem> mInstalledPackages = new LinkedList<PackageItem>();
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ PackageItem disabledItem = new PackageItem(getContext().getResources().getString(R.string.disabled_entry),
+ R.drawable.ic_disabled, DISABLED_ENTRY);
+ mInstalledPackages.add(0, disabledItem);
+
+ notifyDataSetChanged();
+ updatePreferenceViews();
+ }
+ };
+
+ public AppSelectListAdapter(Context context) {
+ mInflater = LayoutInflater.from(context);
+ reloadList();
+ }
+
+ @Override
+ public int getCount() {
+ return mInstalledPackages.size();
+ }
+
+ @Override
+ public PackageItem getItem(int position) {
+ return mInstalledPackages.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mInstalledPackages.get(position).hashCode();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder holder;
+ if (convertView != null) {
+ holder = (ViewHolder) convertView.getTag();
+ } else {
+ convertView = mInflater.inflate(R.layout.applist_preference_icon, null, false);
+ holder = new ViewHolder();
+ convertView.setTag(holder);
+ holder.title = (TextView) convertView.findViewById(R.id.title);
+ holder.icon = (ImageView) convertView.findViewById(R.id.icon);
+ }
+
+ PackageItem applicationInfo = getItem(position);
+ holder.title.setText(applicationInfo.mTitle);
+ if (applicationInfo.mAppIconResourceId != 0) {
+ holder.icon.setImageResource(applicationInfo.mAppIconResourceId);
+ } else {
+ Drawable d = resolveAppIcon(applicationInfo);
+ holder.icon.setImageDrawable(d);
+ }
+ return convertView;
+ }
+
+ private void reloadList() {
+ mInstalledPackages.clear();
+ new Thread(this).start();
+ }
+
+ @Override
+ public void run() {
+ final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ List<ResolveInfo> installedAppsInfo = mPm.queryIntentActivities(mainIntent, 0);
+
+ for (ResolveInfo info : installedAppsInfo) {
+ ActivityInfo activity = info.activityInfo;
+ ApplicationInfo appInfo = activity.applicationInfo;
+ ComponentName componentName = new ComponentName(appInfo.packageName, activity.name);
+ CharSequence label = null;
+ try {
+ label = activity.loadLabel(mPm);
+ } catch (Exception e) {
+ }
+ if (label != null) {
+ final PackageItem item = new PackageItem(activity.loadLabel(mPm), 0, componentName);
+ mInstalledPackages.add(item);
+ }
+ }
+ Collections.sort(mInstalledPackages);
+ mHandler.obtainMessage(0).sendToTarget();
+ }
+
+ private PackageItem resolveApplication(ComponentName componentName) {
+ for (PackageItem item : mInstalledPackages) {
+ if (item.mComponentName != null && item.mComponentName.equals(componentName)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ private class ViewHolder {
+ TextView title;
+ TextView summary;
+ ImageView icon;
+ }
+ }
+
+ public AppSelectListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public AppSelectListPreference(Context context, int color) {
+ super(context, null);
+ init();
+ }
+
+ private void init() {
+ mPm = getContext().getPackageManager();
+ setDialogLayoutResource(R.layout.preference_app_list);
+ setLayoutResource(R.layout.preference_app_select);
+ setNegativeButtonText(android.R.string.cancel);
+ setPositiveButtonText(null);
+ setDialogTitle(R.string.choose_app);
+ setDialogIcon(null);
+ mAdapter = new AppSelectListAdapter(getContext());
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
+ super.onSetInitialValue(restorePersistedValue, defaultValue);
+ if (mTitle != null) {
+ setSummary(mTitle);
+ } else {
+ setSummary(getContext().getResources().getString(R.string.not_ready_summary));
+ }
+ mAppIconResourceId = R.drawable.ic_disabled;
+ setIcon(mAppIconResourceId);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ final ListView list = (ListView) view.findViewById(R.id.app_list);
+ list.setAdapter(mAdapter);
+ list.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ PackageItem info = (PackageItem) parent.getItemAtPosition(position);
+ mValue = info.mValue;
+ if (shouldPersist()) {
+ persistString(mValue);
+ }
+ mTitle = info.mTitle;
+ mAppIconDrawable = null;
+ mAppIconResourceId = 0;
+ if (info.mComponentName != null) {
+ mAppIconDrawable = resolveAppIcon(info);
+ } else {
+ mAppIconResourceId = info.mAppIconResourceId;
+ }
+
+ updatePreferenceViews();
+ callChangeListener(mValue);
+ getDialog().dismiss();
+ }
+ });
+ }
+
+ private void updatePreferenceViews() {
+ String name = null;
+ if (shouldPersist()) {
+ name = getPersistedString(null);
+ } else {
+ name = mValue;
+ }
+ mAppIconResourceId = R.drawable.ic_disabled;
+
+ if (name != null) {
+ if (name.equals(DISABLED_ENTRY)) {
+ mTitle = getContext().getResources().getString(R.string.disabled_entry);
+ mAppIconResourceId = R.drawable.ic_disabled;
+ } else {
+ mAppIconDrawable = null;
+ ComponentName componentName = ComponentName.unflattenFromString(name);
+ PackageItem item = mAdapter.resolveApplication(componentName);
+ if (item != null) {
+ mTitle = item.mTitle;
+ mAppIconDrawable = resolveAppIcon(item);
+ } else {
+ mTitle = getContext().getResources().getString(R.string.resolve_failed_summary);
+ }
+ }
+ } else {
+ mTitle = getContext().getResources().getString(R.string.disabled_entry);
+ mAppIconResourceId = R.drawable.ic_disabled;
+ }
+
+ setSummary(mTitle);
+ if (mAppIconDrawable != null) {
+ setIcon(mAppIconDrawable);
+ } else {
+ setIcon(mAppIconResourceId);
+ }
+ }
+
+ private Drawable getDefaultActivityIcon() {
+ return getContext().getResources().getDrawable(android.R.drawable.sym_def_app_icon);
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+
+ public void setValue(String value) {
+ mValue = value;
+ }
+
+ private Drawable resolveAppIcon(PackageItem item) {
+ Drawable appIcon = null;
+ try {
+ appIcon = mPm.getActivityIcon(item.mComponentName);
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ if (appIcon == null) {
+ appIcon = getDefaultActivityIcon();
+ }
+ return appIcon;
+ }
+
+ public static class AppSelectListPreferenceDialogFragment
+ extends CustomDialogPreferenceCompat.CustomPreferenceDialogFragment {
+ public static CustomDialogPreferenceCompat.CustomPreferenceDialogFragment
+ newInstance(String key) {
+ return CustomDialogPreferenceCompat.CustomPreferenceDialogFragment.newInstance(key);
+ }
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/ColorSelectDialog.java b/omnipreference/java/omnirom/preference/ColorSelectDialog.java
new file mode 100644
index 0000000..ccd93f9
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/ColorSelectDialog.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ * Copyright (C) 2012 The CyanogenMod 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 omnirom.preference;
+
+import android.app.Activity;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.text.InputFilter;
+import android.text.InputFilter.LengthFilter;
+import android.util.Pair;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.Spinner;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+
+import omnirom.preference.R;
+import omnirom.ui.ColorPanelView;
+import omnirom.ui.ColorPickerView;
+import omnirom.ui.ColorPickerView.OnColorChangedListener;
+
+import java.util.ArrayList;
+import java.util.IllegalFormatException;
+import java.util.Locale;
+
+public class ColorSelectDialog extends AlertDialog implements
+ ColorPickerView.OnColorChangedListener, TextWatcher, OnFocusChangeListener {
+
+ private static final String TAG = "ColorSelectDialog";
+ private final static String STATE_KEY_COLOR = "BatteryLightDialog:color";
+
+ private ColorPickerView mColorPicker;
+
+ private EditText mHexColorInput;
+ private ColorPanelView mNewColor;
+ private LayoutInflater mInflater;
+ private boolean mMultiColor = true;
+ private Spinner mColorList;
+ private LinearLayout mColorListView;
+ private LinearLayout mColorPanelView;
+ private ColorPanelView mNewListColor;
+ private LedColorAdapter mLedColorAdapter;
+ private boolean mWithAlpha;
+
+ private boolean mShowLedPreview;
+ private boolean mShowMultiColor;
+ private NotificationManager mNoMan;
+ private Context mContext;
+
+ protected ColorSelectDialog(Context context, int initialColor, boolean showMultiColor, boolean showLedPreview, boolean withAlpha) {
+ super(context);
+ mContext = context;
+ mShowLedPreview = showLedPreview;
+ mWithAlpha = withAlpha;
+ mShowMultiColor = showMultiColor;
+ mMultiColor =
+ (getContext().getResources().getBoolean(R.bool.config_has_multi_color_led) || mShowMultiColor);
+ init(initialColor);
+ }
+
+ private void init(int color) {
+ // To fight color banding.
+ getWindow().setFormat(PixelFormat.RGBA_8888);
+ setUp(color);
+ }
+
+ /**
+ * This function sets up the dialog with the proper values. If the speedOff parameters
+ * has a -1 value disable both spinners
+ *
+ * @param color - the color to set
+ * @param speedOn - the flash time in ms
+ * @param speedOff - the flash length in ms
+ */
+ private void setUp(int color) {
+ mInflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View layout = mInflater.inflate(R.layout.dialog_battery_settings, null);
+
+ mNoMan = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ mColorPicker = (ColorPickerView) layout.findViewById(R.id.color_picker_view);
+ mHexColorInput = (EditText) layout.findViewById(R.id.hex_color_input);
+ mNewColor = (ColorPanelView) layout.findViewById(R.id.color_panel);
+ mColorPanelView = (LinearLayout) layout.findViewById(R.id.color_panel_view);
+
+ mColorListView = (LinearLayout) layout.findViewById(R.id.color_list_view);
+ mColorList = (Spinner) layout.findViewById(R.id.color_list_spinner);
+ mNewListColor = (ColorPanelView) layout.findViewById(R.id.color_list_panel);
+
+ mColorPicker.setOnColorChangedListener(this);
+ mHexColorInput.setOnFocusChangeListener(this);
+ setAlphaSliderVisible(mWithAlpha);
+ mColorPicker.setColor(color, true);
+ showLed(color);
+
+ mColorList = (Spinner) layout.findViewById(R.id.color_list_spinner);
+ mLedColorAdapter = new LedColorAdapter(
+ R.array.entries_led_colors,
+ R.array.values_led_colors);
+ mColorList.setAdapter(mLedColorAdapter);
+ mColorList.setSelection(mLedColorAdapter.getColorPosition(color));
+ mColorList.setOnItemSelectedListener(mColorListListener);
+
+ setView(layout);
+
+ // show and hide the correct UI depending if we have multi-color led or not
+ if (mMultiColor){
+ mColorListView.setVisibility(View.GONE);
+ mColorPicker.setVisibility(View.VISIBLE);
+ mColorPanelView.setVisibility(View.VISIBLE);
+ } else {
+ mColorListView.setVisibility(View.VISIBLE);
+ mColorPicker.setVisibility(View.GONE);
+ mColorPanelView.setVisibility(View.GONE);
+ }
+ }
+
+ private AdapterView.OnItemSelectedListener mColorListListener = new AdapterView.OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ int color = mLedColorAdapter.getColor(position);
+ mNewListColor.setColor(color);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ };
+
+ @Override
+ public Bundle onSaveInstanceState() {
+ Bundle state = super.onSaveInstanceState();
+ state.putInt(STATE_KEY_COLOR, getColor());
+ switchOffLed();
+ return state;
+ }
+
+ @Override
+ public void onRestoreInstanceState(Bundle state) {
+ super.onRestoreInstanceState(state);
+ mColorPicker.setColor(state.getInt(STATE_KEY_COLOR), true);
+ }
+
+ @Override
+ public void onColorChanged(int color) {
+ final boolean hasAlpha = mWithAlpha;
+ final String format = hasAlpha ? "%08x" : "%06x";
+ final int mask = hasAlpha ? 0xFFFFFFFF : 0x00FFFFFF;
+
+ mNewColor.setColor(color);
+ mHexColorInput.setText(String.format(Locale.US, format, color & mask));
+
+ showLed(color);
+ }
+
+ private void showLed(int color) {
+ /*if (mShowLedPreview) {
+ if (color == 0xFFFFFFFF) {
+ // argb white doesn't work
+ color = 0xffffff;
+ }
+ mNoMan.forceShowLedLight(color);
+ }*/
+ }
+
+ public void switchOffLed() {
+ /*if (mShowLedPreview) {
+ mNoMan.forceShowLedLight(-1);
+ }*/
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ switchOffLed();
+ }
+
+ public void setAlphaSliderVisible(boolean visible) {
+ mHexColorInput.setFilters(new InputFilter[] { new InputFilter.LengthFilter(visible ? 8 : 6) } );
+ mColorPicker.setAlphaSliderVisible(visible);
+ }
+
+ public int getColor() {
+ if (mMultiColor){
+ return mColorPicker.getColor();
+ } else {
+ return mNewListColor.getColor();
+ }
+ }
+
+ class LedColorAdapter extends BaseAdapter implements SpinnerAdapter {
+ private ArrayList<Pair<String, Integer>> mColors;
+
+ public LedColorAdapter(int ledColorResource, int ledValueResource) {
+ mColors = new ArrayList<Pair<String, Integer>>();
+
+ String[] color_names = getContext().getResources().getStringArray(ledColorResource);
+ String[] color_values = getContext().getResources().getStringArray(ledValueResource);
+
+ for(int i = 0; i < color_values.length; ++i) {
+ try {
+ int color = Color.parseColor(color_values[i]);
+ mColors.add(new Pair<String, Integer>(color_names[i], color));
+ } catch (IllegalArgumentException ex) {
+ // Number format is incorrect, ignore entry
+ }
+ }
+ }
+
+ /**
+ * Will return the position of the spinner entry with the specified
+ * color. Returns 0 if there is no such entry.
+ */
+ public int getColorPosition(int color) {
+ for (int position = 0; position < getCount(); ++position) {
+ if (getItem(position).second.equals(color)) {
+ return position;
+ }
+ }
+
+ return 0;
+ }
+
+ public int getColor(int position) {
+ Pair<String, Integer> item = getItem(position);
+ if (item != null){
+ return item.second;
+ }
+
+ // -1 is white
+ return -1;
+ }
+
+ @Override
+ public int getCount() {
+ return mColors.size();
+ }
+
+ @Override
+ public Pair<String, Integer> getItem(int position) {
+ return mColors.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View view, ViewGroup parent) {
+ if (view == null) {
+ view = mInflater.inflate(R.layout.led_color_item, null);
+ }
+
+ Pair<String, Integer> entry = getItem(position);
+ ((TextView) view.findViewById(R.id.textViewName)).setText(entry.first);
+
+ return view;
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ String hexColor = mHexColorInput.getText().toString();
+ if (!hexColor.isEmpty()) {
+ try {
+ int color = Color.parseColor('#' + hexColor);
+ if (!mWithAlpha) {
+ color |= 0xFF000000; // set opaque
+ }
+ mColorPicker.setColor(color);
+ mNewColor.setColor(color);
+ } catch (IllegalArgumentException ex) {
+ // Number format is incorrect, ignore
+ }
+ }
+ }
+
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (!hasFocus) {
+ mHexColorInput.removeTextChangedListener(this);
+ InputMethodManager inputMethodManager = (InputMethodManager) getContext()
+ .getSystemService(Activity.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ } else {
+ mHexColorInput.addTextChangedListener(this);
+ }
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/ColorSelectPreference.java b/omnipreference/java/omnirom/preference/ColorSelectPreference.java
new file mode 100644
index 0000000..97a39d5
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/ColorSelectPreference.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.RectShape;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.ImageView;
+
+import androidx.appcompat.app.AlertDialog;
+
+import omnirom.preference.R;
+
+public class ColorSelectPreference extends Preference implements DialogInterface.OnDismissListener {
+
+ private static String TAG = "ColorSelectPreference";
+ public static final int DEFAULT_COLOR = 0xFFFFFF; //White
+
+ private ImageView mLightColorView;
+ private Resources mResources;
+ protected int mColorValue;
+ private AlertDialog mDialog;
+
+ private boolean mShowLedPreview;
+ private boolean mShowMultiColor;
+ private boolean mWithAlpha;
+
+ /**
+ * @param context
+ * @param attrs
+ */
+ public ColorSelectPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mColorValue = DEFAULT_COLOR;
+ init(context, attrs);
+ }
+
+ public ColorSelectPreference(Context context, int color) {
+ super(context, null);
+ mColorValue = color;
+ init(context, null);
+ }
+
+ public ColorSelectPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mColorValue = DEFAULT_COLOR;
+ init(context, attrs);
+ }
+
+ protected void init(Context context, AttributeSet attrs) {
+ setLayoutResource(R.layout.preference_color_select);
+ mResources = getContext().getResources();
+ if (attrs != null) {
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.ColorSelectPreference);
+ final TypedValue useWithAlpha = attributes.peekValue(
+ R.styleable.ColorSelectPreference_withAlpha);
+ if (useWithAlpha != null) {
+ mWithAlpha = (useWithAlpha.type == TypedValue.TYPE_INT_BOOLEAN
+ && useWithAlpha.data != 0);
+ }
+ final TypedValue useLedPreview = attributes.peekValue(
+ R.styleable.ColorSelectPreference_ledPreview);
+ if (useLedPreview != null) {
+ mShowLedPreview = (useLedPreview.type == TypedValue.TYPE_INT_BOOLEAN
+ && useLedPreview.data != 0);
+ }
+ final TypedValue useMultiColor = attributes.peekValue(
+ R.styleable.ColorSelectPreference_multiColor);
+ if (useMultiColor != null) {
+ mShowMultiColor = (useMultiColor.type == TypedValue.TYPE_INT_BOOLEAN
+ && useMultiColor.data != 0);
+ }
+ }
+ }
+
+ public void setColor(int color) {
+ mColorValue = color;
+ updatePreferenceViews();
+ }
+
+ public int getColor() {
+ return mColorValue;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ mLightColorView = (ImageView) holder.findViewById(R.id.light_color);
+
+ updatePreferenceViews();
+ }
+
+ private void updatePreferenceViews() {
+ final int width = (int) mResources.getDimension(R.dimen.color_preference_width);
+ final int height = (int) mResources.getDimension(R.dimen.color_preference_height);
+
+ if (mLightColorView != null) {
+ mLightColorView.setEnabled(true);
+ mLightColorView.setImageDrawable(createRectShape(width, height, 0xFF000000 | mColorValue));
+ }
+ }
+
+ @Override
+ protected void onClick() {
+ if (mDialog != null && mDialog.isShowing()) return;
+ mDialog = getDialog();
+ mDialog.setOnDismissListener(this);
+ mDialog.show();
+ }
+
+ public AlertDialog getDialog() {
+ final ColorSelectDialog d = new ColorSelectDialog(getContext(),
+ 0xFF000000 | mColorValue, mShowMultiColor, mShowLedPreview, mWithAlpha);
+
+ d.setButton(AlertDialog.BUTTON_POSITIVE, mResources.getString(android.R.string.ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ int color = 0;
+ if (mShowLedPreview) {
+ color = d.getColor() & 0x00FFFFFF; // strip alpha, led does not support it
+ d.switchOffLed();
+ } else {
+ color = d.getColor();
+ }
+ setColor(color);
+ callChangeListener(new Integer(color));
+ }
+ });
+ d.setButton(AlertDialog.BUTTON_NEGATIVE, mResources.getString(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ d.switchOffLed();
+ }
+ });
+
+ return d;
+ }
+
+ private static ShapeDrawable createRectShape(int width, int height, int color) {
+ ShapeDrawable shape = new ShapeDrawable(new RectShape());
+ shape.setIntrinsicHeight(height);
+ shape.setIntrinsicWidth(width);
+ shape.getPaint().setColor(color);
+ return shape;
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mDialog = null;
+ }
+
+ public void setWithAlpha(boolean value) {
+ mWithAlpha = value;
+ }
+
+ public void setWithLedPreview(boolean value) {
+ mShowLedPreview = value;
+ }
+
+ public void setWithMultiColor(boolean value) {
+ mShowMultiColor = value;
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/GlobalCheckBoxPreference.java b/omnipreference/java/omnirom/preference/GlobalCheckBoxPreference.java
new file mode 100644
index 0000000..01a9e69
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/GlobalCheckBoxPreference.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import androidx.preference.CheckBoxPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public class GlobalCheckBoxPreference extends CheckBoxPreference {
+ public GlobalCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public GlobalCheckBoxPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public GlobalCheckBoxPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ Settings.Global.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return Settings.Global.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setChecked(Settings.Global.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
+ : (Boolean) defaultValue);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/GlobalSettingSwitchPreference.java b/omnipreference/java/omnirom/preference/GlobalSettingSwitchPreference.java
new file mode 100644
index 0000000..1996a4b
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/GlobalSettingSwitchPreference.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import androidx.preference.SwitchPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public class GlobalSettingSwitchPreference extends SwitchPreference {
+ public GlobalSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public GlobalSettingSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public GlobalSettingSwitchPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+ Settings.Global.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+ return Settings.Global.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setChecked(Settings.Global.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
+ : (Boolean) defaultValue);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/ScrollAppsViewPreference.java b/omnipreference/java/omnirom/preference/ScrollAppsViewPreference.java
new file mode 100644
index 0000000..bf84431
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/ScrollAppsViewPreference.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package omnirom.preference;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import omnirom.preference.R;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class ScrollAppsViewPreference extends Preference {
+ private static final String TAG = "ScrollAppsPreference";
+
+ private Context mContext;
+ private List<String> mValues = new ArrayList<String>();
+ private PackageManager mPm;
+ private LayoutInflater mInflater;
+
+ public ScrollAppsViewPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ initPreference(context);
+ }
+
+ public ScrollAppsViewPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ initPreference(context);
+ }
+
+ public ScrollAppsViewPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initPreference(context);
+ }
+
+ public void setValues(Collection<String> values) {
+ mValues.clear();
+ mValues.addAll(values);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ LinearLayout linearLayout = (LinearLayout) holder.findViewById(R.id.selected_apps);
+ if (linearLayout.getChildCount() > 0) linearLayout.removeAllViews();
+
+ for (String value : mValues) {
+ try {
+ View v = mInflater.inflate(R.layout.app_grid_item, null);
+ ComponentName componentName = ComponentName.unflattenFromString(value);
+ Drawable icon = mPm.getActivityIcon(componentName);
+ ((ImageView) v.findViewById(R.id.appIcon)).setImageDrawable(icon);
+ v.setPadding(10, 5, 10, 5);
+ linearLayout.addView(v);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Set app icon", e);
+ }
+ }
+ }
+
+ private void initPreference(Context context) {
+ mContext = context;
+ setLayoutResource(R.layout.preference_selected_apps_view);
+ mPm = context.getPackageManager();
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/SecureCheckBoxPreference.java b/omnipreference/java/omnirom/preference/SecureCheckBoxPreference.java
new file mode 100644
index 0000000..5f281fb
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/SecureCheckBoxPreference.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import androidx.preference.CheckBoxPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public class SecureCheckBoxPreference extends CheckBoxPreference {
+ public SecureCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public SecureCheckBoxPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SecureCheckBoxPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ Settings.Secure.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return Settings.Secure.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setChecked(Settings.Secure.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
+ : (Boolean) defaultValue);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/SecureSettingSwitchPreference.java b/omnipreference/java/omnirom/preference/SecureSettingSwitchPreference.java
new file mode 100644
index 0000000..0a33f2b
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/SecureSettingSwitchPreference.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import androidx.preference.SwitchPreference;
+import android.util.AttributeSet;
+
+import android.provider.Settings;
+
+public class SecureSettingSwitchPreference extends SwitchPreference {
+ public SecureSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public SecureSettingSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SecureSettingSwitchPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+ Settings.Secure.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+ return Settings.Secure.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setChecked(Settings.Secure.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
+ : (Boolean) defaultValue);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/SeekBarPreference.java b/omnipreference/java/omnirom/preference/SeekBarPreference.java
new file mode 100644
index 0000000..b86a15c
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/SeekBarPreference.java
@@ -0,0 +1,221 @@
+/*
+ ** Copyright 2013, The ChameleonOS Open Source Project
+ ** Copyright 2016, The OmniROM 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 omnirom.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.TypedValue;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import omnirom.preference.R;
+
+public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
+
+ private final String TAG = getClass().getName();
+
+ private static final String ANDROIDNS = "http://schemas.android.com/apk/res/android";
+ private static final int DEFAULT_VALUE = 50;
+
+ private int mMaxValue = 100;
+ private int mMinValue = 0;
+ private int mInterval = 1;
+ private int mCurrentValue;
+ private String mUnitsLeft = "";
+ private String mUnitsRight = "";
+ private SeekBar mSeekBar;
+ private TextView mStatusText;
+
+ public SeekBarPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initPreference(context, attrs);
+ }
+
+ public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initPreference(context, attrs);
+ }
+
+ private void initPreference(Context context, AttributeSet attrs) {
+ setValuesFromXml(context, attrs);
+ setLayoutResource(R.layout.preference_seek_bar);
+ }
+
+ private void setValuesFromXml(Context context, AttributeSet attrs) {
+ mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", 100);
+
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.SeekBarPreference);
+
+ TypedValue minAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_min);
+ if (minAttr != null && minAttr.type == TypedValue.TYPE_INT_DEC) {
+ mMinValue = minAttr.data;
+ }
+
+ TypedValue unitsLeftAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_unitsLeft);
+ CharSequence data = null;
+ if (unitsLeftAttr != null && unitsLeftAttr.type == TypedValue.TYPE_STRING) {
+ if (unitsLeftAttr.resourceId != 0) {
+ data = context.getText(unitsLeftAttr.resourceId);
+ } else {
+ data = unitsLeftAttr.string;
+ }
+ }
+ mUnitsLeft = (data == null) ? "" : data.toString();
+
+ TypedValue unitsRightAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_unitsRight);
+ data = null;
+ if (unitsRightAttr != null && unitsRightAttr.type == TypedValue.TYPE_STRING) {
+ if (unitsRightAttr.resourceId != 0) {
+ data = context.getText(unitsRightAttr.resourceId);
+ } else {
+ data = unitsRightAttr.string;
+ }
+ }
+ mUnitsRight = (data == null) ? "" : data.toString();
+
+ TypedValue intervalAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_interval);
+ if (intervalAttr != null && intervalAttr.type == TypedValue.TYPE_INT_DEC) {
+ mInterval = intervalAttr.data;
+ }
+
+ attributes.recycle();
+ }
+
+ @Override
+ public void onDependencyChanged(Preference dependency, boolean disableDependent) {
+ super.onDependencyChanged(dependency, disableDependent);
+ this.setShouldDisableView(true);
+ if (mSeekBar != null) {
+ mSeekBar.setEnabled(!disableDependent);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ mSeekBar = (SeekBar) holder.findViewById(R.id.seekbar);
+ mSeekBar.setMax(mMaxValue - mMinValue);
+ mSeekBar.setProgress(mCurrentValue - mMinValue);
+ mSeekBar.setOnSeekBarChangeListener(this);
+ mSeekBar.setEnabled(isEnabled());
+
+ mStatusText = (TextView) holder.findViewById(R.id.seekBarPrefValue);
+ mStatusText.setText(String.valueOf(mCurrentValue));
+ mStatusText.setMinimumWidth(30);
+
+ TextView unitsRight = (TextView) holder.findViewById(R.id.seekBarPrefUnitsRight);
+ unitsRight.setText(mUnitsRight);
+ TextView unitsLeft = (TextView) holder.findViewById(R.id.seekBarPrefUnitsLeft);
+ unitsLeft.setText(mUnitsLeft);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ int newValue = progress + mMinValue;
+
+ if (newValue > mMaxValue) {
+ newValue = mMaxValue;
+ } else if (newValue < mMinValue) {
+ newValue = mMinValue;
+ } else if (mInterval != 1 && newValue % mInterval != 0) {
+ newValue = Math.round(((float) newValue) / mInterval) * mInterval;
+ }
+
+ // change rejected, revert to the previous value
+ if (!callChangeListener(newValue)) {
+ seekBar.setProgress(mCurrentValue - mMinValue);
+ return;
+ }
+
+ // change accepted, store it
+ mCurrentValue = newValue;
+ mStatusText.setText(String.valueOf(newValue));
+ persistInt(newValue);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ notifyChanged();
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray ta, int index) {
+ int defaultValue = ta.getInt(index, DEFAULT_VALUE);
+ return defaultValue;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ if (restoreValue) {
+ mCurrentValue = getPersistedInt(mCurrentValue);
+ } else {
+ int temp = 0;
+ try {
+ temp = (Integer) defaultValue;
+ } catch (Exception ex) {
+ Log.e(TAG, "Invalid default value: " + defaultValue.toString());
+ }
+ persistInt(temp);
+ mCurrentValue = temp;
+ }
+ }
+
+ public void setValue(int value) {
+ mCurrentValue = value;
+ }
+
+ public void setMaxValue(int value) {
+ mMaxValue = value;
+ if (mSeekBar != null) {
+ mSeekBar.setMax(mMaxValue - mMinValue);
+ }
+ }
+
+ public void setMinValue(int value) {
+ mMinValue = value;
+ if (mSeekBar != null) {
+ mSeekBar.setMax(mMaxValue - mMinValue);
+ }
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (mSeekBar != null) {
+ mSeekBar.setEnabled(enabled);
+ }
+ super.setEnabled(enabled);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/SystemCheckBoxPreference.java b/omnipreference/java/omnirom/preference/SystemCheckBoxPreference.java
new file mode 100644
index 0000000..f6340e8
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/SystemCheckBoxPreference.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import androidx.preference.CheckBoxPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public class SystemCheckBoxPreference extends CheckBoxPreference {
+ public SystemCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public SystemCheckBoxPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SystemCheckBoxPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ Settings.System.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return Settings.System.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setChecked(Settings.System.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
+ : (Boolean) defaultValue);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/SystemSettingSwitchPreference.java b/omnipreference/java/omnirom/preference/SystemSettingSwitchPreference.java
new file mode 100644
index 0000000..647ce90
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/SystemSettingSwitchPreference.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod 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 omnirom.preference;
+
+import android.content.Context;
+import android.provider.Settings;
+import androidx.preference.SwitchPreference;
+import android.util.AttributeSet;
+
+public class SystemSettingSwitchPreference extends SwitchPreference {
+ public SystemSettingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public SystemSettingSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SystemSettingSwitchPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistBoolean(boolean value) {
+ if (shouldPersist()) {
+ if (value == getPersistedBoolean(!value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+ Settings.System.putInt(getContext().getContentResolver(), getKey(), value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected boolean getPersistedBoolean(boolean defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+ return Settings.System.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue ? 1 : 0) != 0;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ setChecked(Settings.System.getString(getContext().getContentResolver(), getKey()) != null ? getPersistedBoolean(isChecked())
+ : (Boolean) defaultValue);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/SystemSettingsColorSelectPreference.java b/omnipreference/java/omnirom/preference/SystemSettingsColorSelectPreference.java
new file mode 100644
index 0000000..2bffc66
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/SystemSettingsColorSelectPreference.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2021 The OmniROM 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 omnirom.preference;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.util.AttributeSet;
+
+public class SystemSettingsColorSelectPreference extends ColorSelectPreference {
+ private int mDefaultColor = ColorSelectPreference.DEFAULT_COLOR;
+
+ public SystemSettingsColorSelectPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public SystemSettingsColorSelectPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SystemSettingsColorSelectPreference(Context context) {
+ super(context, null);
+ }
+
+ @Override
+ protected boolean persistInt(int value) {
+ if (!shouldPersist()) {
+ return false;
+ }
+
+ if (value == getPersistedInt(~value)) {
+ // It's already there, so the same as persisting
+ return true;
+ }
+
+ Settings.System.putInt(getContext().getContentResolver(), getKey(), value);
+ return true;
+ }
+
+ @Override
+ protected int getPersistedInt(int defaultReturnValue) {
+ if (!shouldPersist()) {
+ return defaultReturnValue;
+ }
+
+ return Settings.System.getInt(getContext().getContentResolver(),
+ getKey(), defaultReturnValue);
+ }
+
+ public void updateColor() {
+ super.setColor(getPersistedInt(mColorValue));
+ }
+
+ @Override
+ public void setColor(int color) {
+ super.setColor(color);
+ persistInt(color);
+ }
+
+ @Override
+ public void setDefaultValue(Object defaultValue) {
+ mDefaultColor = (Integer) defaultValue;
+ super.setDefaultValue(defaultValue);
+ super.setColor(getPersistedInt((Integer) defaultValue));
+ }
+
+ public void resetToDefaultValue() {
+ setColor(mDefaultColor);
+ }
+}
diff --git a/omnipreference/java/omnirom/preference/WifiSelectListPreference.java b/omnipreference/java/omnirom/preference/WifiSelectListPreference.java
new file mode 100644
index 0000000..8feba20
--- /dev/null
+++ b/omnipreference/java/omnirom/preference/WifiSelectListPreference.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2016 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package omnirom.preference;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.net.wifi.WifiManager;
+import android.icu.text.Collator;
+
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiSavedConfigUtils;
+
+import omnirom.preference.R;
+import com.android.settingslib.CustomDialogPreferenceCompat;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Comparator;
+import java.util.Collections;
+
+public class WifiSelectListPreference extends CustomDialogPreferenceCompat {
+ private List<AccessPoint> mAPInfoList;
+ private ActionListAdapter mAdapter;
+ private List<String> mValues = new ArrayList<String>();
+ private WifiManager mWifiManager;
+ private static final Comparator<AccessPoint> SAVED_NETWORK_COMPARATOR =
+ new Comparator<AccessPoint>() {
+ final Collator mCollator = Collator.getInstance();
+
+ @Override
+ public int compare(AccessPoint ap1, AccessPoint ap2) {
+ return mCollator.compare(
+ nullToEmpty(ap1.getSsidStr()), nullToEmpty(ap2.getSsidStr()));
+ }
+
+ private String nullToEmpty(String string) {
+ return (string == null) ? "" : string;
+ }
+ };
+
+ public WifiSelectListPreference(Context context) {
+ this(context, null);
+ }
+
+ public WifiSelectListPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setDialogLayoutResource(R.layout.preference_wifi_ap_list);
+ mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ mAPInfoList = WifiSavedConfigUtils.getAllConfigs(context, mWifiManager);
+ Collections.sort(mAPInfoList, SAVED_NETWORK_COMPARATOR);
+
+ setPositiveButtonText(R.string.action_save);
+ setNegativeButtonText(android.R.string.cancel);
+ }
+
+ public void setValues(Collection<String> values) {
+ mValues.clear();
+ mValues.addAll(values);
+ }
+
+ public Collection<String> getValues() {
+ return mValues;
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mAdapter = new ActionListAdapter(getContext());
+ final ListView listView = (ListView) view.findViewById(R.id.wifi_ap_list);
+ listView.setAdapter(mAdapter);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final AppViewHolder holder = (AppViewHolder) view.getTag();
+ final boolean isChecked = !holder.checkBox.isChecked();
+
+ holder.checkBox.setChecked(isChecked);
+ AccessPoint info = mAdapter.getItem(position);
+
+ if (isChecked) {
+ mValues.add(info.getSsidStr());
+ } else {
+ mValues.remove(info.getSsidStr());
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ if (positiveResult) {
+ callChangeListener(mValues.size() > 0 ? mValues : null);
+ }
+ }
+
+ public class ActionListAdapter extends ArrayAdapter<AccessPoint> {
+ private final LayoutInflater mInflater;
+
+ public ActionListAdapter(Context context) {
+ super(context, 0);
+ mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ addAll(mAPInfoList);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ AppViewHolder holder = AppViewHolder.createOrRecycle(mInflater, convertView);
+ convertView = holder.rootView;
+ AccessPoint info = getItem(position);
+ holder.title.setText(info.getSsidStr());
+ holder.checkBox.setChecked(mValues.contains(info.getSsidStr()));
+ return convertView;
+ }
+
+ @Override
+ public AccessPoint getItem(int position) {
+ return mAPInfoList.get(position);
+ }
+ }
+
+ public static class AppViewHolder {
+ public View rootView;
+ public TextView title;
+ public CheckBox checkBox;
+
+ public static AppViewHolder createOrRecycle(LayoutInflater inflater, View convertView) {
+ if (convertView == null) {
+ convertView = inflater.inflate(R.layout.wifi_ap_item, null);
+
+ // Creates a ViewHolder and store references to the two children views
+ // we want to bind data to.
+ AppViewHolder holder = new AppViewHolder();
+ holder.rootView = convertView;
+ holder.title = (TextView) convertView.findViewById(R.id.ap_name);
+ holder.checkBox = (CheckBox) convertView.findViewById(android.R.id.checkbox);
+ convertView.setTag(holder);
+ return holder;
+ } else {
+ // Get the ViewHolder back to get fast access to the TextView
+ // and the ImageView.
+ return (AppViewHolder) convertView.getTag();
+ }
+ }
+ }
+}
+
diff --git a/omnipreference/java/omnirom/ui/AlphaPatternDrawable.java b/omnipreference/java/omnirom/ui/AlphaPatternDrawable.java
new file mode 100644
index 0000000..d91998d
--- /dev/null
+++ b/omnipreference/java/omnirom/ui/AlphaPatternDrawable.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ * Copyright (C) 2012 The CyanogenMod 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 omnirom.ui;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Bitmap.Config;
+import android.graphics.drawable.Drawable;
+
+/**
+ * This drawable that draws a simple white and gray chess board pattern. It's
+ * pattern you will often see as a background behind a partly transparent image
+ * in many applications.
+ *
+ * @author Daniel Nilsson
+ */
+public class AlphaPatternDrawable extends Drawable {
+
+ private int mRectangleSize = 10;
+
+ private Paint mPaint = new Paint();
+ private Paint mPaintWhite = new Paint();
+ private Paint mPaintGray = new Paint();
+
+ private int numRectanglesHorizontal;
+ private int numRectanglesVertical;
+
+ /**
+ * Bitmap in which the pattern will be cached.
+ */
+ private Bitmap mBitmap;
+
+ public AlphaPatternDrawable(int rectangleSize) {
+ mRectangleSize = rectangleSize;
+ mPaintWhite.setColor(0xffffffff);
+ mPaintGray.setColor(0xffcbcbcb);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ if (mBitmap != null) {
+ canvas.drawBitmap(mBitmap, null, getBounds(), mPaint);
+ }
+ }
+
+ @Override
+ public int getOpacity() {
+ return 0;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ throw new UnsupportedOperationException("Alpha is not supported by this drawwable.");
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ throw new UnsupportedOperationException("ColorFilter is not supported by this drawwable.");
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.onBoundsChange(bounds);
+
+ int height = bounds.height();
+ int width = bounds.width();
+
+ numRectanglesHorizontal = (int) Math.ceil((width / mRectangleSize));
+ numRectanglesVertical = (int) Math.ceil(height / mRectangleSize);
+
+ generatePatternBitmap();
+ }
+
+ /**
+ * This will generate a bitmap with the pattern as big as the rectangle we
+ * were allow to draw on. We do this to cache the bitmap so we don't need
+ * to recreate it each time draw() is called since it takes a few
+ * milliseconds.
+ */
+ private void generatePatternBitmap() {
+
+ if (getBounds().width() <= 0 || getBounds().height() <= 0) {
+ return;
+ }
+
+ mBitmap = Bitmap.createBitmap(getBounds().width(), getBounds().height(), Config.ARGB_8888);
+ Canvas canvas = new Canvas(mBitmap);
+
+ Rect r = new Rect();
+ boolean verticalStartWhite = true;
+ for (int i = 0; i <= numRectanglesVertical; i++) {
+ boolean isWhite = verticalStartWhite;
+ for (int j = 0; j <= numRectanglesHorizontal; j++) {
+ r.top = i * mRectangleSize;
+ r.left = j * mRectangleSize;
+ r.bottom = r.top + mRectangleSize;
+ r.right = r.left + mRectangleSize;
+
+ canvas.drawRect(r, isWhite ? mPaintWhite : mPaintGray);
+
+ isWhite = !isWhite;
+ }
+
+ verticalStartWhite = !verticalStartWhite;
+ }
+ }
+}
diff --git a/omnipreference/java/omnirom/ui/ColorPanelView.java b/omnipreference/java/omnirom/ui/ColorPanelView.java
new file mode 100644
index 0000000..e50ce86
--- /dev/null
+++ b/omnipreference/java/omnirom/ui/ColorPanelView.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ * Copyright (C) 2012 The CyanogenMod 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 omnirom.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * This class draws a panel which which will be filled with a color which can be
+ * set. It can be used to show the currently selected color which you will get
+ * from the {@link ColorPickerView}.
+ *
+ * @author Daniel Nilsson
+ */
+public class ColorPanelView extends View {
+
+ /**
+ * The width in pixels of the border surrounding the color panel.
+ */
+ private final static float BORDER_WIDTH_PX = 1;
+
+ private static float mDensity = 1f;
+
+ private int mBorderColor = 0xff6E6E6E;
+ private int mColor = 0xff000000;
+
+ private Paint mBorderPaint;
+ private Paint mColorPaint;
+
+ private RectF mDrawingRect;
+ private RectF mColorRect;
+
+ private AlphaPatternDrawable mAlphaPattern;
+
+ public ColorPanelView(Context context) {
+ this(context, null);
+ }
+
+ public ColorPanelView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ColorPanelView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ init();
+ }
+
+ private void init() {
+ mBorderPaint = new Paint();
+ mColorPaint = new Paint();
+ mDensity = getContext().getResources().getDisplayMetrics().density;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ final RectF rect = mColorRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(mDrawingRect, mBorderPaint);
+ }
+
+ if (mAlphaPattern != null) {
+ mAlphaPattern.draw(canvas);
+ }
+
+ mColorPaint.setColor(mColor);
+
+ canvas.drawRect(rect, mColorPaint);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mDrawingRect = new RectF();
+ mDrawingRect.left = getPaddingLeft();
+ mDrawingRect.right = w - getPaddingRight();
+ mDrawingRect.top = getPaddingTop();
+ mDrawingRect.bottom = h - getPaddingBottom();
+
+ setUpColorRect();
+
+ }
+
+ private void setUpColorRect() {
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX;
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mColorRect = new RectF(left, top, right, bottom);
+
+ mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
+
+ mAlphaPattern.setBounds(Math.round(mColorRect.left),
+ Math.round(mColorRect.top),
+ Math.round(mColorRect.right),
+ Math.round(mColorRect.bottom));
+
+ }
+
+ /**
+ * Set the color that should be shown by this view.
+ *
+ * @param color
+ */
+ public void setColor(int color) {
+ mColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color currently show by this view.
+ *
+ * @return
+ */
+ public int getColor() {
+ return mColor;
+ }
+
+ /**
+ * Set the color of the border surrounding the panel.
+ *
+ * @param color
+ */
+ public void setBorderColor(int color) {
+ mBorderColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color of the border surrounding the panel.
+ */
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+}
diff --git a/omnipreference/java/omnirom/ui/ColorPickerView.java b/omnipreference/java/omnirom/ui/ColorPickerView.java
new file mode 100644
index 0000000..e703181
--- /dev/null
+++ b/omnipreference/java/omnirom/ui/ColorPickerView.java
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 2010 Daniel Nilsson
+ * Copyright (C) 2012 The CyanogenMod 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 omnirom.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ComposeShader;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.RectF;
+import android.graphics.Shader;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Shader.TileMode;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+/**
+ * Displays a color picker to the user and allow them to select a color. A
+ * slider for the alpha channel is also available. Enable it by setting
+ * setAlphaSliderVisible(boolean) to true.
+ *
+ * @author Daniel Nilsson
+ */
+public class ColorPickerView extends View {
+
+ public interface OnColorChangedListener {
+ public void onColorChanged(int color);
+ }
+
+ private final static int PANEL_SAT_VAL = 0;
+ private final static int PANEL_HUE = 1;
+ private final static int PANEL_ALPHA = 2;
+
+ /**
+ * The width in pixels of the border surrounding all color panels.
+ */
+ private final static float BORDER_WIDTH_PX = 1;
+
+ /**
+ * The width in dp of the hue panel.
+ */
+ private float HUE_PANEL_WIDTH = 30f;
+ /**
+ * The height in dp of the alpha panel
+ */
+ private float ALPHA_PANEL_HEIGHT = 20f;
+ /**
+ * The distance in dp between the different color panels.
+ */
+ private float PANEL_SPACING = 10f;
+ /**
+ * The radius in dp of the color palette tracker circle.
+ */
+ private float PALETTE_CIRCLE_TRACKER_RADIUS = 5f;
+ /**
+ * The dp which the tracker of the hue or alpha panel will extend outside of
+ * its bounds.
+ */
+ private float RECTANGLE_TRACKER_OFFSET = 2f;
+
+ private static float mDensity = 1f;
+
+ private OnColorChangedListener mListener;
+
+ private Paint mSatValPaint;
+ private Paint mSatValTrackerPaint;
+
+ private Paint mHuePaint;
+ private Paint mHueTrackerPaint;
+
+ private Paint mAlphaPaint;
+ private Paint mAlphaTextPaint;
+
+ private Paint mBorderPaint;
+
+ private Shader mValShader;
+ private Shader mSatShader;
+ private Shader mHueShader;
+ private Shader mAlphaShader;
+
+ private int mAlpha = 0xff;
+ private float mHue = 360f;
+ private float mSat = 0f;
+ private float mVal = 0f;
+
+ private String mAlphaSliderText = "Alpha";
+ private int mSliderTrackerColor = 0xff1c1c1c;
+ private int mBorderColor = 0xff6E6E6E;
+ private boolean mShowAlphaPanel = false;
+
+ /*
+ * To remember which panel that has the "focus" when processing hardware
+ * button data.
+ */
+ private int mLastTouchedPanel = PANEL_SAT_VAL;
+
+ /**
+ * Offset from the edge we must have or else the finger tracker will get
+ * clipped when it is drawn outside of the view.
+ */
+ private float mDrawingOffset;
+
+ /*
+ * Distance form the edges of the view of where we are allowed to draw.
+ */
+ private RectF mDrawingRect;
+
+ private RectF mSatValRect;
+ private RectF mHueRect;
+ private RectF mAlphaRect;
+
+ private AlphaPatternDrawable mAlphaPattern;
+
+ private Point mStartTouchPoint = null;
+
+ public ColorPickerView(Context context) {
+ this(context, null);
+ }
+
+ public ColorPickerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ColorPickerView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ mDensity = getContext().getResources().getDisplayMetrics().density;
+ PALETTE_CIRCLE_TRACKER_RADIUS *= mDensity;
+ RECTANGLE_TRACKER_OFFSET *= mDensity;
+ HUE_PANEL_WIDTH *= mDensity;
+ ALPHA_PANEL_HEIGHT *= mDensity;
+ PANEL_SPACING = PANEL_SPACING * mDensity;
+
+ mDrawingOffset = calculateRequiredOffset();
+ initPaintTools();
+
+ // Needed for receiving track ball motion events.
+ setFocusableInTouchMode(true);
+ setFocusable(true);
+ setClickable(true);
+ }
+
+ private void initPaintTools() {
+ mSatValPaint = new Paint();
+ mSatValTrackerPaint = new Paint();
+ mHuePaint = new Paint();
+ mHueTrackerPaint = new Paint();
+ mAlphaPaint = new Paint();
+ mAlphaTextPaint = new Paint();
+ mBorderPaint = new Paint();
+
+ mSatValTrackerPaint.setStyle(Style.STROKE);
+ mSatValTrackerPaint.setStrokeWidth(2f * mDensity);
+ mSatValTrackerPaint.setAntiAlias(true);
+
+ mHueTrackerPaint.setColor(mSliderTrackerColor);
+ mHueTrackerPaint.setStyle(Style.STROKE);
+ mHueTrackerPaint.setStrokeWidth(2f * mDensity);
+ mHueTrackerPaint.setAntiAlias(true);
+
+ mAlphaTextPaint.setColor(0xff1c1c1c);
+ mAlphaTextPaint.setTextSize(14f * mDensity);
+ mAlphaTextPaint.setAntiAlias(true);
+ mAlphaTextPaint.setTextAlign(Align.CENTER);
+ mAlphaTextPaint.setFakeBoldText(true);
+ }
+
+ private float calculateRequiredOffset() {
+ float offset = Math.max(PALETTE_CIRCLE_TRACKER_RADIUS, RECTANGLE_TRACKER_OFFSET);
+ offset = Math.max(offset, BORDER_WIDTH_PX * mDensity);
+
+ return offset * 1.5f;
+ }
+
+ private int[] buildHueColorArray() {
+ int[] hue = new int[361];
+
+ int count = 0;
+ for (int i = hue.length - 1; i >= 0; i--, count++) {
+ hue[count] = Color.HSVToColor(new float[] {
+ i, 1f, 1f
+ });
+ }
+ return hue;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) {
+ return;
+ }
+ drawSatValPanel(canvas);
+ drawHuePanel(canvas);
+ drawAlphaPanel(canvas);
+ }
+
+ private void drawSatValPanel(Canvas canvas) {
+ final RectF rect = mSatValRect;
+ int rgb = Color.HSVToColor(new float[] {
+ mHue, 1f, 1f
+ });
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(mDrawingRect.left, mDrawingRect.top, rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX, mBorderPaint);
+ }
+
+ // On Honeycomb+ we need to use software rendering to create the shader properly
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+
+ // Get the overlaying gradients ready and create the ComposeShader
+ if (mValShader == null) {
+ mValShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
+ 0xffffffff, 0xff000000, TileMode.CLAMP);
+ }
+ mSatShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ 0xffffffff, rgb, TileMode.CLAMP);
+ ComposeShader mShader = new ComposeShader(mValShader, mSatShader, Mode.MULTIPLY);
+ mSatValPaint.setShader(mShader);
+ canvas.drawRect(rect, mSatValPaint);
+
+ Point p = satValToPoint(mSat, mVal);
+ mSatValTrackerPaint.setColor(0xff000000);
+ canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS - 1f * mDensity,
+ mSatValTrackerPaint);
+
+ mSatValTrackerPaint.setColor(0xffdddddd);
+ canvas.drawCircle(p.x, p.y, PALETTE_CIRCLE_TRACKER_RADIUS, mSatValTrackerPaint);
+ }
+
+ private void drawHuePanel(Canvas canvas) {
+ final RectF rect = mHueRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(rect.left - BORDER_WIDTH_PX,
+ rect.top - BORDER_WIDTH_PX,
+ rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX,
+ mBorderPaint);
+ }
+
+ if (mHueShader == null) {
+ mHueShader = new LinearGradient(rect.left, rect.top, rect.left, rect.bottom,
+ buildHueColorArray(), null, TileMode.CLAMP);
+ mHuePaint.setShader(mHueShader);
+ }
+
+ canvas.drawRect(rect, mHuePaint);
+
+ float rectHeight = 4 * mDensity / 2;
+
+ Point p = hueToPoint(mHue);
+
+ RectF r = new RectF();
+ r.left = rect.left - RECTANGLE_TRACKER_OFFSET;
+ r.right = rect.right + RECTANGLE_TRACKER_OFFSET;
+ r.top = p.y - rectHeight;
+ r.bottom = p.y + rectHeight;
+
+ canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
+
+ }
+
+ private void drawAlphaPanel(Canvas canvas) {
+ if (!mShowAlphaPanel || mAlphaRect == null || mAlphaPattern == null) {
+ return;
+ }
+
+ final RectF rect = mAlphaRect;
+
+ if (BORDER_WIDTH_PX > 0) {
+ mBorderPaint.setColor(mBorderColor);
+ canvas.drawRect(rect.left - BORDER_WIDTH_PX,
+ rect.top - BORDER_WIDTH_PX,
+ rect.right + BORDER_WIDTH_PX,
+ rect.bottom + BORDER_WIDTH_PX,
+ mBorderPaint);
+ }
+
+ mAlphaPattern.draw(canvas);
+
+ float[] hsv = new float[] {
+ mHue, mSat, mVal
+ };
+ int color = Color.HSVToColor(hsv);
+ int acolor = Color.HSVToColor(0, hsv);
+
+ mAlphaShader = new LinearGradient(rect.left, rect.top, rect.right, rect.top,
+ color, acolor, TileMode.CLAMP);
+
+ mAlphaPaint.setShader(mAlphaShader);
+
+ canvas.drawRect(rect, mAlphaPaint);
+
+ if (mAlphaSliderText != null && mAlphaSliderText != "") {
+ canvas.drawText(mAlphaSliderText, rect.centerX(), rect.centerY() + 4 * mDensity,
+ mAlphaTextPaint);
+ }
+
+ float rectWidth = 4 * mDensity / 2;
+ Point p = alphaToPoint(mAlpha);
+
+ RectF r = new RectF();
+ r.left = p.x - rectWidth;
+ r.right = p.x + rectWidth;
+ r.top = rect.top - RECTANGLE_TRACKER_OFFSET;
+ r.bottom = rect.bottom + RECTANGLE_TRACKER_OFFSET;
+
+ canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);
+ }
+
+ private Point hueToPoint(float hue) {
+ final RectF rect = mHueRect;
+ final float height = rect.height();
+
+ Point p = new Point();
+ p.y = (int) (height - (hue * height / 360f) + rect.top);
+ p.x = (int) rect.left;
+ return p;
+ }
+
+ private Point satValToPoint(float sat, float val) {
+
+ final RectF rect = mSatValRect;
+ final float height = rect.height();
+ final float width = rect.width();
+
+ Point p = new Point();
+
+ p.x = (int) (sat * width + rect.left);
+ p.y = (int) ((1f - val) * height + rect.top);
+
+ return p;
+ }
+
+ private Point alphaToPoint(int alpha) {
+ final RectF rect = mAlphaRect;
+ final float width = rect.width();
+
+ Point p = new Point();
+ p.x = (int) (width - (alpha * width / 0xff) + rect.left);
+ p.y = (int) rect.top;
+ return p;
+ }
+
+ private float[] pointToSatVal(float x, float y) {
+ final RectF rect = mSatValRect;
+ float[] result = new float[2];
+ float width = rect.width();
+ float height = rect.height();
+
+ if (x < rect.left) {
+ x = 0f;
+ } else if (x > rect.right) {
+ x = width;
+ } else {
+ x = x - rect.left;
+ }
+
+ if (y < rect.top) {
+ y = 0f;
+ } else if (y > rect.bottom) {
+ y = height;
+ } else {
+ y = y - rect.top;
+ }
+
+ result[0] = 1.f / width * x;
+ result[1] = 1.f - (1.f / height * y);
+ return result;
+ }
+
+ private float pointToHue(float y) {
+ final RectF rect = mHueRect;
+ float height = rect.height();
+
+ if (y < rect.top) {
+ y = 0f;
+ } else if (y > rect.bottom) {
+ y = height;
+ } else {
+ y = y - rect.top;
+ }
+ return 360f - (y * 360f / height);
+ }
+
+ private int pointToAlpha(int x) {
+ final RectF rect = mAlphaRect;
+ final int width = (int) rect.width();
+
+ if (x < rect.left) {
+ x = 0;
+ } else if (x > rect.right) {
+ x = width;
+ } else {
+ x = x - (int) rect.left;
+ }
+ return 0xff - (x * 0xff / width);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ float x = event.getX();
+ float y = event.getY();
+ boolean update = false;
+
+ if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ switch (mLastTouchedPanel) {
+ case PANEL_SAT_VAL:
+ float sat,
+ val;
+ sat = mSat + x / 50f;
+ val = mVal - y / 50f;
+ if (sat < 0f) {
+ sat = 0f;
+ } else if (sat > 1f) {
+ sat = 1f;
+ }
+
+ if (val < 0f) {
+ val = 0f;
+ } else if (val > 1f) {
+ val = 1f;
+ }
+ mSat = sat;
+ mVal = val;
+ update = true;
+ break;
+ case PANEL_HUE:
+ float hue = mHue - y * 10f;
+ if (hue < 0f) {
+ hue = 0f;
+ } else if (hue > 360f) {
+ hue = 360f;
+ }
+ mHue = hue;
+ update = true;
+ break;
+ case PANEL_ALPHA:
+ if (!mShowAlphaPanel || mAlphaRect == null) {
+ update = false;
+ } else {
+ int alpha = (int) (mAlpha - x * 10);
+ if (alpha < 0) {
+ alpha = 0;
+ } else if (alpha > 0xff) {
+ alpha = 0xff;
+ }
+ mAlpha = alpha;
+ update = true;
+ }
+ break;
+ }
+ }
+
+ if (update) {
+ if (mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
+ mHue, mSat, mVal
+ }));
+ }
+ invalidate();
+ return true;
+ }
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean update = false;
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mStartTouchPoint = new Point((int) event.getX(), (int) event.getY());
+ update = moveTrackersIfNeeded(event);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ update = moveTrackersIfNeeded(event);
+ break;
+ case MotionEvent.ACTION_UP:
+ mStartTouchPoint = null;
+ update = moveTrackersIfNeeded(event);
+ break;
+ }
+
+ if (update) {
+ requestFocus();
+ if (mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
+ mHue, mSat, mVal
+ }));
+ }
+ invalidate();
+ return true;
+ }
+
+ return super.onTouchEvent(event);
+ }
+
+ private boolean moveTrackersIfNeeded(MotionEvent event) {
+
+ if (mStartTouchPoint == null)
+ return false;
+
+ boolean update = false;
+ int startX = mStartTouchPoint.x;
+ int startY = mStartTouchPoint.y;
+
+ if (mHueRect.contains(startX, startY)) {
+ mLastTouchedPanel = PANEL_HUE;
+ mHue = pointToHue(event.getY());
+ update = true;
+ } else if (mSatValRect.contains(startX, startY)) {
+ mLastTouchedPanel = PANEL_SAT_VAL;
+ float[] result = pointToSatVal(event.getX(), event.getY());
+ mSat = result[0];
+ mVal = result[1];
+ update = true;
+ } else if (mAlphaRect != null && mAlphaRect.contains(startX, startY)) {
+ mLastTouchedPanel = PANEL_ALPHA;
+ mAlpha = pointToAlpha((int) event.getX());
+ update = true;
+ }
+
+ return update;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = 0;
+ int height = 0;
+
+ int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+
+ int widthAllowed = MeasureSpec.getSize(widthMeasureSpec);
+ int heightAllowed = MeasureSpec.getSize(heightMeasureSpec);
+
+ widthAllowed = chooseWidth(widthMode, widthAllowed);
+ heightAllowed = chooseHeight(heightMode, heightAllowed);
+
+ if (!mShowAlphaPanel) {
+ height = (int) (widthAllowed - PANEL_SPACING - HUE_PANEL_WIDTH);
+
+ // If calculated height (based on the width) is more than the
+ // allowed height.
+ if (height > heightAllowed && heightMode != MeasureSpec.UNSPECIFIED) {
+ height = heightAllowed;
+ width = (int) (height + PANEL_SPACING + HUE_PANEL_WIDTH);
+ } else {
+ width = widthAllowed;
+ }
+ } else {
+
+ width = (int) (heightAllowed - ALPHA_PANEL_HEIGHT + HUE_PANEL_WIDTH);
+
+ if (width > widthAllowed && widthMode != MeasureSpec.UNSPECIFIED) {
+ width = widthAllowed;
+ height = (int) (widthAllowed - HUE_PANEL_WIDTH + ALPHA_PANEL_HEIGHT);
+ } else {
+ height = heightAllowed;
+ }
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ private int chooseWidth(int mode, int size) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
+ return size;
+ } else { // (mode == MeasureSpec.UNSPECIFIED)
+ return getPrefferedWidth();
+ }
+ }
+
+ private int chooseHeight(int mode, int size) {
+ if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
+ return size;
+ } else { // (mode == MeasureSpec.UNSPECIFIED)
+ return getPrefferedHeight();
+ }
+ }
+
+ private int getPrefferedWidth() {
+ int width = getPrefferedHeight();
+ if (mShowAlphaPanel) {
+ width -= (PANEL_SPACING + ALPHA_PANEL_HEIGHT);
+ }
+ return (int) (width + HUE_PANEL_WIDTH + PANEL_SPACING);
+ }
+
+ private int getPrefferedHeight() {
+ int height = (int) (200 * mDensity);
+ if (mShowAlphaPanel) {
+ height += PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ }
+ return height;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mDrawingRect = new RectF();
+ mDrawingRect.left = mDrawingOffset + getPaddingLeft();
+ mDrawingRect.right = w - mDrawingOffset - getPaddingRight();
+ mDrawingRect.top = mDrawingOffset + getPaddingTop();
+ mDrawingRect.bottom = h - mDrawingOffset - getPaddingBottom();
+
+ setUpSatValRect();
+ setUpHueRect();
+ setUpAlphaRect();
+ }
+
+ private void setUpSatValRect() {
+ final RectF dRect = mDrawingRect;
+ float panelSide = dRect.height() - BORDER_WIDTH_PX * 2;
+
+ if (mShowAlphaPanel) {
+ panelSide -= PANEL_SPACING + ALPHA_PANEL_HEIGHT;
+ }
+
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = top + panelSide;
+ float right = left + panelSide;
+ mSatValRect = new RectF(left, top, right, bottom);
+ }
+
+ private void setUpHueRect() {
+ final RectF dRect = mDrawingRect;
+
+ float left = dRect.right - HUE_PANEL_WIDTH + BORDER_WIDTH_PX;
+ float top = dRect.top + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX
+ - (mShowAlphaPanel ? (PANEL_SPACING + ALPHA_PANEL_HEIGHT) : 0);
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mHueRect = new RectF(left, top, right, bottom);
+ }
+
+ private void setUpAlphaRect() {
+ if (!mShowAlphaPanel) {
+ return;
+ }
+
+ final RectF dRect = mDrawingRect;
+ float left = dRect.left + BORDER_WIDTH_PX;
+ float top = dRect.bottom - ALPHA_PANEL_HEIGHT + BORDER_WIDTH_PX;
+ float bottom = dRect.bottom - BORDER_WIDTH_PX;
+ float right = dRect.right - BORDER_WIDTH_PX;
+
+ mAlphaRect = new RectF(left, top, right, bottom);
+ mAlphaPattern = new AlphaPatternDrawable((int) (5 * mDensity));
+ mAlphaPattern.setBounds(Math.round(mAlphaRect.left), Math
+ .round(mAlphaRect.top), Math.round(mAlphaRect.right), Math
+ .round(mAlphaRect.bottom));
+ }
+
+ /**
+ * Set a OnColorChangedListener to get notified when the color selected by
+ * the user has changed.
+ *
+ * @param listener
+ */
+ public void setOnColorChangedListener(OnColorChangedListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Set the color of the border surrounding all panels.
+ *
+ * @param color
+ */
+ public void setBorderColor(int color) {
+ mBorderColor = color;
+ invalidate();
+ }
+
+ /**
+ * Get the color of the border surrounding all panels.
+ */
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+ /**
+ * Get the current color this view is showing.
+ *
+ * @return the current color.
+ */
+ public int getColor() {
+ return Color.HSVToColor(mAlpha, new float[] {
+ mHue, mSat, mVal
+ });
+ }
+
+ /**
+ * Set the color the view should show.
+ *
+ * @param color The color that should be selected.
+ */
+ public void setColor(int color) {
+ setColor(color, false);
+ }
+
+ /**
+ * Set the color this view should show.
+ *
+ * @param color The color that should be selected.
+ * @param callback If you want to get a callback to your
+ * OnColorChangedListener.
+ */
+ public void setColor(int color, boolean callback) {
+ int alpha = Color.alpha(color);
+ int red = Color.red(color);
+ int blue = Color.blue(color);
+ int green = Color.green(color);
+ float[] hsv = new float[3];
+
+ Color.RGBToHSV(red, green, blue, hsv);
+ mAlpha = alpha;
+ mHue = hsv[0];
+ mSat = hsv[1];
+ mVal = hsv[2];
+
+ if (callback && mListener != null) {
+ mListener.onColorChanged(Color.HSVToColor(mAlpha, new float[] {
+ mHue, mSat, mVal
+ }));
+ }
+ invalidate();
+ }
+
+ /**
+ * Get the drawing offset of the color picker view. The drawing offset is
+ * the distance from the side of a panel to the side of the view minus the
+ * padding. Useful if you want to have your own panel below showing the
+ * currently selected color and want to align it perfectly.
+ *
+ * @return The offset in pixels.
+ */
+ public float getDrawingOffset() {
+ return mDrawingOffset;
+ }
+
+ /**
+ * Set if the user is allowed to adjust the alpha panel. Default is false.
+ * If it is set to false no alpha will be set.
+ *
+ * @param visible
+ */
+ public void setAlphaSliderVisible(boolean visible) {
+ if (mShowAlphaPanel != visible) {
+ mShowAlphaPanel = visible;
+
+ /*
+ * Reset all shader to force a recreation. Otherwise they will not
+ * look right after the size of the view has changed.
+ */
+ mValShader = null;
+ mSatShader = null;
+ mHueShader = null;
+ mAlphaShader = null;
+ requestLayout();
+ }
+
+ }
+
+ public boolean isAlphaSliderVisible() {
+ return mShowAlphaPanel;
+ }
+
+ public void setSliderTrackerColor(int color) {
+ mSliderTrackerColor = color;
+ mHueTrackerPaint.setColor(mSliderTrackerColor);
+ invalidate();
+ }
+
+ public int getSliderTrackerColor() {
+ return mSliderTrackerColor;
+ }
+
+ /**
+ * Set the text that should be shown in the alpha slider. Set to null to
+ * disable text.
+ *
+ * @param res string resource id.
+ */
+ public void setAlphaSliderText(int res) {
+ String text = getContext().getString(res);
+ setAlphaSliderText(text);
+ }
+
+ /**
+ * Set the text that should be shown in the alpha slider. Set to null to
+ * disable text.
+ *
+ * @param text Text that should be shown.
+ */
+ public void setAlphaSliderText(String text) {
+ mAlphaSliderText = text;
+ invalidate();
+ }
+
+ /**
+ * Get the current value of the text that will be shown in the alpha slider.
+ *
+ * @return
+ */
+ public String getAlphaSliderText() {
+ return mAlphaSliderText;
+ }
+}
diff --git a/omnipreference/java/omnirom/widget/SecureSettingsSwitch.java b/omnipreference/java/omnirom/widget/SecureSettingsSwitch.java
new file mode 100644
index 0000000..02cfda7
--- /dev/null
+++ b/omnipreference/java/omnirom/widget/SecureSettingsSwitch.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The OmniROM 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 omnirom.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Switch;
+
+import omnirom.preference.R;
+
+public class SecureSettingsSwitch extends Switch {
+
+ private boolean mInflated = false;
+ private int mInitialValue = 0;
+
+ public SecureSettingsSwitch(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ setInitialValue(context, attrs);
+ }
+
+ public SecureSettingsSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setInitialValue(context, attrs);
+ }
+
+ public SecureSettingsSwitch(Context context) {
+ super(context, null);
+ }
+
+ private void setInitialValue(Context context, AttributeSet attrs) {
+ if (attrs == null) return;
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.SecureSettingsSwitch, 0, 0);
+ mInitialValue =
+ attributes.getInteger(R.styleable.SecureSettingsSwitch_initialValue, 0);
+ attributes.recycle();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mInflated = true;
+ switch (mInitialValue) {
+ case 0:
+ setChecked(Settings.Secure.getIntForUser(getContext().getContentResolver(),
+ getResources().getResourceEntryName(getId()), 0, UserHandle.USER_CURRENT) != 0);
+ break;
+ case 1:
+ setChecked(Settings.Secure.getIntForUser(getContext().getContentResolver(),
+ getResources().getResourceEntryName(getId()), 1, UserHandle.USER_CURRENT) == 1);
+ }
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ if (!mInflated) return;
+ Settings.Secure.putIntForUser(getContext().getContentResolver(),
+ getResources().getResourceEntryName(getId()), checked ? 1 : 0, UserHandle.USER_CURRENT);
+ super.setChecked(checked);
+ }
+}
diff --git a/omnipreference/java/omnirom/widget/SystemSettingsSwitch.java b/omnipreference/java/omnirom/widget/SystemSettingsSwitch.java
new file mode 100644
index 0000000..74fa2fa
--- /dev/null
+++ b/omnipreference/java/omnirom/widget/SystemSettingsSwitch.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The OmniROM 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 omnirom.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.Switch;
+
+import omnirom.preference.R;
+
+public class SystemSettingsSwitch extends Switch {
+
+ private boolean mInflated = false;
+ private int mInitialValue = 0;
+
+ public SystemSettingsSwitch(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ setInitialValue(context, attrs);
+ }
+
+ public SystemSettingsSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setInitialValue(context, attrs);
+ }
+
+ public SystemSettingsSwitch(Context context) {
+ super(context, null);
+ }
+
+ private void setInitialValue(Context context, AttributeSet attrs) {
+ if (attrs == null) return;
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.SystemSettingsSwitch, 0, 0);
+ mInitialValue =
+ attributes.getInteger(R.styleable.SystemSettingsSwitch_initialValue, 0);
+ attributes.recycle();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mInflated = true;
+ switch (mInitialValue) {
+ case 0:
+ setChecked(Settings.System.getIntForUser(getContext().getContentResolver(),
+ getResources().getResourceEntryName(getId()), 0, UserHandle.USER_CURRENT) != 0);
+ break;
+ case 1:
+ setChecked(Settings.System.getIntForUser(getContext().getContentResolver(),
+ getResources().getResourceEntryName(getId()), 1, UserHandle.USER_CURRENT) == 1);
+ }
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ if (!mInflated) return;
+ Settings.System.putIntForUser(getContext().getContentResolver(),
+ getResources().getResourceEntryName(getId()), checked ? 1 : 0, UserHandle.USER_CURRENT);
+ super.setChecked(checked);
+ }
+}