[2/2] OmniGears: lock screen config
configure time and date display on lock screen
-select what to show time/date/alarm/nothing
-configure color/font/shadow
-add shortcut hide
-show statusbar time if lock screen time is hidden
add FontPreference and NumberPickerPreference
to pick a font - value stored is the path to the ttf file use
Typeface.createFromFile(file) to apply to a text
And while we are here fix the shadow slider settings
Change-Id: I4d5b99159a15fabf550c0e74b18680abe568ac04
diff --git a/res/layout/preference_font_picker.xml b/res/layout/preference_font_picker.xml
new file mode 100644
index 0000000..d41365f
--- /dev/null
+++ b/res/layout/preference_font_picker.xml
@@ -0,0 +1,48 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:background="?android:attr/selectableItemBackground" >
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp">
+
+ <TextView android:id="@+android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+ <TextView android:id="@+android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/title"
+ android:layout_alignStart="@android:id/title"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="1" />
+ </RelativeLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp">
+
+ <TextView android:id="@+id/font_sample"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:layout_gravity="center"
+ android:text="@string/font_sample_text" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/preference_number_picker.xml b/res/layout/preference_number_picker.xml
new file mode 100644
index 0000000..f53e62b
--- /dev/null
+++ b/res/layout/preference_number_picker.xml
@@ -0,0 +1,14 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingStart="@dimen/alert_dialog_padding_material"
+ android:paddingEnd="@dimen/alert_dialog_padding_material" >
+ <NumberPicker
+ android:id="@+id/number_picker"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="6dip"
+ android:layout_marginTop="6dip" />
+</LinearLayout>
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
index 6e9a6c1..0cbbb6e 100644
--- a/res/values/custom_strings.xml
+++ b/res/values/custom_strings.xml
@@ -208,10 +208,20 @@
<string name="lockscreen_wallpaper_clear_title">Clear lock screen wallpaper</string>
<string name="reset_lockscreen_wallpaper">Set to default</string>
- <!-- Lock screen shortcut -->
+ <!-- Lock screen config -->
<string name="lockscreen_shortcut_title">Shortcuts</string>
<string name="lockscreen_voice_shortcut_title">Voice assist shortcut</string>
<string name="lockscreen_voice_shortcut_summary">Show voice assist instead of dialer shortcut</string>
+ <string name="lockscreen_shortcuts_enable_title">Enable</string>
+ <string name="lockscreen_clock_display_time_title">Display time</string>
+ <string name="lockscreen_clock_display_date_title">Display date</string>
+ <string name="lockscreen_clock_display_alarm_title">Display next alarm</string>
+ <string name="lockscreen_clock">Clock</string>
+ <string name="lockscreen_clock_font_title">Time font</string>
+ <string name="lockscreen_clock_color_title">Time and date color</string>
+ <string name="lockscreen_clock_size_title">Time size</string>
+ <string name="lockscreen_clock_enable_title">Enable</string>
+ <string name="lockscreen_clock_shadow_title">Shadow</string>
<string name="notification_title">Notification panel</string>
<string name="status_bar_custom_header_title">Custom header image</string>
@@ -299,4 +309,6 @@
<string name="global_actions_title">Power menu</string>
<string name="global_actions_summary">Actions shown in power menu</string>
<string name="global_actions_header">Some actions are only visible depending on the setup or only if the device is unlocked</string>
+
+ <string name="font_sample_text">11:57</string>
</resources>
diff --git a/res/xml/lockscreen_settings.xml b/res/xml/lockscreen_settings.xml
index 8b1e50a..f639958 100644
--- a/res/xml/lockscreen_settings.xml
+++ b/res/xml/lockscreen_settings.xml
@@ -21,11 +21,17 @@
android:key="lockscreen_shortcut"
android:title="@string/lockscreen_shortcut_title" >
+ <com.android.settings.preference.SecureSettingSwitchPreference
+ android:key="lockscreen_shortcuts_enable"
+ android:title="@string/lockscreen_shortcuts_enable_title"
+ android:defaultValue="true"/>
+
<com.android.settings.preference.SecureCheckBoxPreference
android:key="lockscreen_voice_shortcut"
android:title="@string/lockscreen_voice_shortcut_title"
android:summary="@string/lockscreen_voice_shortcut_summary"
- android:defaultValue="true"/>
+ android:defaultValue="true"
+ android:dependency="lockscreen_shortcuts_enable" />
</PreferenceCategory>
@@ -44,4 +50,60 @@
android:persistent="false"/>
</PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="lockscreen_clock"
+ android:title="@string/lockscreen_clock" >
+
+ <com.android.settings.preference.SystemSettingSwitchPreference
+ android:key="lockscreen_clock_enable"
+ android:title="@string/lockscreen_clock_enable_title"
+ android:defaultValue="true" />
+
+ <CheckBoxPreference
+ android:key="lockscreen_clock_display_time"
+ android:title="@string/lockscreen_clock_display_time_title"
+ android:persistent="false"
+ android:defaultValue="true"
+ android:dependency="lockscreen_clock_enable" />
+
+ <CheckBoxPreference
+ android:key="lockscreen_clock_display_date"
+ android:title="@string/lockscreen_clock_display_date_title"
+ android:persistent="false"
+ android:defaultValue="true"
+ android:dependency="lockscreen_clock_enable" />
+
+ <CheckBoxPreference
+ android:key="lockscreen_clock_display_alarm"
+ android:title="@string/lockscreen_clock_display_alarm_title"
+ android:persistent="false"
+ android:defaultValue="true"
+ android:dependency="lockscreen_clock_enable" />
+
+ <org.omnirom.omnigears.preference.FontPreference
+ android:key="lockscreen_clock_font"
+ android:title="@string/lockscreen_clock_font_title"
+ android:persistent="false"
+ android:dependency="lockscreen_clock_enable" />
+
+ <org.omnirom.omnigears.preference.ColorPickerPreference
+ android:key="lockscreen_clock_color"
+ android:title="@string/lockscreen_clock_color_title"
+ android:persistent="false"
+ android:dependency="lockscreen_clock_enable" />
+
+ <org.omnirom.omnigears.preference.NumberPickerPreference
+ android:key="lockscreen_clock_size"
+ android:title="@string/lockscreen_clock_size_title"
+ android:persistent="false"
+ android:dependency="lockscreen_clock_enable" />
+
+ <com.android.settings.preference.SystemCheckBoxPreference
+ android:key="lockscreen_clock_shadow"
+ android:title="@string/lockscreen_clock_shadow_title"
+ android:defaultValue="false"
+ android:dependency="lockscreen_clock_enable" />
+
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/more_interface_settings.xml b/res/xml/more_interface_settings.xml
index cead945..855161c 100644
--- a/res/xml/more_interface_settings.xml
+++ b/res/xml/more_interface_settings.xml
@@ -16,8 +16,6 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- android:key="interface_more"
- android:title="@string/interface_more_title"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
<PreferenceCategory
diff --git a/res/xml/statusbar_battery_settings.xml b/res/xml/statusbar_battery_settings.xml
index 5080042..5ceb438 100644
--- a/res/xml/statusbar_battery_settings.xml
+++ b/res/xml/statusbar_battery_settings.xml
@@ -51,7 +51,7 @@
android:title="@string/statusbar_battery_charging_color_enable_title"
android:summary="@string/statusbar_battery_charging_color_enable_summary"
android:defaultValue="true"/>
- <org.omnirom.omnigears.ui.ColorPickerPreference
+ <org.omnirom.omnigears.preference.ColorPickerPreference
android:key="statusbar_battery_charging_color"
android:title="@string/statusbar_battery_charging_color_title"
android:persistent="false"
diff --git a/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java b/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java
index 39710c3..604ecb2 100644
--- a/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java
+++ b/src/org/omnirom/omnigears/interfacesettings/BarsSettings.java
@@ -126,7 +126,7 @@
mHeaderShadow = (SeekBarPreference) findPreference(CUSTOM_HEADER_IMAGE_SHADOW);
final int headerShadow = Settings.System.getInt(getContentResolver(),
Settings.System.STATUS_BAR_CUSTOM_HEADER_SHADOW, 0);
- mHeaderShadow.setValue((int)((headerShadow / 255) * 100));
+ mHeaderShadow.setValue((int)(((double) headerShadow / 255) * 100));
mHeaderShadow.setOnPreferenceChangeListener(this);
}
diff --git a/src/org/omnirom/omnigears/interfacesettings/LockscreenSettings.java b/src/org/omnirom/omnigears/interfacesettings/LockscreenSettings.java
index 40f14f9..2bd3ceb 100644
--- a/src/org/omnirom/omnigears/interfacesettings/LockscreenSettings.java
+++ b/src/org/omnirom/omnigears/interfacesettings/LockscreenSettings.java
@@ -19,25 +19,56 @@
import android.app.Activity;
import android.app.WallpaperManager;
+import android.content.Context;
+import android.content.ContentResolver;
import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
+import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+import android.provider.SearchIndexableResource;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
-public class LockscreenSettings extends SettingsPreferenceFragment {
+import org.omnirom.omnigears.R;
+import org.omnirom.omnigears.preference.FontPreference;
+import org.omnirom.omnigears.preference.NumberPickerPreference;
+import org.omnirom.omnigears.preference.ColorPickerPreference;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class LockscreenSettings extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener, Indexable {
public static final int IMAGE_PICK = 1;
private static final String KEY_WALLPAPER_SET = "lockscreen_wallpaper_set";
private static final String KEY_WALLPAPER_CLEAR = "lockscreen_wallpaper_clear";
+ private static final String KEY_CLOCK_FONT = "lockscreen_clock_font";
+ private static final String KEY_CLOCK_COLOR = "lockscreen_clock_color";
+ private static final String KEY_CLOCK_SIZE = "lockscreen_clock_size";
+ private static final String KEY_CLOCK_DISPLAY = "lockscreen_clock_display";
+ private static final String KEY_CLOCK_DISPLAY_TIME = "lockscreen_clock_display_time";
+ private static final String KEY_CLOCK_DISPLAY_DATE = "lockscreen_clock_display_date";
+ private static final String KEY_CLOCK_DISPLAY_ALARM = "lockscreen_clock_display_alarm";
private Preference mSetWallpaper;
private Preference mClearWallpaper;
+ private FontPreference mClockFont;
+ private NumberPickerPreference mClockSize;
+ private ColorPickerPreference mClockColor;
+ private CheckBoxPreference mClockDisplayTime;
+ private CheckBoxPreference mClockDisplayDate;
+ private CheckBoxPreference mClockDisplayAlarm;
@Override
protected int getMetricsCategory() {
@@ -51,10 +82,52 @@
mSetWallpaper = (Preference) findPreference(KEY_WALLPAPER_SET);
mClearWallpaper = (Preference) findPreference(KEY_WALLPAPER_CLEAR);
+
+ mClockFont = (FontPreference) findPreference(KEY_CLOCK_FONT);
+ mClockFont.setOnPreferenceChangeListener(this);
+ mClockColor = (ColorPickerPreference) findPreference(KEY_CLOCK_COLOR);
+ mClockColor.setOnPreferenceChangeListener(this);
+ mClockSize = (NumberPickerPreference) findPreference(KEY_CLOCK_SIZE);
+ mClockSize.setOnPreferenceChangeListener(this);
+ mClockSize.setMinValue(40);
+ mClockSize.setMaxValue(140);
+ mClockDisplayTime = (CheckBoxPreference) findPreference(KEY_CLOCK_DISPLAY_TIME);
+ mClockDisplayDate = (CheckBoxPreference) findPreference(KEY_CLOCK_DISPLAY_DATE);
+ mClockDisplayAlarm = (CheckBoxPreference) findPreference(KEY_CLOCK_DISPLAY_ALARM);
+
+ ContentResolver resolver = getActivity().getContentResolver();
+ int color = Settings.System.getInt(resolver, Settings.System.LOCK_CLOCK_COLOR, Color.WHITE);
+ mClockColor.setColor(color);
+ String hexColor = String.format("#%08X", color);
+ mClockColor.setSummary(hexColor);
+
+ int defaultSize = (int) (getResources().getDimension(com.android.internal.R.dimen.lock_clock_time_font_size)
+ / getResources().getDisplayMetrics().density);
+ int size = Settings.System.getInt(resolver, Settings.System.LOCK_CLOCK_SIZE, defaultSize);
+ mClockSize.setValue(size);
+ mClockSize.setSummary(String.valueOf(size));
+
+ String font = Settings.System.getString(resolver, Settings.System.LOCK_CLOCK_FONT);
+ if (font != null) {
+ mClockFont.setValue(font);
+ int valueIndex = mClockFont.findIndexOfValue(font);
+ if (valueIndex != -1) {
+ mClockFont.setSummary(mClockFont.getEntries()[valueIndex]);
+ }
+ } else {
+ mClockFont.setSummary("sans-serif-light");
+ }
+
+ final int clockDisplay = Settings.System.getInt(resolver,
+ Settings.System.LOCK_CLOCK_DISPLAY, Settings.System.LOCK_CLOCK_ALL);
+ mClockDisplayTime.setChecked((clockDisplay & Settings.System.LOCK_CLOCK_TIME) == Settings.System.LOCK_CLOCK_TIME);
+ mClockDisplayDate.setChecked((clockDisplay & Settings.System.LOCK_CLOCK_DATE) == Settings.System.LOCK_CLOCK_DATE);
+ mClockDisplayAlarm.setChecked((clockDisplay & Settings.System.LOCK_CLOCK_ALARM) == Settings.System.LOCK_CLOCK_ALARM);
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ ContentResolver resolver = getContentResolver();
if (preference == mSetWallpaper) {
setKeyguardWallpaper();
return true;
@@ -63,10 +136,48 @@
Toast.makeText(getView().getContext(), getString(R.string.reset_lockscreen_wallpaper),
Toast.LENGTH_LONG).show();
return true;
+ } else if (preference == mClockDisplayTime) {
+ Settings.System.putInt(resolver,
+ Settings.System.LOCK_CLOCK_DISPLAY, getCurrentClockDisplayValue());
+ return true;
+ } else if (preference == mClockDisplayDate) {
+ Settings.System.putInt(resolver,
+ Settings.System.LOCK_CLOCK_DISPLAY, getCurrentClockDisplayValue());
+ return true;
+ } else if (preference == mClockDisplayAlarm) {
+ Settings.System.putInt(resolver,
+ Settings.System.LOCK_CLOCK_DISPLAY, getCurrentClockDisplayValue());
+ return true;
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
+ private int getCurrentClockDisplayValue() {
+ return (mClockDisplayTime.isChecked() ? Settings.System.LOCK_CLOCK_TIME : 0) +
+ (mClockDisplayDate.isChecked() ? Settings.System.LOCK_CLOCK_DATE : 0) +
+ (mClockDisplayAlarm.isChecked() ? Settings.System.LOCK_CLOCK_ALARM : 0);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ ContentResolver resolver = getContentResolver();
+ if (preference == mClockFont) {
+ String value = (String) newValue;
+ int valueIndex = mClockFont.findIndexOfValue(value);
+ mClockFont.setSummary(mClockFont.getEntries()[valueIndex]);
+ Settings.System.putString(resolver, Settings.System.LOCK_CLOCK_FONT, value);
+ } else if (preference == mClockColor) {
+ String hexColor = String.format("#%08X", mClockColor.getColor());
+ mClockColor.setSummary(hexColor);
+ Settings.System.putInt(resolver, Settings.System.LOCK_CLOCK_COLOR, mClockColor.getColor());
+ } else if (preference == mClockSize) {
+ Integer value = (Integer) newValue;
+ mClockSize.setSummary(String.valueOf(value));
+ Settings.System.putInt(resolver, Settings.System.LOCK_CLOCK_SIZE, value);
+ }
+ return true;
+ }
+
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_PICK && resultCode == Activity.RESULT_OK) {
@@ -93,4 +204,26 @@
wallpaperManager = WallpaperManager.getInstance(getActivity());
wallpaperManager.clearKeyguardWallpaper();
}
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ ArrayList<SearchIndexableResource> result =
+ new ArrayList<SearchIndexableResource>();
+
+ SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.lockscreen_settings;
+ result.add(sir);
+
+ return result;
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ ArrayList<String> result = new ArrayList<String>();
+ return result;
+ }
+ };
}
diff --git a/src/org/omnirom/omnigears/interfacesettings/MoreInterfaceSettings.java b/src/org/omnirom/omnigears/interfacesettings/MoreInterfaceSettings.java
index f0b4ff1..60d07db 100644
--- a/src/org/omnirom/omnigears/interfacesettings/MoreInterfaceSettings.java
+++ b/src/org/omnirom/omnigears/interfacesettings/MoreInterfaceSettings.java
@@ -51,14 +51,6 @@
import java.util.List;
import java.util.ArrayList;
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.Indexable;
-
-import java.util.List;
-import java.util.ArrayList;
-
public class MoreInterfaceSettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener, Indexable {
private static final String TAG = "MoreInterfaceSettings";
diff --git a/src/org/omnirom/omnigears/interfacesettings/StatusbarBatterySettings.java b/src/org/omnirom/omnigears/interfacesettings/StatusbarBatterySettings.java
index 713e715..1d41cda 100644
--- a/src/org/omnirom/omnigears/interfacesettings/StatusbarBatterySettings.java
+++ b/src/org/omnirom/omnigears/interfacesettings/StatusbarBatterySettings.java
@@ -52,7 +52,7 @@
import java.util.List;
import java.util.ArrayList;
-import org.omnirom.omnigears.ui.ColorPickerPreference;
+import org.omnirom.omnigears.preference.ColorPickerPreference;
public class StatusbarBatterySettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener, Indexable {
diff --git a/src/org/omnirom/omnigears/ui/ColorPickerPreference.java b/src/org/omnirom/omnigears/preference/ColorPickerPreference.java
similarity index 96%
rename from src/org/omnirom/omnigears/ui/ColorPickerPreference.java
rename to src/org/omnirom/omnigears/preference/ColorPickerPreference.java
index 626670f..f2c2dff 100644
--- a/src/org/omnirom/omnigears/ui/ColorPickerPreference.java
+++ b/src/org/omnirom/omnigears/preference/ColorPickerPreference.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.omnirom.omnigears.ui;
+package org.omnirom.omnigears.preference;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -37,7 +37,8 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.settings.R;
+import org.omnirom.omnigears.R;
+import org.omnirom.omnigears.ui.ColorPickerDialog;
public class ColorPickerPreference extends Preference implements DialogInterface.OnDismissListener {
diff --git a/src/org/omnirom/omnigears/preference/FontPreference.java b/src/org/omnirom/omnigears/preference/FontPreference.java
new file mode 100644
index 0000000..76e18ea
--- /dev/null
+++ b/src/org/omnirom/omnigears/preference/FontPreference.java
@@ -0,0 +1,74 @@
+/*
+ * 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 org.omnirom.omnigears.preference;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.graphics.Typeface;
+import android.preference.ListPreference;
+import android.util.Log;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.omnirom.omnigears.R;
+import org.omnirom.omnigears.utils.FontManager;
+
+public class FontPreference extends ListPreference {
+ private TextView mFontSample;
+
+ public FontPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.preference_font_picker);
+
+ HashMap< String, String > fonts = FontManager.enumerateFonts();
+ List<CharSequence>fontPaths = new ArrayList<CharSequence>();
+ List<CharSequence> fontNames = new ArrayList<CharSequence>();
+
+ List<String> keys = new ArrayList<String>();
+ keys.addAll(fonts.keySet());
+ Collections.sort(keys);
+
+ for (String name : keys) {
+ fontNames.add(name);
+ fontPaths.add(fonts.get(name));
+ }
+
+ setEntries(fontNames.toArray(new CharSequence[fontNames.size()]));
+ setEntryValues(fontPaths.toArray(new CharSequence[fontPaths.size()]));
+ }
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ mFontSample = (TextView) view.findViewById(R.id.font_sample);
+ if (getValue() != null) {
+ Typeface tface = Typeface.createFromFile(getValue());
+ if (tface != null) {
+ mFontSample.setTypeface(tface);
+ }
+ }
+ }
+}
diff --git a/src/org/omnirom/omnigears/preference/NumberPickerPreference.java b/src/org/omnirom/omnigears/preference/NumberPickerPreference.java
new file mode 100644
index 0000000..55e9495
--- /dev/null
+++ b/src/org/omnirom/omnigears/preference/NumberPickerPreference.java
@@ -0,0 +1,115 @@
+/*
+ * Based on: http://www.lukehorvat.com/blog/android-numberpickerdialogpreference/
+ * Thanks to the original author!
+ */
+
+package org.omnirom.omnigears.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.preference.DialogPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.NumberPicker;
+
+import org.omnirom.omnigears.R;
+
+/**
+* A {@link DialogPreference} that provides a user with the means to select an integer from a {@link NumberPicker}, and persist it.
+*
+* @author lukehorvat
+*
+*/
+public class NumberPickerPreference extends DialogPreference
+{
+ private static final int DEFAULT_MIN_VALUE = 0;
+ private static final int DEFAULT_MAX_VALUE = 100;
+ private static final int DEFAULT_VALUE = 0;
+
+ private int mMinValue;
+ private int mMaxValue;
+ private int mValue;
+ private NumberPicker mNumberPicker;
+
+ public NumberPickerPreference(Context context) {
+ this(context, null);
+ }
+
+ public NumberPickerPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ setMinValue(DEFAULT_MIN_VALUE);
+ setMaxValue(DEFAULT_MAX_VALUE);
+
+ // set layout
+ setDialogLayoutResource(R.layout.preference_number_picker);
+ setPositiveButtonText(android.R.string.ok);
+ setNegativeButtonText(android.R.string.cancel);
+ setDialogIcon(null);
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restore, Object defaultValue) {
+ setValue(restore ? getPersistedInt(DEFAULT_VALUE) : (Integer) defaultValue);
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray a, int index) {
+ return a.getInt(index, DEFAULT_VALUE);
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mNumberPicker = (NumberPicker) view.findViewById(R.id.number_picker);
+ mNumberPicker.setMinValue(mMinValue);
+ mNumberPicker.setMaxValue(mMaxValue);
+ mNumberPicker.setValue(mValue);
+ }
+
+ public int getMinValue() {
+ return mMinValue;
+ }
+
+ public void setMinValue(int minValue) {
+ mMinValue = minValue;
+ setValue(Math.max(mValue, mMinValue));
+ }
+
+ public int getMaxValue() {
+ return mMaxValue;
+ }
+
+ public void setMaxValue(int maxValue) {
+ mMaxValue = maxValue;
+ setValue(Math.min(mValue, mMaxValue));
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+
+ public void setValue(int value) {
+ value = Math.max(Math.min(value, mMaxValue), mMinValue);
+
+ if (value != mValue) {
+ mValue = value;
+ persistInt(value);
+ notifyChanged();
+ }
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ // when the user selects "OK", persist the new value
+ if (positiveResult) {
+ int numberPickerValue = mNumberPicker.getValue();
+ if (callChangeListener(numberPickerValue)) {
+ setValue(numberPickerValue);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/omnirom/omnigears/utils/FontManager.java b/src/org/omnirom/omnigears/utils/FontManager.java
new file mode 100644
index 0000000..7ea3163
--- /dev/null
+++ b/src/org/omnirom/omnigears/utils/FontManager.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2011 George Yunaev @ Ulduzsoft
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ */
+
+package org.omnirom.omnigears.utils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.HashMap;
+
+public class FontManager
+{
+ // This function enumerates all fonts on Android system and returns the HashMap with the font
+ // absolute file name as key, and the font literal name (embedded into the font) as value.
+ static public HashMap< String, String > enumerateFonts()
+ {
+ String[] fontdirs = { "/system/fonts", "/system/font", "/data/fonts" };
+ HashMap< String, String > fonts = new HashMap< String, String >();
+ TTFAnalyzer analyzer = new TTFAnalyzer();
+
+ for ( String fontdir : fontdirs )
+ {
+ File dir = new File( fontdir );
+
+ if ( !dir.exists() )
+ continue;
+
+ File[] files = dir.listFiles();
+
+ if ( files == null )
+ continue;
+
+ for ( File file : files )
+ {
+ String fontname = analyzer.getTtfFontName( file.getAbsolutePath() );
+
+ if ( fontname != null )
+ fonts.put( fontname, file.getAbsolutePath() );
+ }
+ }
+
+ return fonts.isEmpty() ? null : fonts;
+ }
+}
+
+// The class which loads the TTF file, parses it and returns the TTF font name
+class TTFAnalyzer
+{
+ // This function parses the TTF file and returns the font name specified in the file
+ public String getTtfFontName( String fontFilename )
+ {
+ try
+ {
+ // Parses the TTF file format.
+ // See http://developer.apple.com/fonts/ttrefman/rm06/Chap6.html
+ m_file = new RandomAccessFile( fontFilename, "r" );
+
+ // Read the version first
+ int version = readDword();
+
+ // The version must be either 'true' (0x74727565) or 0x00010000
+ if ( version != 0x74727565 && version != 0x00010000 )
+ return null;
+
+ // The TTF file consist of several sections called "tables", and we need to know how many of them are there.
+ int numTables = readWord();
+
+ // Skip the rest in the header
+ readWord(); // skip searchRange
+ readWord(); // skip entrySelector
+ readWord(); // skip rangeShift
+
+ // Now we can read the tables
+ for ( int i = 0; i < numTables; i++ )
+ {
+ // Read the table entry
+ int tag = readDword();
+ readDword(); // skip checksum
+ int offset = readDword();
+ int length = readDword();
+
+ // Now here' the trick. 'name' field actually contains the textual string name.
+ // So the 'name' string in characters equals to 0x6E616D65
+ if ( tag == 0x6E616D65 )
+ {
+ // Here's the name section. Read it completely into the allocated buffer
+ byte[] table = new byte[ length ];
+
+ m_file.seek( offset );
+ read( table );
+
+ // This is also a table. See http://developer.apple.com/fonts/ttrefman/rm06/Chap6name.html
+ // According to Table 36, the total number of table records is stored in the second word, at the offset 2.
+ // Getting the count and string offset - remembering it's big endian.
+ int count = getWord( table, 2 );
+ int string_offset = getWord( table, 4 );
+
+ // Record starts from offset 6
+ for ( int record = 0; record < count; record++ )
+ {
+ // Table 37 tells us that each record is 6 words -> 12 bytes, and that the nameID is 4th word so its offset is 6.
+ // We also need to account for the first 6 bytes of the header above (Table 36), so...
+ int nameid_offset = record * 12 + 6;
+ int platformID = getWord( table, nameid_offset );
+ int nameid_value = getWord( table, nameid_offset + 6 );
+
+ // Table 42 lists the valid name Identifiers. We're interested in 4 but not in Unicode encoding (for simplicity).
+ // The encoding is stored as PlatformID and we're interested in Mac encoding
+ if ( nameid_value == 4 && platformID == 1 )
+ {
+ // We need the string offset and length, which are the word 6 and 5 respectively
+ int name_length = getWord( table, nameid_offset + 8 );
+ int name_offset = getWord( table, nameid_offset + 10 );
+
+ // The real name string offset is calculated by adding the string_offset
+ name_offset = name_offset + string_offset;
+
+ // Make sure it is inside the array
+ if ( name_offset >= 0 && name_offset + name_length < table.length )
+ return new String( table, name_offset, name_length );
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+ catch (FileNotFoundException e)
+ {
+ // Permissions?
+ return null;
+ }
+ catch (IOException e)
+ {
+ // Most likely a corrupted font file
+ return null;
+ }
+ }
+
+ // Font file; must be seekable
+ private RandomAccessFile m_file = null;
+
+ // Helper I/O functions
+ private int readByte() throws IOException
+ {
+ return m_file.read() & 0xFF;
+ }
+
+ private int readWord() throws IOException
+ {
+ int b1 = readByte();
+ int b2 = readByte();
+
+ return b1 << 8 | b2;
+ }
+
+ private int readDword() throws IOException
+ {
+ int b1 = readByte();
+ int b2 = readByte();
+ int b3 = readByte();
+ int b4 = readByte();
+
+ return b1 << 24 | b2 << 16 | b3 << 8 | b4;
+ }
+
+ private void read( byte [] array ) throws IOException
+ {
+ if ( m_file.read( array ) != array.length )
+ throw new IOException();
+ }
+
+ // Helper
+ private int getWord( byte [] array, int offset )
+ {
+ int b1 = array[ offset ] & 0xFF;
+ int b2 = array[ offset + 1 ] & 0xFF;
+
+ return b1 << 8 | b2;
+ }
+}