Add minimum font size support

Change-Id: I2dc092f7484ff63ce90f15c2c46c7029c84265e8
diff --git a/src/com/android/browser/BrowserSettings.java b/src/com/android/browser/BrowserSettings.java
index 9dc3c5f..b791531 100644
--- a/src/com/android/browser/BrowserSettings.java
+++ b/src/com/android/browser/BrowserSettings.java
@@ -59,6 +59,7 @@
  * To remove an observer:
  * s.deleteObserver(webView.getSettings());
  */
+// TODO: Really need to refactor this :/
 public class BrowserSettings extends Observable implements OnSharedPreferenceChangeListener {
     // Private variables for settings
     // NOTE: these defaults need to be kept in sync with the XML
@@ -92,6 +93,9 @@
     private String databasePath; // default value set in loadFromDb()
     private String geolocationDatabasePath; // default value set in loadFromDb()
     private WebStorageSizeManager webStorageSizeManager;
+    // Accessibility settings
+    private int minimumFontSize = 1;
+    private WebSettings.TextSize textSize = WebSettings.TextSize.NORMAL;
 
     private String jsFlags = "";
 
@@ -117,12 +121,9 @@
     private boolean showConsole = true;
 
     // Private preconfigured values
-    private static int minimumFontSize = 1;
     private static int minimumLogicalFontSize = 1;
     private static int defaultFontSize = 16;
     private static int defaultFixedFontSize = 13;
-    private static WebSettings.TextSize textSize =
-        WebSettings.TextSize.NORMAL;
     private static WebSettings.ZoomDensity zoomDensity =
         WebSettings.ZoomDensity.MEDIUM;
     private static int pageCacheCapacity;
@@ -167,6 +168,7 @@
     public final static String PREF_MOST_VISITED_HOMEPAGE = "use_most_visited_homepage";
     public final static String PREF_PLUGIN_STATE = "plugin_state";
     public final static String PREF_USE_INSTANT = "use_instant_search";
+    public final static String PREF_MIN_FONT_SIZE = "min_font_size";
 
     private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (Macintosh; " +
             "U; Intel Mac OS X 10_6_3; en-us) AppleWebKit/533.16 (KHTML, " +
@@ -221,7 +223,7 @@
      * An observer wrapper for updating a WebSettings object with the new
      * settings after a call to BrowserSettings.update().
      */
-    static class Observer implements java.util.Observer {
+    public static class Observer implements java.util.Observer {
         // Private WebSettings object that will be updated.
         private WebSettings mSettings;
 
@@ -432,7 +434,7 @@
          }
     }
 
-    /* package */ void syncSharedPreferences(Context ctx, SharedPreferences p) {
+    public void syncSharedPreferences(Context ctx, SharedPreferences p) {
 
         homeUrl =
             p.getString(PREF_HOMEPAGE, homeUrl);
@@ -464,6 +466,7 @@
         openInBackground = p.getBoolean("open_in_background", openInBackground);
         textSize = WebSettings.TextSize.valueOf(
                 p.getString(PREF_TEXT_SIZE, textSize.name()));
+        minimumFontSize = p.getInt(PREF_MIN_FONT_SIZE, 1);
         zoomDensity = WebSettings.ZoomDensity.valueOf(
                 p.getString(PREF_DEFAULT_ZOOM, zoomDensity.name()));
         autoFitPage = p.getBoolean("autofit_pages", autoFitPage);
@@ -566,6 +569,10 @@
         return textSize;
     }
 
+    public int getMinimumFontSize() {
+        return minimumFontSize;
+    }
+
     public WebSettings.ZoomDensity getDefaultZoom() {
         return zoomDensity;
     }
diff --git a/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java b/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java
new file mode 100644
index 0000000..1f88e48
--- /dev/null
+++ b/src/com/android/browser/preferences/AccessibilityPreferencesFragment.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.browser.preferences;
+
+import com.android.browser.BrowserSettings;
+import com.android.browser.R;
+
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceFragment;
+import android.util.Log;
+import android.view.View;
+
+public class AccessibilityPreferencesFragment extends PreferenceFragment
+        implements Preference.OnPreferenceChangeListener {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.accessibility_preferences);
+
+        Preference e = findPreference(BrowserSettings.PREF_TEXT_SIZE);
+        e.setOnPreferenceChangeListener(this);
+        e.setSummary(getVisualTextSizeName(
+                getPreferenceScreen().getSharedPreferences()
+                .getString(BrowserSettings.PREF_TEXT_SIZE, null)) );
+    }
+
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        getListView().setItemsCanFocus(true);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference pref, Object objValue) {
+        if (getActivity() == null) {
+            // We aren't attached, so don't accept preferences changes from the
+            // invisible UI.
+            return false;
+        }
+
+        if (pref.getKey().equals(BrowserSettings.PREF_TEXT_SIZE)) {
+            pref.setSummary(getVisualTextSizeName((String) objValue));
+            return true;
+        }
+        return false;
+    }
+
+    private CharSequence getVisualTextSizeName(String enumName) {
+        Resources res = getActivity().getResources();
+        CharSequence[] visualNames = res.getTextArray(R.array.pref_text_size_choices);
+        CharSequence[] enumNames = res.getTextArray(R.array.pref_text_size_values);
+
+        // Sanity check
+        if (visualNames.length != enumNames.length) {
+            return "";
+        }
+
+        int length = enumNames.length;
+        for (int i = 0; i < length; i++) {
+            if (enumNames[i].equals(enumName)) {
+                return visualNames[i];
+            }
+        }
+
+        return "";
+    }
+
+}
\ No newline at end of file
diff --git a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
index e2e45f5..80db879 100644
--- a/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
+++ b/src/com/android/browser/preferences/AdvancedPreferencesFragment.java
@@ -49,13 +49,7 @@
                 BrowserSettings.PREF_WEBSITE_SETTINGS);
         websiteSettings.setFragment(WebsiteSettingsFragment.class.getName());
 
-        Preference e = findPreference(BrowserSettings.PREF_TEXT_SIZE);
-        e.setOnPreferenceChangeListener(this);
-        e.setSummary(getVisualTextSizeName(
-                getPreferenceScreen().getSharedPreferences()
-                .getString(BrowserSettings.PREF_TEXT_SIZE, null)) );
-
-        e = findPreference(BrowserSettings.PREF_DEFAULT_ZOOM);
+        Preference e = findPreference(BrowserSettings.PREF_DEFAULT_ZOOM);
         e.setOnPreferenceChangeListener(this);
         e.setSummary(getVisualDefaultZoomName(
                 getPreferenceScreen().getSharedPreferences()
@@ -114,10 +108,7 @@
             return false;
         }
 
-        if (pref.getKey().equals(BrowserSettings.PREF_TEXT_SIZE)) {
-            pref.setSummary(getVisualTextSizeName((String) objValue));
-            return true;
-        } else if (pref.getKey().equals(BrowserSettings.PREF_DEFAULT_ZOOM)) {
+        if (pref.getKey().equals(BrowserSettings.PREF_DEFAULT_ZOOM)) {
             pref.setSummary(getVisualDefaultZoomName((String) objValue));
             return true;
         } else if (pref.getKey().equals(BrowserSettings.PREF_DEFAULT_TEXT_ENCODING)) {
@@ -139,26 +130,6 @@
         return false;
     }
 
-    private CharSequence getVisualTextSizeName(String enumName) {
-        Resources res = getActivity().getResources();
-        CharSequence[] visualNames = res.getTextArray(R.array.pref_text_size_choices);
-        CharSequence[] enumNames = res.getTextArray(R.array.pref_text_size_values);
-
-        // Sanity check
-        if (visualNames.length != enumNames.length) {
-            return "";
-        }
-
-        int length = enumNames.length;
-        for (int i = 0; i < length; i++) {
-            if (enumNames[i].equals(enumName)) {
-                return visualNames[i];
-            }
-        }
-
-        return "";
-    }
-
     private CharSequence getVisualDefaultZoomName(String enumName) {
         Resources res = getActivity().getResources();
         CharSequence[] visualNames = res.getTextArray(R.array.pref_default_zoom_choices);
diff --git a/src/com/android/browser/preferences/MinFontSizePreference.java b/src/com/android/browser/preferences/MinFontSizePreference.java
new file mode 100644
index 0000000..22092b0
--- /dev/null
+++ b/src/com/android/browser/preferences/MinFontSizePreference.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser.preferences;
+
+import com.android.browser.R;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+public class MinFontSizePreference extends Preference implements OnSeekBarChangeListener {
+
+    // range from 1:6..24
+    static final int MIN = 5;
+    static final int MAX = 23;
+    private int mProgress;
+    View mRoot;
+
+    public MinFontSizePreference(
+            Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public MinFontSizePreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public MinFontSizePreference(Context context) {
+        super(context);
+    }
+
+    @Override
+    public View getView(View convertView, ViewGroup parent) {
+        if (mRoot == null) {
+            LayoutInflater inflater = LayoutInflater.from(getContext());
+            mRoot = inflater.inflate(R.layout.min_font_size, parent, false);
+            SeekBar seek = (SeekBar) mRoot.findViewById(R.id.seekbar);
+            seek.setMax((MAX - MIN));
+            seek.setProgress(mProgress);
+            seek.setOnSeekBarChangeListener(this);
+        }
+        return mRoot;
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        mProgress = restoreValue ? getPersistedInt(mProgress)
+                : (Integer) defaultValue;
+        mProgress -= 1;
+    }
+
+    @Override
+    public void onProgressChanged(
+            SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+            if (progress == 0) {
+                persistInt(1);
+            } else {
+                persistInt(progress + MIN + 1);
+            }
+        }
+        mRoot.invalidate();
+    }
+
+    @Override
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    @Override
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        /*
+         * Suppose a client uses this preference type without persisting. We
+         * must save the instance state so it is able to, for example, survive
+         * orientation changes.
+         */
+
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        // Save the instance state
+        final SavedState myState = new SavedState(superState);
+        myState.progress = mProgress;
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (!state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        // Restore the instance state
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        mProgress = myState.progress;
+        notifyChanged();
+    }
+
+    /**
+     * SavedState, a subclass of {@link BaseSavedState}, will store the state
+     * of MyPreference, a subclass of Preference.
+     * <p>
+     * It is important to always call through to super methods.
+     */
+    private static class SavedState extends BaseSavedState {
+        int progress;
+
+        public SavedState(Parcel source) {
+            super(source);
+
+            // Restore the click counter
+            progress = source.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+
+            // Save the click counter
+            dest.writeInt(progress);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
+}
diff --git a/src/com/android/browser/preferences/WebViewPreview.java b/src/com/android/browser/preferences/WebViewPreview.java
new file mode 100644
index 0000000..15dc83a
--- /dev/null
+++ b/src/com/android/browser/preferences/WebViewPreview.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser.preferences;
+
+import com.android.browser.BrowserSettings;
+import com.android.browser.R;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
+import android.preference.Preference;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+
+public class WebViewPreview extends Preference implements OnSharedPreferenceChangeListener {
+
+    // 80 char line width limit? Rules are made to be broken.
+    static final String HTML_FORMAT = "<html><head><style type=\"text/css\">p { margin: 2px auto;}</style><body><p style=\"font-size: .4em\">%s</p><p style=\"font-size: .7em\">%s</p><p style=\"font-size: 1em\">%s</p><p style=\"font-size: 1.3em\">%s</p><p style=\"font-size: 1.6em\">%s</p></body></html>";
+
+    String HTML;
+    private View mRoot;
+    private WebView mWebView;
+
+    public WebViewPreview(
+            Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init(context);
+    }
+
+    public WebViewPreview(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init(context);
+    }
+
+    public WebViewPreview(Context context) {
+        super(context);
+        init(context);
+    }
+
+    void init(Context context) {
+        Resources res = context.getResources();
+        Object[] visualNames = res.getStringArray(R.array.pref_text_size_choices);
+        HTML = String.format(HTML_FORMAT, visualNames);
+    }
+
+    void updatePreview() {
+        if (mWebView == null) return;
+
+        BrowserSettings.getInstance().syncSharedPreferences(getContext(),
+                PreferenceManager.getDefaultSharedPreferences(getContext()));
+        WebSettings ws = mWebView.getSettings();
+        BrowserSettings bs = BrowserSettings.getInstance();
+        ws.setMinimumFontSize(bs.getMinimumFontSize());
+        ws.setTextSize(bs.getTextSize());
+        mWebView.loadData(HTML, "text/html", "utf-8");
+    }
+
+    @Override
+    public View getView(View convertView, ViewGroup parent) {
+        if (mWebView == null) {
+            LayoutInflater inflater = LayoutInflater.from(getContext());
+            mRoot = inflater.inflate(R.layout.webview_preview, parent, false);
+            mWebView = (WebView) mRoot.findViewById(R.id.webview);
+        }
+        updatePreview();
+        return mRoot;
+    }
+
+    @Override
+    protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+        super.onAttachedToHierarchy(preferenceManager);
+        getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
+    }
+
+    @Override
+    protected void onPrepareForRemoval() {
+        getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
+        super.onPrepareForRemoval();
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(
+            SharedPreferences sharedPreferences, String key) {
+        updatePreview();
+    }
+
+}