1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- 2 * This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 package org.mozilla.gecko.preferences; 7 8 import org.mozilla.gecko.R; 9 10 import android.app.AlertDialog; 11 import android.content.Context; 12 import android.content.res.Resources; 13 import android.graphics.Color; 14 import android.preference.DialogPreference; 15 import android.util.AttributeSet; 16 import android.util.Log; 17 import android.util.TypedValue; 18 import android.view.LayoutInflater; 19 import android.view.View; 20 import android.view.ViewGroup; 21 import android.widget.Button; 22 import android.widget.ScrollView; 23 import android.widget.TextView; 24 25 import java.util.HashMap; 26 27 class FontSizePreference extends DialogPreference { 28 private static final String LOGTAG = "FontSizePreference"; 29 private static final int TWIP_TO_PT_RATIO = 20; // 20 twip = 1 point. 30 private static final int PREVIEW_FONT_SIZE_UNIT = TypedValue.COMPLEX_UNIT_PT; 31 private static final int DEFAULT_FONT_INDEX = 2; 32 33 private final Context mContext; 34 /** Container for mPreviewFontView to allow for scrollable padding at the top of the view. */ 35 private ScrollView mScrollingContainer; 36 private TextView mPreviewFontView; 37 private Button mIncreaseFontButton; 38 private Button mDecreaseFontButton; 39 40 private final String[] mFontTwipValues; 41 private final String[] mFontSizeNames; // Ex: "Small". 42 /** Index into the above arrays for the saved preference value (from Gecko). */ 43 private int mSavedFontIndex = DEFAULT_FONT_INDEX; 44 /** Index into the above arrays for the currently displayed font size (the preview). */ 45 private int mPreviewFontIndex = mSavedFontIndex; 46 private final HashMap<String, Integer> mFontTwipToIndexMap; 47 FontSizePreference(Context context, AttributeSet attrs)48 public FontSizePreference(Context context, AttributeSet attrs) { 49 super(context, attrs); 50 mContext = context; 51 52 final Resources res = mContext.getResources(); 53 mFontTwipValues = res.getStringArray(R.array.pref_font_size_values); 54 mFontSizeNames = res.getStringArray(R.array.pref_font_size_entries); 55 mFontTwipToIndexMap = new HashMap<String, Integer>(); 56 for (int i = 0; i < mFontTwipValues.length; ++i) { 57 mFontTwipToIndexMap.put(mFontTwipValues[i], i); 58 } 59 } 60 61 @Override onPrepareDialogBuilder(AlertDialog.Builder builder)62 protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 63 final LayoutInflater inflater = 64 (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 65 View dialogView = inflater.inflate(R.layout.font_size_preference, null); 66 initInternalViews(dialogView); 67 updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]); 68 69 builder.setTitle(null); 70 builder.setView(dialogView); 71 } 72 73 /** Saves relevant views to instance variables and initializes their settings. */ initInternalViews(View dialogView)74 private void initInternalViews(View dialogView) { 75 mScrollingContainer = (ScrollView) dialogView.findViewById(R.id.scrolling_container); 76 // Background cannot be set in XML (see bug 783597 - TODO: Change this to XML when bug is fixed). 77 mScrollingContainer.setBackgroundColor(Color.WHITE); 78 mPreviewFontView = (TextView) dialogView.findViewById(R.id.preview); 79 80 mDecreaseFontButton = (Button) dialogView.findViewById(R.id.decrease_preview_font_button); 81 mIncreaseFontButton = (Button) dialogView.findViewById(R.id.increase_preview_font_button); 82 setButtonState(mPreviewFontIndex); 83 mDecreaseFontButton.setOnClickListener(new View.OnClickListener() { 84 @Override 85 public void onClick(View v) { 86 mPreviewFontIndex = Math.max(mPreviewFontIndex - 1, 0); 87 updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]); 88 mIncreaseFontButton.setEnabled(true); 89 // If we reached the minimum index, disable the button. 90 if (mPreviewFontIndex == 0) { 91 mDecreaseFontButton.setEnabled(false); 92 } 93 } 94 }); 95 mIncreaseFontButton.setOnClickListener(new View.OnClickListener() { 96 @Override 97 public void onClick(View v) { 98 mPreviewFontIndex = Math.min(mPreviewFontIndex + 1, mFontTwipValues.length - 1); 99 updatePreviewFontSize(mFontTwipValues[mPreviewFontIndex]); 100 101 mDecreaseFontButton.setEnabled(true); 102 // If we reached the maximum index, disable the button. 103 if (mPreviewFontIndex == mFontTwipValues.length - 1) { 104 mIncreaseFontButton.setEnabled(false); 105 } 106 } 107 }); 108 } 109 110 @Override onDialogClosed(boolean positiveResult)111 protected void onDialogClosed(boolean positiveResult) { 112 super.onDialogClosed(positiveResult); 113 if (!positiveResult) { 114 mPreviewFontIndex = mSavedFontIndex; 115 return; 116 } 117 mSavedFontIndex = mPreviewFontIndex; 118 final String twipVal = mFontTwipValues[mSavedFontIndex]; 119 final OnPreferenceChangeListener prefChangeListener = getOnPreferenceChangeListener(); 120 if (prefChangeListener == null) { 121 Log.e(LOGTAG, "PreferenceChangeListener is null. FontSizePreference will not be saved to Gecko."); 122 return; 123 } 124 prefChangeListener.onPreferenceChange(this, twipVal); 125 } 126 127 /** 128 * Finds the index of the given twip value and sets it as the saved preference value. Also the 129 * current preview text size to the given value. Does not update the mPreviewFontView text size. 130 */ setSavedFontSize(String twip)131 protected void setSavedFontSize(String twip) { 132 final Integer index = mFontTwipToIndexMap.get(twip); 133 if (index != null) { 134 mSavedFontIndex = index; 135 mPreviewFontIndex = mSavedFontIndex; 136 return; 137 } 138 resetSavedFontSizeToDefault(); 139 Log.e(LOGTAG, "setSavedFontSize: Given font size does not exist in twip values map. Reverted to default font size."); 140 } 141 142 /** 143 * Updates the mPreviewFontView to the given text size, resets the container's scroll to the top 144 * left, and invalidates the view. Does not update the font indices. 145 */ updatePreviewFontSize(String twip)146 private void updatePreviewFontSize(String twip) { 147 float pt = convertTwipStrToPT(twip); 148 // Android will not render a font size of 0 pt but for Gecko, 0 twip turns off font 149 // inflation. Thus we special case 0 twip to display a renderable font size. 150 if (pt == 0) { 151 // Android adds an inexplicable extra margin on the smallest font size so to get around 152 // this, we reinflate the view. 153 ViewGroup parentView = (ViewGroup) mScrollingContainer.getParent(); 154 parentView.removeAllViews(); 155 final LayoutInflater inflater = 156 (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 157 View dialogView = inflater.inflate(R.layout.font_size_preference, parentView); 158 initInternalViews(dialogView); 159 mPreviewFontView.setTextSize(PREVIEW_FONT_SIZE_UNIT, 1); 160 } else { 161 mPreviewFontView.setTextSize(PREVIEW_FONT_SIZE_UNIT, pt); 162 } 163 mScrollingContainer.scrollTo(0, 0); 164 } 165 166 /** 167 * Resets the font indices to the default value. Does not update the mPreviewFontView text size. 168 */ resetSavedFontSizeToDefault()169 private void resetSavedFontSizeToDefault() { 170 mSavedFontIndex = DEFAULT_FONT_INDEX; 171 mPreviewFontIndex = mSavedFontIndex; 172 } 173 setButtonState(int index)174 private void setButtonState(int index) { 175 if (index == 0) { 176 mDecreaseFontButton.setEnabled(false); 177 } else if (index == mFontTwipValues.length - 1) { 178 mIncreaseFontButton.setEnabled(false); 179 } 180 } 181 182 /** 183 * Returns the name of the font size (ex: "Small") at the currently saved preference value. 184 */ getSavedFontSizeName()185 protected String getSavedFontSizeName() { 186 return mFontSizeNames[mSavedFontIndex]; 187 } 188 convertTwipStrToPT(String twip)189 private float convertTwipStrToPT(String twip) { 190 return Float.parseFloat(twip) / TWIP_TO_PT_RATIO; 191 } 192 } 193