[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;
+    }
+}