1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/preferences/SearchEnginePreference.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,155 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +package org.mozilla.gecko.preferences; 1.9 + 1.10 +import org.json.JSONException; 1.11 +import org.json.JSONObject; 1.12 +import org.mozilla.gecko.R; 1.13 +import org.mozilla.gecko.favicons.Favicons; 1.14 +import org.mozilla.gecko.favicons.decoders.FaviconDecoder; 1.15 +import org.mozilla.gecko.util.ThreadUtils; 1.16 +import org.mozilla.gecko.widget.FaviconView; 1.17 + 1.18 +import android.app.AlertDialog; 1.19 +import android.content.Context; 1.20 +import android.graphics.Bitmap; 1.21 +import android.graphics.drawable.BitmapDrawable; 1.22 +import android.text.SpannableString; 1.23 +import android.util.Log; 1.24 +import android.view.View; 1.25 +import android.widget.Toast; 1.26 + 1.27 +/** 1.28 + * Represents an element in the list of search engines on the preferences menu. 1.29 + */ 1.30 +public class SearchEnginePreference extends CustomListPreference { 1.31 + protected String LOGTAG = "SearchEnginePreference"; 1.32 + 1.33 + protected static final int INDEX_REMOVE_BUTTON = 1; 1.34 + 1.35 + // The icon to display in the prompt when clicked. 1.36 + private BitmapDrawable mPromptIcon; 1.37 + 1.38 + // The bitmap backing the drawable above - needed separately for the FaviconView. 1.39 + private Bitmap mIconBitmap; 1.40 + 1.41 + private FaviconView mFaviconView; 1.42 + 1.43 + public SearchEnginePreference(Context context, SearchPreferenceCategory parentCategory) { 1.44 + super(context, parentCategory); 1.45 + } 1.46 + 1.47 + /** 1.48 + * Called by Android when we're bound to the custom view. Allows us to set the custom properties 1.49 + * of our custom view elements as we desire (We can now use findViewById on them). 1.50 + * 1.51 + * @param view The view instance for this Preference object. 1.52 + */ 1.53 + @Override 1.54 + protected void onBindView(View view) { 1.55 + super.onBindView(view); 1.56 + 1.57 + // Set the icon in the FaviconView. 1.58 + mFaviconView = ((FaviconView) view.findViewById(R.id.search_engine_icon)); 1.59 + mFaviconView.updateAndScaleImage(mIconBitmap, getTitle().toString()); 1.60 + } 1.61 + 1.62 + @Override 1.63 + protected int getPreferenceLayoutResource() { 1.64 + return R.layout.preference_search_engine; 1.65 + } 1.66 + 1.67 + /** 1.68 + * Returns the strings to be displayed in the dialog. 1.69 + */ 1.70 + @Override 1.71 + protected String[] createDialogItems() { 1.72 + return new String[] { LABEL_SET_AS_DEFAULT, 1.73 + LABEL_REMOVE }; 1.74 + } 1.75 + 1.76 + @Override 1.77 + public void showDialog() { 1.78 + // If this is the last engine, then we are the default, and none of the options 1.79 + // on this menu can do anything. 1.80 + if (mParentCategory.getPreferenceCount() == 1) { 1.81 + ThreadUtils.postToUiThread(new Runnable() { 1.82 + @Override 1.83 + public void run() { 1.84 + Toast.makeText(getContext(), R.string.pref_search_last_toast, Toast.LENGTH_SHORT).show(); 1.85 + } 1.86 + }); 1.87 + return; 1.88 + } 1.89 + 1.90 + super.showDialog(); 1.91 + } 1.92 + 1.93 + @Override 1.94 + protected void configureDialogBuilder(AlertDialog.Builder builder) { 1.95 + // Copy the icon from this object to the prompt we produce. We lazily create the drawable, 1.96 + // as the user may not ever actually tap this object. 1.97 + if (mPromptIcon == null && mIconBitmap != null) { 1.98 + mPromptIcon = new BitmapDrawable(getContext().getResources(), mFaviconView.getBitmap()); 1.99 + } 1.100 + 1.101 + builder.setIcon(mPromptIcon); 1.102 + } 1.103 + 1.104 + @Override 1.105 + protected void onDialogIndexClicked(int index) { 1.106 + switch (index) { 1.107 + case INDEX_SET_DEFAULT_BUTTON: 1.108 + mParentCategory.setDefault(this); 1.109 + break; 1.110 + 1.111 + case INDEX_REMOVE_BUTTON: 1.112 + mParentCategory.uninstall(this); 1.113 + break; 1.114 + 1.115 + default: 1.116 + Log.w(LOGTAG, "Selected index out of range."); 1.117 + break; 1.118 + } 1.119 + } 1.120 + 1.121 + /** 1.122 + * Configure this Preference object from the Gecko search engine JSON object. 1.123 + * @param geckoEngineJSON The Gecko-formatted JSON object representing the search engine. 1.124 + * @throws JSONException If the JSONObject is invalid. 1.125 + */ 1.126 + public void setSearchEngineFromJSON(JSONObject geckoEngineJSON) throws JSONException { 1.127 + final String engineName = geckoEngineJSON.getString("name"); 1.128 + final SpannableString titleSpannable = new SpannableString(engineName); 1.129 + 1.130 + setTitle(titleSpannable); 1.131 + 1.132 + final String iconURI = geckoEngineJSON.getString("iconURI"); 1.133 + // Keep a reference to the bitmap - we'll need it later in onBindView. 1.134 + try { 1.135 + final int desiredWidth; 1.136 + if (mFaviconView != null) { 1.137 + desiredWidth = mFaviconView.getWidth(); 1.138 + } else { 1.139 + // largestFaviconSize is initialized when Favicons is attached to a 1.140 + // context, which occurs during GeckoApp.onCreate. That might not 1.141 + // ever happen (leaving it at 0), so we fall back. 1.142 + if (Favicons.largestFaviconSize == 0) { 1.143 + desiredWidth = 128; 1.144 + } else { 1.145 + desiredWidth = Favicons.largestFaviconSize; 1.146 + } 1.147 + } 1.148 + 1.149 + // TODO: use the cache. Bug 961600. 1.150 + mIconBitmap = FaviconDecoder.getMostSuitableBitmapFromDataURI(iconURI, desiredWidth); 1.151 + 1.152 + } catch (IllegalArgumentException e) { 1.153 + Log.e(LOGTAG, "IllegalArgumentException creating Bitmap. Most likely a zero-length bitmap.", e); 1.154 + } catch (NullPointerException e) { 1.155 + Log.e(LOGTAG, "NullPointerException creating Bitmap. Most likely a zero-length bitmap.", e); 1.156 + } 1.157 + } 1.158 +}