summaryrefslogtreecommitdiffstats
path: root/mobile/android/base/java/org/mozilla/gecko/preferences/FontSizePreference.java
blob: c77c2cc23a68780bae9b6edd756af53f1fbe4c12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.preferences;

import org.mozilla.gecko.R;

import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ScrollView;
import android.widget.TextView;

import java.util.HashMap;

class FontSizePreference extends DialogPreference {
    private static final String LOGTAG = "FontSizePreference";
    private static final int TWIP_TO_PT_RATIO = 20; // 20 twip = 1 point.
    private static final int PREVIEW_FONT_SIZE_UNIT = TypedValue.COMPLEX_UNIT_PT;
    private static final int DEFAULT_FONT_INDEX = 2;

    private final Context mContext;
    /** Container for mPreviewFontView to allow for scrollable padding at the top of the view. */
    private ScrollView mScrollingContainer;
    private TextView mPreviewFontView;
    private Button mIncreaseFontButton;
    private Button mDecreaseFontButton;

    private final String[] mFontTwipValues;
    private final String[] mFontSizeNames; // Ex: "Small".
    /** Index into the above arrays for the saved preference value (from Gecko). */
    private int mSavedFontIndex = DEFAULT_FONT_INDEX;
    /** Index into the above arrays for the currently displayed font size (the preview). */
    private int mPreviewFontIndex = mSavedFontIndex;
    private final HashMap<String, Integer> mFontTwipToIndexMap;

    public FontSizePreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;

        final Resources res = mContext.getResources();
        mFontTwipValues = res.getStringArray(R.array.pref_font_size_values);
        mFontSizeNames = res.getStringArray(R.array.pref_font_size_entries);
        mFontTwipToIndexMap = new HashMap<String, Integer>();
        for (int i = 0; i < mFontTwipValues.length; ++i) {
            mFontTwipToIndexMap.put(mFontTwipValues[i], i);
        }
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
        final LayoutInflater inflater =
            (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View dialogView = inflater.inflate(R.layout.font_size_preference, null);
        initInternalViews(dialogView);
        updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]);

        builder.setTitle(null);
        builder.setView(dialogView);
    }

    /** Saves relevant views to instance variables and initializes their settings. */
    private void initInternalViews(View dialogView) {
        mScrollingContainer = (ScrollView) dialogView.findViewById(R.id.scrolling_container);
        // Background cannot be set in XML (see bug 783597 - TODO: Change this to XML when bug is fixed).
        mScrollingContainer.setBackgroundColor(Color.WHITE);
        mPreviewFontView = (TextView) dialogView.findViewById(R.id.preview);

        mDecreaseFontButton = (Button) dialogView.findViewById(R.id.decrease_preview_font_button);
        mIncreaseFontButton = (Button) dialogView.findViewById(R.id.increase_preview_font_button);
        setButtonState(mPreviewFontIndex);
        mDecreaseFontButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPreviewFontIndex = Math.max(mPreviewFontIndex - 1, 0);
                updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]);
                mIncreaseFontButton.setEnabled(true);
                // If we reached the minimum index, disable the button.
                if (mPreviewFontIndex == 0) {
                    mDecreaseFontButton.setEnabled(false);
                }
            }
        });
        mIncreaseFontButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPreviewFontIndex = Math.min(mPreviewFontIndex + 1, mFontTwipValues.length - 1);
                updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]);

                mDecreaseFontButton.setEnabled(true);
                // If we reached the maximum index, disable the button.
                if (mPreviewFontIndex == mFontTwipValues.length - 1) {
                    mIncreaseFontButton.setEnabled(false);
                }
            }
        });
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);
        if (!positiveResult) {
            mPreviewFontIndex = mSavedFontIndex;
            return;
        }
        mSavedFontIndex = mPreviewFontIndex;
        final String twipVal = mFontTwipValues[mSavedFontIndex];
        final OnPreferenceChangeListener prefChangeListener = getOnPreferenceChangeListener();
        if (prefChangeListener == null) {
            Log.e(LOGTAG, "PreferenceChangeListener is null. FontSizePreference will not be saved to Gecko.");
            return;
        }
        prefChangeListener.onPreferenceChange(this, twipVal);
    }

    /**
     * Finds the index of the given twip value and sets it as the saved preference value. Also the
     * current preview text size to the given value. Does not update the mPreviewFontView text size.
     */
    protected void setSavedFontSize(String twip) {
        final Integer index = mFontTwipToIndexMap.get(twip);
        if (index != null) {
            mSavedFontIndex = index;
            mPreviewFontIndex = mSavedFontIndex;
            return;
        }
        resetSavedFontSizeToDefault();
        Log.e(LOGTAG, "setSavedFontSize: Given font size does not exist in twip values map. Reverted to default font size.");
    }

    /**
     * Updates the mPreviewFontView to the given text size, resets the container's scroll to the top
     * left, and invalidates the view. Does not update the font indices.
     */
    private void updatePreviewFontSize(String twip) {
        float pt = convertTwipStrToPT(twip);
        // Android will not render a font size of 0 pt but for Gecko, 0 twip turns off font
        // inflation. Thus we special case 0 twip to display a renderable font size.
        if (pt == 0) {
            // Android adds an inexplicable extra margin on the smallest font size so to get around
            // this, we reinflate the view.
            ViewGroup parentView = (ViewGroup) mScrollingContainer.getParent();
            parentView.removeAllViews();
            final LayoutInflater inflater =
                (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View dialogView = inflater.inflate(R.layout.font_size_preference, parentView);
            initInternalViews(dialogView);
            mPreviewFontView.setTextSize(PREVIEW_FONT_SIZE_UNIT, 1);
        } else {
            mPreviewFontView.setTextSize(PREVIEW_FONT_SIZE_UNIT, pt);
        }
        mScrollingContainer.scrollTo(0, 0);
    }

    /**
     * Resets the font indices to the default value. Does not update the mPreviewFontView text size.
     */
    private void resetSavedFontSizeToDefault() {
        mSavedFontIndex = DEFAULT_FONT_INDEX;
        mPreviewFontIndex = mSavedFontIndex;
    }

    private void setButtonState(int index) {
        if (index == 0) {
            mDecreaseFontButton.setEnabled(false);
        } else if (index == mFontTwipValues.length - 1) {
            mIncreaseFontButton.setEnabled(false);
        }
    }

    /**
     * Returns the name of the font size (ex: "Small") at the currently saved preference value.
     */
    protected String getSavedFontSizeName() {
        return mFontSizeNames[mSavedFontIndex];
    }

    private float convertTwipStrToPT(String twip) {
        return Float.parseFloat(twip) / TWIP_TO_PT_RATIO;
    }
}